该驱动采用中断方式,未来会加入DMA方式。中断方式采用FIFO的方式。用户程序直接用UartRead和UartWrite操作读写。
无论采用中断还是DMA,都会支持一个中断回调函数。该中断回调函数处理由用户自己定义,触发条件为——接收缓冲超时(1Byte的时间),接收缓冲过半,接收缓冲满,发送缓冲空,以应对UART在某些场合对实时性的需求。
同时为了支持多种OS环境(本人移植过UCOS和RTX两种OS),也可以裸奔,UART驱动中不会有任何和特定OS相关的操作,所以中断回调函数中可以向任务中发送信号量,消息邮箱等。同时任务在初始化UART时,可以分配一个缓冲供中断回调函数操作。比如中断回调函数向任务中发送一个消息邮箱,消息邮箱的缓冲可以建立在任务中,初始化串口的时候分配给串口驱动,当串口中断发生时直接把该缓冲区的指针发给任务,如果中断发送给任务的消息邮箱,指针位于中断函数的局部变量,当中断函数结束时,任务还没有收到消息邮箱,邮箱里面的“邮件”就变成了“空白”。而用我的驱动就完全可以避免中断发送的消息邮箱无效的情况。
先是UART.h头文件的code
- /******************** (C) COPYRIGHT 2008 boost ********************
- * File Name : usart.h
- * Author : Luo Yiming
- * Version : V1.1.0
- * Date : 2013年3月19日
- * Description : Header for usart.c module
- ********************************************************************************/
- /* Includes ------------------------------------------------------------------*/
- #include "STM32f10x.h"
- /* Define to prevent recursive inclusion ------------------------------------ */
- #ifndef __USART_H
- #define __USART_H
- #define UART_RX_IDLE 0x01 // Uart Rx Buffer is less than half when idle
- #define UART_RX_OVF 0x02 // Uart Rx Buffer is more than half
- #define UART_RX_FULL 0x04 // Uart Rx Buffer is full
- #define UART_TX_DONE 0x08 // Uart Tx Buffer is empty
- #define UART_PORT_MAX 5
- #define UART_PORT_1 0
- #define UART_PORT_2 1
- #define UART_PORT_3 2
- #define UART_PORT_4 3
- #define UART_PORT_5 4
- #define UART_FLOW_EN 0x80
- #define UART_2STOP_EN 0x40
- #define UART_EVEN_EN 0x20
- #define UART_ODD_EN 0x10
- typedef struct{
- u16 rxSize;
- u16 txSize;
- u8* rxBuf;
- u8* txBuf;
- void (*isr)(uint8_t port,uint8_t event,void* msg);
- void *msg;
- USART_InitTypeDef init;
- u8 rxdma;
- u8 txdma;
- }uart_seting_t;
- /* Exported functions ------------------------------------------------------- */
- extern void UartNvicSet(uint8_t port,uint8_t preprio,uint8_t subprio);
- extern void USART_ISR(uint8_t port);
- extern void UartSeting(uint8_t port,uart_seting_t seting);
- extern uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len);
- extern uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len);
- extern uint16_t UartRxCnt(uint8_t port);
- extern uint16_t UartTxCnt(uint8_t port);
- extern void UartSetIsrMsg(uint8_t port,void* msg);
- #endif /* __USART_H */
- /******************* (C) COPYRIGHT 2008 boost *****END OF FILE****/
复制代码
还有UART.c,这才是关键。
- /******************** (C) COPYRIGHT 2008 litt ********************
- * File Name : usart.c
- * Author : luo yi ming
- * Version : V1.1.0
- * Date : 2013年3月19日
- * Description : This file provides a set of functions needed to manage the
- * communication between usart peripheral and RS485/HW/PLC.
- ********************************************************************************/
- /* Includes ------------------------------------------------------------------*/
- #include "usart.h"
- /* Private typedef -----------------------------------------------------------*/
- struct _uart_fifo_t{
- //rx 12byte
- u8* rxBuf; //4
- u16 rxSize; //2
- vu16 rxPush; //2
- vu16 rxPop; //2
- vu16 rxCnt; //2
- //tx 12byte
- u8* txBuf; //4
- u16 txSize; //2
- vu16 txPush; //2
- vu16 txPop; //2
- vu16 txCnt; //2
- //Isr 4byte
- void (*isr)(uint8_t port,uint8_t event,void* msg);
- //task msg to isr
- void* msg;
- };//28
- struct _uart_device_t{
- struct _uart_fifo_t fifo;
- USART_TypeDef* uart;
- DMA_Channel_TypeDef* rxdma;
- DMA_Channel_TypeDef* txdma;
- };
- typedef USART_TypeDef* pUSART_TypeDef;
- typedef DMA_Channel_TypeDef* pDMA_Channel_TypeDef;
- /* Private define ------------------------------------------------------------*/
- //#define UART_OVF_LINE 16
- //#define UART_MIN_FIFO 16
- //#define UART_MAX_FIFO 2048
- #define UART1_DMA_RX DMA1_Channel5
- #define UART1_DMA_TX DMA1_Channel4
- #define UART2_DMA_RX DMA1_Channel6
- #define UART2_DMA_TX DMA1_Channel7
- #define UART3_DMA_RX DMA1_Channel3
- #define UART3_DMA_TX DMA1_Channel2
- #define UART_REG_1 {USART1,UART1_DMA_RX,UART1_DMA_TX}
- #define UART_REG_2 {USART2,UART2_DMA_RX,UART2_DMA_TX}
- #define UART_REG_3 {USART3,UART3_DMA_RX,UART3_DMA_TX}
- #define UART_REG_4 {UART4,NULL,NULL}
- #define UART_REG_5 {UART5,NULL,NULL}
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- const pUSART_TypeDef USART_TABLE[UART_PORT_MAX] = {USART1,USART2,USART3,UART4,UART5};
- const pDMA_Channel_TypeDef UART_DMA_RX_TABLE[UART_PORT_MAX] = {UART1_DMA_RX,UART2_DMA_RX,UART3_DMA_RX,NULL,NULL};
- const pDMA_Channel_TypeDef UART_DMA_TX_TABLE[UART_PORT_MAX] = {UART1_DMA_TX,UART2_DMA_TX,UART3_DMA_TX,NULL,NULL};
- static struct _uart_device_t UartDevice[UART_PORT_MAX];
- /* Function -------------------------------------------------------------------*/
- /*************************************************************************************************
- * Name : _uart_isr
- * Describe : 串口中断服务程序
- * param : pfifo,uart
- * Return : 无
- * Create by : 罗一鸣 2012-12-03
- * Moid by :
- *************************************************************************************************/
- static __inline void _uart_isr(uint8_t port,struct _uart_fifo_t *pfifo,USART_TypeDef *uart)
- {
- uint32_t ie,iflag;
- uint8_t c,event = 0;
- ie = __get_PRIMASK();
- __set_PRIMASK(1);
- iflag = (uart->CR1 & (USART_FLAG_TXE|USART_FLAG_TC|USART_FLAG_RXNE|USART_FLAG_IDLE) & uart->SR);
- __set_PRIMASK(ie);
- //IDLE IRQ
- if(iflag & USART_FLAG_IDLE)
- {
- c = uart->DR;
- if(pfifo->rxCnt <= (pfifo->rxSize>>1)) //rx buffer is not full when rx idle happen
- {
- event |= UART_RX_IDLE;
- }
- }
- //RX IRQ
- if(iflag & USART_FLAG_RXNE)
- {
- c = uart->DR;
- if(pfifo->rxCnt < pfifo->rxSize)
- {
- pfifo->rxBuf[pfifo->rxPush] = c;
- pfifo->rxPush += 1;
- if(pfifo->rxPush >= pfifo->rxSize)
- {
- pfifo->rxPush = 0;
- }
- pfifo->rxCnt += 1;
- if(pfifo->rxCnt == pfifo->rxSize) //rx buffer is full
- {
- event |= UART_RX_FULL;
- }
- else if(pfifo->rxCnt > (pfifo->rxSize>>1))//rx byte is more than half of rx buffer
- {
- event |= UART_RX_OVF;
- }
- }
- }
- //TXE IRQ
- if(iflag & USART_FLAG_TXE)
- {
- uart->CR1 &= (uint16_t)~0x0080; //off TX
- if(pfifo->txCnt)
- {
- c = pfifo->txBuf[pfifo->txPop];
- uart->DR = c;
- uart->CR1 |= (uint16_t)0x0080;
- pfifo->txPop += 1;
- if(pfifo->txPop >= pfifo->txSize)
- {
- pfifo->txPop = 0;
- }
- pfifo->txCnt -= 1;
- if(pfifo->txCnt == 0)
- {
- event |= UART_TX_DONE;
- }
- }
- }
- //run isr function
- if(NULL != pfifo->isr)
- {
- pfifo->isr(port,event,pfifo->msg);
- }
- }
- /*************************************************************************************************
- * Name : _uart_read_isr
- * Describe : 串口读取函数中断模式
- * param :
- * Return :
- * Create by :
- * Moid by :
- *************************************************************************************************/
- static uint16_t _uart_read_isr(struct _uart_fifo_t *pfifo,USART_TypeDef *uart,uint8_t *data,uint16_t len)
- {
- uint32_t ie;
- uint16_t n;
- if(len == 0)
- {
- return 0;
- }
- for(n=0;n
- {
- if(n < pfifo->rxCnt)
- {
- *data++ = pfifo->rxBuf[pfifo->rxPop];
- pfifo->rxPop += 1;
- if(pfifo->rxPop>=pfifo->rxSize)
- {
- pfifo->rxPop = 0;
- }
- }
- else
- {
- break;
- }
- }
- ie = __get_PRIMASK();
- __set_PRIMASK(1);
- pfifo->rxCnt -= n;
- __set_PRIMASK(ie);
- return n;
- }
- /*************************************************************************************************
- * Name : _uart_write_isr
- * Describe : 串口写入函数中断模式
- * param :
- * Return :
- * Create by :
- * Moid by :
- *************************************************************************************************/
- static uint16_t _uart_write_isr(struct _uart_fifo_t *pfifo,USART_TypeDef *uart,uint8_t *data,uint16_t len)
- {
- uint32_t ie;
- uint16_t n;
- if(len == 0)
- {
- return 0;
- }
- for(n=0;n
- {
- if((pfifo->txSize-n) > pfifo->txCnt)
- {
- pfifo->txBuf[pfifo->txPush] = *data++;
- pfifo->txPush += 1;
- if(pfifo->txPush >= pfifo->txSize)
- {
- pfifo->txPush = 0;
- }
- }
- else
- {
- break;
- }
- }
- ie = __get_PRIMASK();
- __set_PRIMASK(1);
- pfifo->txCnt += n;
- __set_PRIMASK(ie);
- return n;
- }
- /*************************************************************************************************
- * Name : UART_ISR
- * Describe : 串口中断服务
- * param :
- * Return :
- * Create by :
- * Moid by :
- *************************************************************************************************/
- void USART_ISR(uint8_t port)
- {
- _uart_isr(port,&UartDevice[port].fifo,UartDevice[port].uart);
- }
- /*************************************************************************************************
- * Name : UART_DMA_ISR
- * Describe : 串口中断服务
- * param :
- * Return :
- * Create by :
- * Moid by :
- *************************************************************************************************/
- void UART_DMA_ISR(uint8_t port)
- {
- }
- /*
- __inline void UartDmaIsr(uint8_t port,struct UartFifo *pfifo,USART_TypeDef *uart)
- {
-
-
- }
- */
- /*************************************************************************************************
- * Name : UartSeting
- * Describe :
- * param :
- * Return :
- * Create by : 罗一鸣 Date: 2013-06-18
- * Moid by :
- *************************************************************************************************/
- void UartSeting(uint8_t port,uart_seting_t seting)
- {
- UartDevice[port].uart = USART_TABLE[port];
- UartDevice[port].rxdma = NULL;
- UartDevice[port].txdma = NULL;
- UartDevice[port].fifo.rxCnt = UartDevice[port].fifo.txCnt = 0;
- UartDevice[port].fifo.rxPush = UartDevice[port].fifo.rxPop = 0;
- UartDevice[port].fifo.txPush = UartDevice[port].fifo.txPop = 0;
- UartDevice[port].fifo.rxSize = seting.rxSize;
- UartDevice[port].fifo.rxBuf = seting.rxBuf;
- UartDevice[port].fifo.txSize = seting.txSize;
- UartDevice[port].fifo.txBuf = seting.txBuf;
- UartDevice[port].fifo.isr = seting.isr;
- UartDevice[port].fifo.msg = seting.msg;
- if(seting.rxdma)
- {
- UartDevice[port].rxdma = UART_DMA_RX_TABLE[port];
- }
- if(seting.txdma)
- {
- UartDevice[port].txdma = UART_DMA_TX_TABLE[port];
- }
- USART_Init(UartDevice[port].uart, &seting.init);
- }
- /*************************************************************************************************
- * Name : UartRead
- * Describe :
- * param :
- * Return :
- * Create by : 罗一鸣 Date: 2012-12-03
- * Moid by :
- *************************************************************************************************/
- uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len)
- {
- if(UART_PORT_MAX <= port)
- {
- return 0;
- }
- if((NULL != UartDevice[port].rxdma))
- {
- return 0;
- }
- else
- {
- return _uart_read_isr(&UartDevice[port].fifo,UartDevice[port].uart,data,len);
- }
- }
- /*************************************************************************************************
- * Name : UartWrite
- * Describe :
- * param :
- * Return :
- * Create by : 罗一鸣 Date: 2012-12-03
- * Moid by :
- *************************************************************************************************/
- uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len)
- {
- if(UART_PORT_MAX <= port)
- {
- return 0;
- }
- if((NULL != UartDevice[port].txdma))
- {
- return 0;
- }
- else
- {
- return _uart_write_isr(&UartDevice[port].fifo,UartDevice[port].uart,data,len);
- }
- }
- /*************************************************************************************************
- * Name : UartRxCnt
- * Describe :
- * param :
- * Return :
- * Create by :
- * Moid by :
- *************************************************************************************************/
- uint16_t UartRxCnt(uint8_t port)
- {
- return UartDevice[port].fifo.rxCnt;
- }
- /*************************************************************************************************
- * Name : UartTxCnt
- * Describe :
- * param :
- * Return :
- * Create by :
- * Moid by :
- *************************************************************************************************/
- uint16_t UartTxCnt(uint8_t port)
- {
- return UartDevice[port].fifo.txCnt;
- }
- /*************************************************************************************************
- * Name : UartSetIsrMsg
- * Describe : send msg to Isr
- * param :
- * Return :
- * Create by : 罗一鸣 Date: 2013-06-18
- * Moid by :
- *************************************************************************************************/
- void UartSetIsrMsg(uint8_t port,void* msg)
- {
- UartDevice[port].fifo.msg = msg;
- }
- /*************************************************************************************************
- * Name : UartInit
- * Describe :
- * param :
- * Return :
- * Create by : 罗一鸣 Date: 2012-12-03
- * Moid by :
- *************************************************************************************************/
- void UartInit(uint8_t port,uint8_t preprio,uint8_t subprio)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- if(UART_PORT_1 == port)
- {
- // config USART1 clock
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
- // Configure USART1 Tx (PA.09) as alternate function push-pull
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // Configure USART1 Rx (PA.10) as input floating
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // Set Interrupt Priority
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- //CLI();
- NVIC_Init(&NVIC_InitStructure);
- //SEI();
- }
- else if(UART_PORT_2 == port)
- {
- // config USART2 clock
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- // Configure USART2 Tx (PA.02) as alternate function push-pull
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // Configure USART2 Rx (PA.03) as input floating
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // Set Interrupt Priority
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- //CLI();
- NVIC_Init(&NVIC_InitStructure);
- //SEI();
- }
- else if(UART_PORT_3 == port)
- {
- // config USART3 clock
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
- // Configure USART2 Tx (PB.10) as alternate function push-pull
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- // Configure USART2 Rx (PB.11) as input floating
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- // Set Interrupt Priority
- NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- //CLI();
- NVIC_Init(&NVIC_InitStructure);
- //SEI();
- }
- }
- /****************************************************************************
- *************************** End of File *************************************
- ****************************************************************************/
复制代码
|