Связь через последовательный порт (универсальный асинхронный приемник-передатчик UART, TTL) представляет собой последовательный полнодуплексный метод связи между устройствами. Поскольку UART является асинхронной передачей и не передает синхронные часы, для обеспечения точности данных UART использует тактовый сигнал, в 16 раз превышающий скорость передачи данных для выборки. Поскольку это просто и удобно, большинство электронного оборудования поддерживает этот метод связи. Инженеры часто используют этот метод для вывода отладочной информации при отладке оборудования. Подробности в этой статьепредставлять Как написать программу приемопередатчика последовательного порта,Мы используем часто используемую логику отправки и получения.,Отправьте непосредственно написанную функцию для реализации,Прием завершается с помощью прерываний. Прерывание приема использует два метода запуска прерывания при приеме байта и кадра данных.
USART имеет несколько событий запроса прерывания.
Причина, по которой это звание Прерывание Запрос USART вызван тем, что многие люди на начальном этапе не очень хорошо знают, как оценить статус прерывания последовательного порта, поэтому я сосредоточусь здесь на должности. Как правило, после того, как мы запустим и настроим прерывание последовательного порта, при входе в обработчик прерывания последовательного порта возникнет множество ситуаций. Мы также можем выбрать, какие ситуации прерывания последовательного порта открывать. В обычных обстоятельствах флаги событий прерывания, которые мы в основном используем при принятии, — это RXNE и IDLE. RXNE — это прерывание приема. Это прерывание запускается каждый раз при получении байта. Это также наиболее часто используемый запрос прерывания. IDLE Это прерывание по простою. Каждый раз, когда принимается кадр данных, шина временно простаивает, и срабатывает это прерывание.
Статус последовательного порта можно прочитать через регистр состояния USART_SR. Ребята из USART_SR описывают это следующим образом:
Здесь мы сосредоточимся на двух битах: битах 5 и 6 RXNE и TC. RXNE (регистр считанных данных не пуст), когда этот бит установлен в 1, это указывает, что данные получены и могут быть считаны. Что нам нужно сделать в этот момент, так это как можно скорее прочитать USART_DR. Читая USART_DR, этот бит можно очистить, или мы можем записать 0 в этот бит, чтобы очистить его напрямую. TC (передача завершена), когда этот бит установлен, это означает, что данные в USART_DR были отправлены. Если этот бит установлен, будет сгенерировано прерывание. Есть два способа очистить этот бит:
Этот проект в основном пишет трансивер последовательного порта. Использование STM32F103C8T6 в качестве MCU,Используйте помощник по отладке последовательного порта на ПК в качестве главного компьютера. Каждый раз, когда ПК отправляет кадр данных в MCU, Каждый раз, когда MCU получает байт данных, он проверяет, есть ли в данных команда 0x23. При получении команды 0x23 MCU отправляет «ПК» на главный компьютер. Когда получен один кадр данных, MCU отправляет «Receive a frame data”.
Общие этапы инициации постепенного порта можно резюмировать следующим образом:
#include "usart.h"
#include <stdio.h>
#include "stm32f1xx_hal.h
UART_HandleTypeDef huart3
void MX_USART3_UART_Init(void)
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler()
__HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);//получим разрешение прерывания
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);//Разрешение прерывания простоя
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART3)
{
__HAL_RCC_USART3_CLK_ENABLE()
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct)
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
Обычно нам нужно изменить некоторую конфигурацию параметров последовательного порта.
Отправка через последовательный порт Используемый здесь метод непрерывной отправки.
/*******************************************************************************
* @имя функции USART_Send
* @описание функции Отправить сообщение
* @входные параметры _UART: номер последовательного порта
данные: первый адрес информации, которая будет отправлена.
len: отправленная длина
* @выходной параметр никто
* @return параметры никто
*******************************************************************************/
void USART_Send(USART_TypeDef *_UART,uint8_t *data,uint8_t len)
{
for(int i;i<len;i++)
{
HAL_UART_Transmit(&huart3,&data[i],1,1000);
}
}
В основном используютсяHAL_UART_Transmit(&huart3,&Res,1,0Xffff); Это функция блокировки отправки, поэтому нет необходимости повторно определять, завершил ли последовательный порт отправку. Отправляйте каждый символ до тех пор, пока не встретите нулевой символ. Первый параметр — это номер последовательного порта, второй параметр — начальный адрес отправляемых данных, третий — длина отправляемых данных и четвертый — время ожидания (если передача не увенчалась успехом после этой длины). , блокировка завершена и прекращается. Отправлено, выполнение функции завершено).
Здесь Прием последовательного Порт использует метод прерывания. Категория прерывания уже упомянута в начале статьи. Мы устанавливаем тип прерывания, которое срабатывает при инициализации. установлено в этой статье
__HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);//получим разрешение прерывания
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);//Разрешение прерывания простоя
Это означает, что сработают только прерывания приема данных и простоя. В stm32f1xx_it.c есть функция обработки прерываний последовательного порта. Давайте проведем рефакторинг этой функции.
void USART3_IRQHandler(void)
{
uint8_t Res;
if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET
{
HAL_UART_Receive(&huart3,&Res,1,0Xffff);
if(Res==0x23)
printf("PC");
}
else if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET)//Прерывание ожидания (означает, что передача данных этого кадра завершена)
{
printf("Receive a frame data.");
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
}
Давайте рассмотрим ключевые моменты здесь один за другим. Первый — определить бит флага. Мы используем функцию __HAL_UART_GET_FLAG() в библиотеке HAL, которая имеет два параметра: первый — это дескриптор последовательного порта, а второй — конкретный бит флага. if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET)Используется для определения того, обнаружено ли однобайтовое прерывание.。 if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET) используется для определения наличия прерывания по простою (это означает, что передача данных этого кадра завершена).
Еще следует отметить, что для использования функций fput и fgetc для перенаправления функций ввода и вывода стандартной библиотеки языка C необходимо установить флажок «Использовать MicroLIB» в параметрах проекта MDK. MicroLIB является альтернативой библиотеке C по умолчанию. Стандартная библиотека C оптимизирована для использования меньшего количества кода и ресурсов. Чтобы использовать функции printf и scanf, вам необходимо включить в файл заголовочный файл stdio.h.
/**
* Функция функция: Перенаправить функцию библиотеки c printf
* Входные параметры: никто
* возвращаться раз ценить: никто
* объяснять яркий:никто
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* Функция функция: Перенаправить функции библиотеки C getchar, scanf
* Входные параметры: никто
* возвращаться раз ценить: никто
* объяснять яркий:никто
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart3, &ch, 1, 0xffff);
return ch;
}