微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > ARM技术讨论 > STM32的万能UART驱动,支持多种RTOS,多个UART口同时工作。

STM32的万能UART驱动,支持多种RTOS,多个UART口同时工作。

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

先是UART.h头文件的code

  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             0x80
  24. #define  UART_2STOP_EN            0x40
  25. #define  UART_EVEN_EN             0x20
  26. #define  UART_ODD_EN              0x10

  27. typedef struct{
  28.         u16 rxSize;
  29.         u16 txSize;       
  30.         u8* rxBuf;
  31.         u8* txBuf;
  32.         void (*isr)(uint8_t port,uint8_t event,void* msg);
  33.         void *msg;
  34.         USART_InitTypeDef init;
  35.         u8  rxdma;
  36.         u8  txdma;
  37. }uart_seting_t;

  38. /* Exported functions ------------------------------------------------------- */
  39. extern void UartNvicSet(uint8_t port,uint8_t preprio,uint8_t subprio);
  40. extern void USART_ISR(uint8_t port);
  41. extern void UartSeting(uint8_t port,uart_seting_t seting);
  42. extern uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len);
  43. extern uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len);
  44. extern uint16_t UartRxCnt(uint8_t port);
  45. extern uint16_t UartTxCnt(uint8_t port);
  46. extern void UartSetIsrMsg(uint8_t port,void* msg);
  47. #endif /* __USART_H */

  48. /******************* (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,uint8_t event,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,iflag;
  71.         uint8_t c,event = 0;
  72.         ie = __get_PRIMASK();
  73.         __set_PRIMASK(1);
  74.         iflag = (uart->CR1 & (USART_FLAG_TXE|USART_FLAG_TC|USART_FLAG_RXNE|USART_FLAG_IDLE) & uart->SR);
  75.         __set_PRIMASK(ie);
  76.         //IDLE IRQ
  77.         if(iflag & USART_FLAG_IDLE)
  78.         {
  79.                 c = uart->DR;
  80.                 if(pfifo->rxCnt <= (pfifo->rxSize>>1)) //rx buffer is not full when rx idle happen
  81.                 {
  82.                         event |=  UART_RX_IDLE;
  83.                 }
  84.         }
  85.         //RX IRQ
  86.         if(iflag & USART_FLAG_RXNE)
  87.         {
  88.                 c = uart->DR;
  89.                 if(pfifo->rxCnt < pfifo->rxSize)
  90.                 {
  91.                         pfifo->rxBuf[pfifo->rxPush] = c;
  92.                         pfifo->rxPush += 1;
  93.                         if(pfifo->rxPush >= pfifo->rxSize)
  94.                         {
  95.                                 pfifo->rxPush = 0;
  96.                         }
  97.                         pfifo->rxCnt += 1;
  98.                         if(pfifo->rxCnt == pfifo->rxSize)  //rx buffer is full
  99.                         {
  100.                                 event |= UART_RX_FULL;
  101.                         }
  102.                         else if(pfifo->rxCnt > (pfifo->rxSize>>1))//rx byte is more than half of rx buffer  
  103.                         {
  104.                                 event |= UART_RX_OVF;
  105.                         }
  106.                 }
  107.         }
  108.         //TXE IRQ
  109.         if(iflag & USART_FLAG_TXE)
  110.         {
  111.                 uart->CR1 &= (uint16_t)~0x0080; //off TX
  112.                 if(pfifo->txCnt)
  113.                 {
  114.                         c = pfifo->txBuf[pfifo->txPop];
  115.                         uart->DR = c;
  116.                         uart->CR1 |= (uint16_t)0x0080;
  117.                         pfifo->txPop += 1;
  118.                         if(pfifo->txPop >= pfifo->txSize)
  119.                         {
  120.                                 pfifo->txPop = 0;
  121.                         }
  122.                         pfifo->txCnt -= 1;
  123.                         if(pfifo->txCnt == 0)
  124.                         {
  125.                                 event |=  UART_TX_DONE;
  126.                         }
  127.                 }
  128.         }
  129.         //run isr function
  130.         if(NULL != pfifo->isr)
  131.         {
  132.                 pfifo->isr(port,event,pfifo->msg);
  133.         }
  134. }


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


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



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


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

  233. }

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



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


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

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


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

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

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


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



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

复制代码

好东西的,谢谢共享

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

网站地图

Top