赞
踩
所用测试开发板:stm32f407ZET6
函数实现部分:(每个串口的初始化、收发处理方式一致,以串口1进行说明)
- #define Uart1RxUsed 1//使能接收置1,以下类似
-
- #define Uart1TxUsed 1
-
- #define Uart1RxUsedDMA 1
-
- #define Uart1TxUsedDMA 1
-
- #define Uart1ReceBufSize 256
-
- #define Uart1SendBufSize 256
串口接收FIFO结构体定义
- typedef volatile struct
- {
- uint16_t WriteAddr;
- uint16_t ReadAddr;
- uint16_t ByteCount;
- uint16_t Reserve;
- }UartRxFifoDef;
- #if Uart1RxUse
- static uint8_t Uart1ReceBuf[Uart1ReceBufSize];
- static UartRxFifoDef Uart1RxFifoValue;
- #endif
-
- #if Uart1TxUsed
- static uint8_t Uart1SendBuf[Uart1SendBufSize];
- #endif
串口初始化流程:
串口中断使能配置
- /* Uart Interrupt Config part */
- NVIC_InitTypeDef NVIC_InitStruct = {0};
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 11;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- if(Uartx == USART1)
- NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
-
- NVIC_Init(&NVIC_InitStruct);
- USART_ITConfig(Uartx,USART_IT_IDLE,ENABLE);
- /* DMA Interrupt Config part*/
- #if Uart1TxUsedDMA
- if(Uartx == USART1)
- {
- DMA_ITConfig(DMA2_Stream7,DMA_IT_TC,ENABLE);
- NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream7_IRQn;
- }
- #endif
-
- NVIC_Init(&NVIC_InitStruct);
注册串口空闲中断回调函数
- void UartxIDELHandleCallBack(USART_TypeDef *Uartx,void(*Function)(void))
- {
- if(Uartx == USART1)
- UartxIDELHandle[0] = Function;
- }
串口1中断处理函数:
- #if Uart1RxUsed
- void USART1_IRQHandler(void)
- {
- if(USART_GetITStatus(USART1,USART_IT_IDLE))
- {
- uint32_t Temp = (USART1->SR)<<16;
- Temp |= USART1->DR;
- Uart1RxFifoValue.WriteAddr = Uart1ReceBufSize - DMA_GetCurrDataCounter(DMA2_Stream5);
- Uart1RxFifoValue.ByteCount = ((Uart1RxFifoValue.WriteAddr > Uart1RxFifoValue.ReadAddr)?\
- Uart1RxFifoValue.WriteAddr : (Uart1RxFifoValue.WriteAddr + Uart1ReceBufSize)) - Uart1RxFifoValue.ReadAddr;
- if(UartxIDELHandle[0])
- UartxIDELHandle[0]();
- }
- }
- #endif
串口1DMA发送完成处理,置标志位
- #if Uart1TxUsedDMA
- void DMA2_Stream7_IRQHandler(void)
- {
- if(DMA_GetITStatus(DMA2_Stream7,DMA_IT_TCIF7))
- {
- UartxTxCompleteFlag |= 0x01;/*发送完成标志。下一帧数据发送时,检查该标志位*/
- DMA_ClearITPendingBit(DMA2_Stream7,DMA_IT_TCIF7);
- }
- }
- #endif
获取接收帧长度的方法:
- uint16_t UartGetReceByteNum(USART_TypeDef *Uartx)
- {
- #if Uart1RxUsed
- if(Uartx == USART1)
- return Uart1RxFifoValue.ByteCount;
- #endif
- return 0;
- }
获取接收完成的数据帧内容,然后进行数据拷贝的过程:
- uint8_t UartReadData(USART_TypeDef *Uartx,uint8_t *pBuf,uint16_t Lenth)
- {
- #if Uart1RxUsed
- if(Uartx == USART1)
- {
- if(Lenth > Uart1RxFifoValue.ByteCount)
- return 0;
- for(uint32_t i = 0;i < Lenth;i ++)
- {
- *pBuf++ = Uart1ReceBuf[Uart1RxFifoValue.ReadAddr ++];
- if(Uart1RxFifoValue.ReadAddr >= Uart1ReceBufSize)
- Uart1RxFifoValue.ReadAddr = 0;
- Uart1RxFifoValue.ByteCount --;
- if(Uart1RxFifoValue.ByteCount > Uart1ReceBufSize)
- Uart1RxFifoValue.ByteCount = 0;
- }
- return 1;
- }
-
- return 0;
-
- }
串口1发送数据过程:
- uint8_t UartSendData(USART_TypeDef *Uartx,uint8_t *pBuf,uint16_t Lenth)
- {
- #if Uart1TxUsed
- if(Uartx == USART1 && (Lenth <= Uart1SendBufSize))
- {
- #if Uart1TxUsedDMA
- /* Check DMA is Ready To Send */
- if(UartxTxCompleteFlag & 0x01)
- {
- for(uint32_t i = 0;i < Lenth;i ++)
- Uart1SendBuf[i] = pBuf[i];
- /* Wait for Uart Send The Last Data Complete */
- while(USART_GetFlagStatus(Uartx,USART_FLAG_TXE) == RESET);
- /* Enable DMA to Send Data */
- DMA_SetCurrDataCounter(DMA2_Stream7,Lenth);
- DMA_Cmd(DMA2_Stream7,ENABLE);
- UartxTxCompleteFlag &= 0xFE;
- return 1;
- }
- else
- return 0;
- #else
- /* Useing Interrupt Send Data at Here */
-
- #endif
- }
-
- }
复位串口1接收FIFO相关标志位
-
- void UartResetReceFifo(USART_TypeDef *Uartx)
- {
- volatile UartRxFifoDef *pRxFifo;
- #if Uart1RxUsed
- if(Uartx == USART1)
- pRxFifo = &Uart1RxFifoValue;
- else
- #endif
- pRxFifo = 0;
- if(pRxFifo)
- {
- pRxFifo->ReadAddr = pRxFifo->WriteAddr;
- pRxFifo->ByteCount = 0;
- }
- }
串口初始化调用过程:设置串口1波特率为115200
- UartInit(USART1,115200);
-
- UartxIDELHandleCallBack(USART1,RxCallBack);//为串口1注册空闲接收完成回调函数
函数实体为:RxCallBack();
- static void RxCallBack(void)
- {
- BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
- xSemaphoreGiveFromISR(RxSem,&pxHigherPriorityTaskWoken);/*发起信号量通知,等待相关任务处理接收到的数据*/
- portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
- }
OKay,那接下来就是接收任务的处理过程了:
- static uint8_t RxBuf[256];
-
- void Uart1RxTask(void *pcParameter)
-
- {
-
- while(1)
- {
- xSemaphoreTake(RxSem,portMAX_DELAY);
- uint16_t RxNum = UartGetReceByteNum(SCREEN_COM);
- UartReadData(SCREEN_COM,RxBuf,RxNum);
-
- /*在此处按照串口协议利用状态机机制处理收到的数据RxBuf*/
-
- }
-
- }
整个串口的初始化、收发处理过程都在这里了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。