微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 优化的UART驱动,可以适应多种RTOS,也能裸奔。

优化的UART驱动,可以适应多种RTOS,也能裸奔。

时间:10-02 整理:3721RD 点击:
该驱动采用中断方式,未来会加入DMA方式。中断方式采用FIFO的方式。用户程序直接用UartRead和UartWrite操作读写。
无论采用中断还是DMA,都会支持一个中断回调函数。该中断回调函数处理由用户自己定义,触发条件为——接收缓冲超时(1Byte的时间),接收缓冲过半,接收缓冲满,发送缓冲空,以应对UART在某些场合对实时性的需求。
同时为了支持多种OS环境(本人移植过UCOS和RTX两种OS),也可以裸奔,UART驱动中不会有任何和特定OS相关的操作,所以中断回调函数中可以向任务中发送信号量,消息邮箱等。同时任务在初始化UART时,可以分配一个缓冲供中断回调函数操作。比如中断回调函数向任务中发送一个消息邮箱,消息邮箱的缓冲可以建立在任务中,初始化串口的时候分配给串口驱动,当串口中断发生时直接把该缓冲区的指针发给任务,如果中断发送给任务的消息邮箱,指针位于中断函数的局部变量,当中断函数结束时,任务还没有收到消息邮箱,邮箱里面的“邮件”就变成了“空白”。
UART.h

  1. /******************** (C) COPYRIGHT 2008 boost ********************
  2. * File Name          : usart.h
  3. * Author             : Luo Yiming
  4. * Version            : V1.1.0
  5. * Date               : 2013年3月19日
  6. * Description        : Header for usart.c module
  7. ********************************************************************************/

  8. /* Includes ------------------------------------------------------------------*/
  9. #include "stm32f10x.h"

  10. /* Define to prevent recursive inclusion ------------------------------------ */
  11. #ifndef __USART_H
  12. #define __USART_H

  13. #define UART_RX_IDLE  0x01           // Uart Rx Buffer is less than half when idle
  14. #define UART_RX_OVF   0x02           // Uart Rx Buffer is more than half
  15. #define UART_RX_FULL  0x04           // Uart Rx Buffer is full
  16. #define UART_TX_DONE  0x08           // Uart Tx Buffer is empty

  17. #define  UART_PORT_MAX            5

  18. #define  UART_PORT_1              0
  19. #define  UART_PORT_2              1
  20. #define  UART_PORT_3              2
  21. #define  UART_PORT_4              3
  22. #define  UART_PORT_5              4

  23. #define  UART_FLOW_EN             0x0080
  24. #define  UART_2STOP_EN            0x0040
  25. #define  UART_EVEN_EN             0x0020
  26. #define  UART_ODD_EN              0x0010

  27. typedef struct{
  28.         u16 event;
  29.         u8  rxCh;
  30.         u8  txCh;
  31. }uart_status_t;

  32. typedef struct{
  33.         u16 rxSize;
  34.         u16 txSize;       
  35.         u8* rxBuf;
  36.         u8* txBuf;
  37.         void (*isr)(uint8_t port,uart_status_t status,void* msg);
  38.         void *msg;
  39.         USART_InitTypeDef init;
  40.         u8  rxdma;
  41.         u8  txdma;
  42. }uart_seting_t;

  43. /* Exported functions ------------------------------------------------------- */
  44. extern void UartNvicSet(uint8_t port,uint8_t preprio,uint8_t subprio);
  45. extern void USART_ISR(uint8_t port);
  46. extern void UartSeting(uint8_t port,uart_seting_t seting);
  47. extern uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len);
  48. extern uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len);
  49. extern uint16_t UartRxCnt(uint8_t port);
  50. extern uint16_t UartTxCnt(uint8_t port);
  51. extern void UartSetIsrMsg(uint8_t port,void* msg);
  52. #endif /* __USART_H */

  53. /******************* (C) COPYRIGHT 2008 boost *****END OF FILE****/

复制代码

UART .C

  1. /******************** (C) COPYRIGHT 2008 litt ********************
  2. * File Name          : usart.c
  3. * Author             : luo yi ming
  4. * Version            : V1.1.0
  5. * Date               : 2013年3月19日
  6. * Description        : This file provides a set of functions needed to manage the
  7. *                      communication between usart peripheral and RS485/HW/PLC.
  8. ********************************************************************************/

  9. /* Includes ------------------------------------------------------------------*/
  10. #include "usart.h"



  11. /* Private typedef -----------------------------------------------------------*/
  12. struct _uart_fifo_t{
  13.         //rx 12byte
  14.         u8*   rxBuf;             //4
  15.         u16   rxSize;            //2
  16.         vu16  rxPush;   //2
  17.         vu16  rxPop;    //2
  18.         vu16  rxCnt;    //2
  19.         //tx 12byte
  20.         u8*   txBuf;             //4
  21.         u16   txSize;            //2
  22.         vu16  txPush;   //2
  23.         vu16  txPop;    //2
  24.         vu16  txCnt;    //2
  25.         //Isr 4byte
  26.         void (*isr)(uint8_t port,uart_status_t status,void* msg);
  27.         //task msg to isr
  28.         void* msg;
  29. };//28


  30. struct _uart_device_t{
  31.         struct _uart_fifo_t  fifo;
  32.         USART_TypeDef*   uart;
  33.         DMA_Channel_TypeDef*     rxdma;
  34.         DMA_Channel_TypeDef*     txdma;
  35. };


  36. typedef   USART_TypeDef*        pUSART_TypeDef;
  37. typedef   DMA_Channel_TypeDef*  pDMA_Channel_TypeDef;
  38. /* Private define ------------------------------------------------------------*/
  39. //#define  UART_OVF_LINE     16
  40. //#define  UART_MIN_FIFO     16
  41. //#define  UART_MAX_FIFO     2048

  42. #define  UART1_DMA_RX  DMA1_Channel5
  43. #define  UART1_DMA_TX  DMA1_Channel4

  44. #define  UART2_DMA_RX  DMA1_Channel6
  45. #define  UART2_DMA_TX  DMA1_Channel7

  46. #define  UART3_DMA_RX  DMA1_Channel3
  47. #define  UART3_DMA_TX  DMA1_Channel2

  48. #define  UART_REG_1 {USART1,UART1_DMA_RX,UART1_DMA_TX}
  49. #define  UART_REG_2 {USART2,UART2_DMA_RX,UART2_DMA_TX}
  50. #define  UART_REG_3 {USART3,UART3_DMA_RX,UART3_DMA_TX}
  51. #define  UART_REG_4 {UART4,NULL,NULL}
  52. #define  UART_REG_5 {UART5,NULL,NULL}

  53. /* Private macro -------------------------------------------------------------*/


  54. /* Private variables ---------------------------------------------------------*/
  55. const  pUSART_TypeDef         USART_TABLE[UART_PORT_MAX] = {USART1,USART2,USART3,UART4,UART5};
  56. const  pDMA_Channel_TypeDef          UART_DMA_RX_TABLE[UART_PORT_MAX] = {UART1_DMA_RX,UART2_DMA_RX,UART3_DMA_RX,NULL,NULL};
  57. const  pDMA_Channel_TypeDef          UART_DMA_TX_TABLE[UART_PORT_MAX] = {UART1_DMA_TX,UART2_DMA_TX,UART3_DMA_TX,NULL,NULL};
  58. static struct _uart_device_t  UartDevice[UART_PORT_MAX];


  59. /* Function -------------------------------------------------------------------*/

  60. /*************************************************************************************************
  61. * Name       : _uart_isr
  62. * Describe   : 串口中断服务程序
  63. * param      : pfifo,uart
  64. * Return     : 无
  65. * Create by  : 罗一鸣 2012-12-03
  66. * Moid   by  :
  67. *************************************************************************************************/
  68. static __inline void _uart_isr(uint8_t port,struct _uart_fifo_t *pfifo,USART_TypeDef *uart)
  69. {
  70.         //uint32_t ie;
  71.         uint32_t iflag;
  72.         uart_status_t status = {0,0,0};
  73.         //ie = __get_PRIMASK();
  74.         //__set_PRIMASK(1);
  75.         iflag = (uart->CR1 & uart->SR);//(USART_FLAG_TXE|USART_FLAG_TC|USART_FLAG_RXNE|USART_FLAG_IDLE)
  76.         //__set_PRIMASK(ie);
  77.         //IDLE IRQ
  78.         if(iflag & USART_FLAG_IDLE)
  79.         {
  80.                 status.rxCh = uart->DR;
  81.                 if(pfifo->rxCnt <= (pfifo->rxSize>>1)) //rx buffer is not full when rx idle happen
  82.                 {
  83.                         status.event |=  UART_RX_IDLE;
  84.                 }
  85.         }
  86.         //RX IRQ
  87.         if(iflag & USART_FLAG_RXNE)
  88.         {
  89.                 status.rxCh = uart->DR;
  90.                 if(pfifo->rxCnt < pfifo->rxSize)
  91.                 {
  92.                         pfifo->rxBuf[pfifo->rxPush] = status.rxCh;
  93.                         pfifo->rxPush += 1;
  94.                         if(pfifo->rxPush >= pfifo->rxSize)
  95.                         {
  96.                                 pfifo->rxPush = 0;
  97.                         }
  98.                         pfifo->rxCnt += 1;
  99.                         if(pfifo->rxCnt == pfifo->rxSize)  //rx buffer is full
  100.                         {
  101.                                 status.event |= UART_RX_FULL;
  102.                         }
  103.                         else if(pfifo->rxCnt > (pfifo->rxSize>>1))//rx byte is more than half of rx buffer  
  104.                         {
  105.                                 status.event |= UART_RX_OVF;
  106.                         }
  107.                 }
  108.         }
  109.         //TXE IRQ
  110.         if(iflag & USART_FLAG_TXE)
  111.         {
  112.                 uart->CR1 &= (uint16_t)~0x0080; //off TX
  113.                 if(pfifo->txCnt)
  114.                 {
  115.                         status.txCh = pfifo->txBuf[pfifo->txPop];
  116.                         uart->DR = status.txCh;
  117.                         uart->CR1 |= (uint16_t)0x0080;
  118.                         pfifo->txPop += 1;
  119.                         if(pfifo->txPop >= pfifo->txSize)
  120.                         {
  121.                                 pfifo->txPop = 0;
  122.                         }
  123.                         pfifo->txCnt -= 1;
  124.                         if(pfifo->txCnt == 0)
  125.                         {
  126.                                 status.event |=  UART_TX_DONE;
  127.                         }
  128.                 }
  129.         }
  130.         //run isr function
  131.         if((NULL != pfifo->isr) && (0 != status.event))
  132.         {
  133.                 pfifo->isr(port,status,pfifo->msg);
  134.         }
  135. }


  136. /*************************************************************************************************
  137. * Name       : _uart_read_isr
  138. * Describe   : 串口读取函数中断模式
  139. * param      :
  140. * Return     :
  141. * Create by  :
  142. * Moid   by  :
  143. *************************************************************************************************/
  144. static uint16_t _uart_read_isr(struct _uart_fifo_t *pfifo,USART_TypeDef *uart,uint8_t *data,uint16_t len)
  145. {
  146.         uint32_t ie;
  147.         uint16_t n;
  148.         if(len == 0)
  149.         {
  150.                 return 0;
  151.         }
  152.         for(n=0;n<len;n++)
  153.         {
  154.                 if(n < pfifo->rxCnt)
  155.                 {
  156.                         *data++ = pfifo->rxBuf[pfifo->rxPop];
  157.                         pfifo->rxPop += 1;
  158.                         if(pfifo->rxPop>=pfifo->rxSize)
  159.                         {
  160.                                 pfifo->rxPop = 0;
  161.                         }
  162.                 }
  163.                 else
  164.                 {
  165.                         break;
  166.                 }
  167.         }
  168.         ie = __get_PRIMASK();
  169.         __set_PRIMASK(1);
  170.         pfifo->rxCnt -= n;
  171.         __set_PRIMASK(ie);
  172.         return n;
  173. }


  174. /*************************************************************************************************
  175. * Name       : _uart_write_isr
  176. * Describe   : 串口写入函数中断模式
  177. * param      :
  178. * Return     :
  179. * Create by  :
  180. * Moid   by  :
  181. *************************************************************************************************/
  182. static uint16_t _uart_write_isr(struct _uart_fifo_t *pfifo,USART_TypeDef *uart,uint8_t *data,uint16_t len)
  183. {
  184.         uint32_t ie;
  185.         uint16_t n;
  186.         if(len == 0)
  187.         {
  188.                 return 0;
  189.         }
  190.         for(n=0;n<len;n++)
  191.         {
  192.                 if((pfifo->txSize-n) > pfifo->txCnt)
  193.                 {
  194.                         pfifo->txBuf[pfifo->txPush] = *data++;
  195.                         pfifo->txPush += 1;
  196.                         if(pfifo->txPush >= pfifo->txSize)
  197.                         {
  198.                                 pfifo->txPush = 0;
  199.                         }
  200.                 }
  201.                 else
  202.                 {
  203.                         break;
  204.                 }
  205.         }
  206.         ie = __get_PRIMASK();
  207.         __set_PRIMASK(1);
  208.         pfifo->txCnt += n;
  209.         __set_PRIMASK(ie);
  210.         return n;
  211. }



  212. /*************************************************************************************************
  213. * Name       : UART_ISR
  214. * Describe   : 串口中断服务
  215. * param      :
  216. * Return     :
  217. * Create by  :
  218. * Moid   by  :
  219. *************************************************************************************************/
  220. void USART_ISR(uint8_t port)
  221. {
  222.         _uart_isr(port,&UartDevice[port].fifo,UartDevice[port].uart);
  223. }


  224. /*************************************************************************************************
  225. * Name       : UART_DMA_ISR
  226. * Describe   : 串口中断服务
  227. * param      :
  228. * Return     :
  229. * Create by  :
  230. * Moid   by  :
  231. *************************************************************************************************/
  232. void UART_DMA_ISR(uint8_t port)
  233. {

  234. }

  235. /*
  236. __inline void UartDmaIsr(uint8_t port,struct UartFifo *pfifo,USART_TypeDef *uart)
  237. {
  238.        
  239.        
  240. }
  241. */



  242. /*************************************************************************************************
  243. * Name       : UartSeting
  244. * Describe   :  
  245. * param      :  
  246. * Return     :  
  247. * Create by  : 罗一鸣    Date: 2013-06-18
  248. * Moid   by  :
  249. *************************************************************************************************/
  250. void UartSeting(uint8_t port,uart_seting_t seting)
  251. {
  252.         UartDevice[port].uart  = USART_TABLE[port];
  253.         UartDevice[port].rxdma = NULL;
  254.         UartDevice[port].txdma = NULL;
  255.         UartDevice[port].fifo.rxCnt  = UartDevice[port].fifo.txCnt  = 0;
  256.         UartDevice[port].fifo.rxPush = UartDevice[port].fifo.rxPop  = 0;       
  257.         UartDevice[port].fifo.txPush = UartDevice[port].fifo.txPop  = 0;
  258.         UartDevice[port].fifo.rxSize = seting.rxSize;
  259.         UartDevice[port].fifo.rxBuf  = seting.rxBuf;
  260.         UartDevice[port].fifo.txSize = seting.txSize;
  261.         UartDevice[port].fifo.txBuf  = seting.txBuf;
  262.         UartDevice[port].fifo.isr    = seting.isr;
  263.         UartDevice[port].fifo.msg         = seting.msg;
  264.         if(seting.rxdma)
  265.         {
  266.                 UartDevice[port].rxdma = UART_DMA_RX_TABLE[port];
  267.         }
  268.         if(seting.txdma)
  269.         {
  270.                 UartDevice[port].txdma = UART_DMA_TX_TABLE[port];
  271.         }
  272.         USART_Init(UartDevice[port].uart, &seting.init);
  273. }


  274. /*************************************************************************************************
  275. * Name       : UartRead
  276. * Describe   :  
  277. * param      :  
  278. * Return     :  
  279. * Create by  : 罗一鸣    Date: 2012-12-03
  280. * Moid   by  :
  281. *************************************************************************************************/
  282. uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len)
  283. {
  284.         if(UART_PORT_MAX <= port)
  285.         {
  286.                 return 0;
  287.         }
  288.         if((NULL != UartDevice[port].rxdma))
  289.         {
  290.                 return 0;
  291.         }
  292.         else
  293.         {
  294.                 return _uart_read_isr(&UartDevice[port].fifo,UartDevice[port].uart,data,len);
  295.         }
  296. }

  297. /*************************************************************************************************
  298. * Name       : UartWrite
  299. * Describe   :  
  300. * param      :  
  301. * Return     :  
  302. * Create by  : 罗一鸣    Date: 2012-12-03
  303. * Moid   by  :
  304. *************************************************************************************************/
  305. uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len)
  306. {
  307.         if(UART_PORT_MAX <= port)
  308.         {
  309.                 return 0;
  310.         }
  311.         if((NULL != UartDevice[port].txdma))
  312.         {
  313.                 return 0;
  314.         }
  315.         else
  316.         {
  317.                 return _uart_write_isr(&UartDevice[port].fifo,UartDevice[port].uart,data,len);
  318.         }
  319. }


  320. /*************************************************************************************************
  321. * Name       : UartRxCnt
  322. * Describe   :
  323. * param      :
  324. * Return     :
  325. * Create by  :
  326. * Moid   by  :
  327. *************************************************************************************************/
  328. uint16_t UartRxCnt(uint8_t port)
  329. {
  330.         return UartDevice[port].fifo.rxCnt;
  331. }

  332. /*************************************************************************************************
  333. * Name       : UartTxCnt
  334. * Describe   :
  335. * param      :
  336. * Return     :
  337. * Create by  :
  338. * Moid   by  :
  339. *************************************************************************************************/
  340. uint16_t UartTxCnt(uint8_t port)
  341. {
  342.         return UartDevice[port].fifo.txCnt;
  343. }

  344. /*************************************************************************************************
  345. * Name       : UartSetIsrMsg
  346. * Describe   : send msg to Isr
  347. * param      :  
  348. * Return     :  
  349. * Create by  : 罗一鸣    Date: 2013-06-18
  350. * Moid   by  :
  351. *************************************************************************************************/
  352. void UartSetIsrMsg(uint8_t port,void* msg)
  353. {
  354.         UartDevice[port].fifo.msg = msg;
  355. }


  356. /*************************************************************************************************
  357. * Name       : UartInit
  358. * Describe   :  
  359. * param      :  
  360. * Return     :  
  361. * Create by  : 罗一鸣    Date: 2012-12-03
  362. * Moid   by  :
  363. *************************************************************************************************/
  364. void UartInit(uint8_t port,uint8_t preprio,uint8_t subprio)
  365. {
  366.         NVIC_InitTypeDef NVIC_InitStructure;
  367.         GPIO_InitTypeDef GPIO_InitStructure;
  368.         if(UART_PORT_1 == port)
  369.         {               
  370.                 // config USART1 clock
  371.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
  372.                 // Configure USART1 Tx (PA.09) as alternate function push-pull
  373.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  374.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  375.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  376.                 GPIO_Init(GPIOA, &GPIO_InitStructure);
  377.                 // Configure USART1 Rx (PA.10) as input floating
  378.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  379.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  380.                 GPIO_Init(GPIOA, &GPIO_InitStructure);
  381.                 // Set Interrupt Priority
  382.             NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  383.             NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
  384.             NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
  385.             NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  386.                 //CLI();
  387.                 NVIC_Init(&NVIC_InitStructure);
  388.                 //SEI();
  389.         }
  390.         else if(UART_PORT_2 == port)
  391.         {
  392.                 // config USART2 clock
  393.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  394.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  395.                 // Configure USART2 Tx (PA.02) as alternate function push-pull
  396.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  397.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  398.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  399.                 GPIO_Init(GPIOA, &GPIO_InitStructure);
  400.                 // Configure USART2 Rx (PA.03) as input floating
  401.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  402.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  403.                 GPIO_Init(GPIOA, &GPIO_InitStructure);               
  404.                 // Set Interrupt Priority
  405.             NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  406.             NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
  407.             NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
  408.             NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  409.                 //CLI();
  410.                 NVIC_Init(&NVIC_InitStructure);
  411.                 //SEI();
  412.         }
  413.         else if(UART_PORT_3 == port)
  414.         {
  415.                 // config USART3 clock
  416.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  417.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
  418.                 // Configure USART2 Tx (PB.10) as alternate function push-pull
  419.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  420.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  421.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  422.                 GPIO_Init(GPIOB, &GPIO_InitStructure);
  423.                 // Configure USART2 Rx (PB.11) as input floating
  424.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  425.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  426.                 GPIO_Init(GPIOB, &GPIO_InitStructure);
  427.                 // Set Interrupt Priority
  428.             NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  429.             NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
  430.             NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
  431.             NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  432.                 //CLI();
  433.                 NVIC_Init(&NVIC_InitStructure);
  434.                 //SEI();
  435.         }
  436. }



  437. /****************************************************************************
  438. *************************** End of File *************************************
  439. ****************************************************************************/

复制代码

牛,我还处于裸奔组合的年代

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top