串口数据处理比较频繁时,不用RTOS处理数据容易丢包。
串口数据处理可以用FreeRTOS进行管理,用于支持串口的CMD指令收发。
除了串口任务的创建,定时器创建外,单纯串口数据处理需要进行下面几个步骤。
1 串口初始化与参数初始化
定义串口数据机构体
#define SH _BUFSIZE 512
#define UART_BUFSIZE 1024
typedef struct UART_Buffer
{
/* @brief Receive buffer. */
volatile uint8_t RX[SH _BUFSIZE];
/* @brief Transmit buffer. */
volatile uint8_t TX[2];
/* @brief Receive buffer head. */
volatile uint16_t RX_Head;
/* @brief Receive buffer tail. */
volatile uint16_t RX_Tail;
/* @brief Transmit buffer head. */
volatile uint16_t TX_Head;
/* @brief Transmit buffer tail. */
volatile uint16_t TX_Tail;
/* @brief RX buffer counting semaphore */
volatile xQueueHandle RXBuf_Sem;
/* @brief TX buffer counting semaphore*/
volatile xQueueHandle TXBuf_Sem;
} uart_Buffer_t;
static uart_Buffer_t SH_Uart_Buf;
配置串口1
void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure; //定义串口初始化结构
/* 开启GPIO_A USART1的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
/*USART1_RX ->PA10*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*USART1_TX ->PA9*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
/*串口通讯参数设置*/
USART_InitStructure.USART_BaudRate = 115200; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位
USART_InitStructure.USART_Parity = USART_Parity_No; //校验位 无
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //使能接收和发送引脚
USART_Init(USART1, &USART_InitStructure);
USART_ClearFlag(USART1,USART_FLAG_TC);
USART_Cmd(USART1, ENABLE);//开启USART1,注意与上面RCC_APB2PeriphClockCmd()设置的区别
}
初始化串口1 buffer
void uart1_init(void)
{
/* Init Ring Buffer */
SH_Uart_Buf.RX_Tail = 0;
SH_Uart_Buf.RX_Head = 0;
SH_Uart_Buf.TX_Tail = 0;
SH_Uart_Buf.TX_Head = 0;
vSemaphoreCreateBinary(SH_Uart_Buf.RXBuf_Sem);
SH_Uart_Buf.TXBuf_Sem = NULL ;
/* Enable receive interrupt */
USART_ITConfig (USART1, USART_IT_RXNE, ENABLE );
USART_ITConfig(USART1, USART_IT_TXE, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_TC, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_IDLE, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_LBD, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_CTS, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_ERR, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_ORE, DISABLE ) ;
USART_ITConfig(USART1, USART_IT_FE, DISABLE ) ;
/* Enable */
USART_Cmd(USART1, ENABLE);
}
2 串口中断数据处理
void USART1_IRQHandler(void) {
SH_IRQHandler();
}
void SH _IRQHandler(void) {
static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
USART_TypeDef *USART_ID = USART1 ;
SHELL_Buffer_t *pUSART_Buf = & SH_Uart_Buf ;
unsigned long uxSavedStatusValue ;
uxSavedStatusValue = portSET_INTERRUPT_MASK_FROM_ISR() ;
if(USART_GetITStatus(USART_ID, USART_IT_RXNE) != RESET)
{
/* Advance buffer head. */
uint16_t tempRX_Head = (pUSART_Buf->RX_Head + 1) & (SH _BUFSIZE -1);
/* Check for overflow. */
uint16_t tempRX_Tail = pUSART_Buf->RX_Tail;
uint8_t data = USART_ReceiveData(USART_ID);
if (tempRX_Head == tempRX_Tail) {
USART_ITConfig(USART_ID, USART_IT_RXNE, DISABLE);
}else{
pUSART_Buf->RX[pUSART_Buf->RX_Head] = data;
pUSART_Buf->RX_Head = tempRX_Head;
USART_ClearITPendingBit(USART_ID, USART_IT_RXNE) ;
if(pUSART_Buf->RXBuf_Sem != NULL) {
xSemaphoreGive(pUSART_Buf->RXBuf_Sem);
}
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
}
if(USART_GetITStatus(USART_ID, USART_IT_TXE) != RESET)
{
/* Check if all data is transmitted. */
uint16_t tempTX_Tail = (pUSART_Buf)->TX_Tail;
if (pUSART_Buf->TX_Head == tempTX_Tail){
/* Overflow MAX size Situation */
/* Disable the USART Transmit interrupt */
USART_ITConfig(USART_ID, USART_IT_TXE, DISABLE);
}else{
uint8_t data = pUSART_Buf->TX[pUSART_Buf->TX_Tail];
USART_ID->DR = data;
USART_ClearITPendingBit(USART_ID, USART_IT_RXNE) ;
(pUSART_Buf)->TX_Tail = (pUSART_Buf->TX_Tail + 1) & (UART_BUFSIZE-1);
if (pUSART_Buf->TXBuf_Sem != NULL)
xSemaphoreGiveFromISR( pUSART_Buf->TXBuf_Sem, &xHigherPriorityTaskWoken );
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue);
}
3 某一个任务重处理接收数据:
uint8_t debug_uart_getch(uint32_t timeout_ms)
{
SHELL_Buffer_t *pUSART_Buf;
USART_TypeDef* UART;
uint8_t ans ;
pUSART_Buf = & SH_Uart_Buf;
UART = USART1;
#if (UART_HANDLING == UART_INTERRUPT_MODE)
vPortEnterCritical() ;
if( pUSART_Buf->RX_Head == pUSART_Buf->RX_Tail)
{
vPortExitCritical() ;
if (pUSART_Buf->RXBuf_Sem != NULL)
xSemaphoreTake(pUSART_Buf->RXBuf_Sem, timeout_ms);
return 0;
}
ans = (pUSART_Buf->RX[pUSART_Buf->RX_Tail]);
pUSART_Buf->RX_Tail = (pUSART_Buf->RX_Tail + 1) & (SH _BUFSIZE -1);
vPortExitCritical() ;
USART_ITConfig(UART, USART_IT_RXNE, ENABLE);
return ans ;
#else
while (!(UART->SR & USART_FLAG_RXNE));
return (uint8_t)(UART->DR);
#endif
}
void vSHTaskHandler(void *params)
{
uint8_t c;
USART1_Config()
uart_init();
vTaskDelay(10);
while (1) {
c = uart1_getch(1000 / portTICK_RATE_MS);
if (c != 0x0) {
处理数据环节;
……
}
}
4 发送数据(略)