STM32F407之基于FreeRTOS的串口数据处理

串口数据处理比较频繁时,不用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 发送数据(略)

上一篇:IO控制方式


下一篇:STM32F1串口使用DMA实现数据回传