当前位置:   article > 正文

STM32F407串口收发数据代码实现(标准库)_stm32f407标准库函数

stm32f407标准库函数

所用测试开发板:stm32f407ZET6

函数实现部分:(每个串口的初始化、收发处理方式一致,以串口1进行说明)

  1. #define Uart1RxUsed 1//使能接收置1,以下类似
  2. #define Uart1TxUsed 1
  3. #define Uart1RxUsedDMA 1
  4. #define Uart1TxUsedDMA 1
  5. #define Uart1ReceBufSize 256
  6. #define Uart1SendBufSize 256

 串口接收FIFO结构体定义

  1. typedef volatile struct
  2. {
  3. uint16_t WriteAddr;
  4. uint16_t ReadAddr;
  5. uint16_t ByteCount;
  6. uint16_t Reserve;
  7. }UartRxFifoDef;
  1. #if Uart1RxUse
  2. static uint8_t Uart1ReceBuf[Uart1ReceBufSize];
  3. static UartRxFifoDef Uart1RxFifoValue;
  4. #endif
  5. #if Uart1TxUsed
  6. static uint8_t Uart1SendBuf[Uart1SendBufSize];
  7. #endif

串口初始化流程:

串口中断使能配置

  1. /* Uart Interrupt Config part */
  2. NVIC_InitTypeDef NVIC_InitStruct = {0};
  3. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 11;
  4. NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
  5. NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  6. if(Uartx == USART1)
  7. NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
  8. NVIC_Init(&NVIC_InitStruct);
  9. USART_ITConfig(Uartx,USART_IT_IDLE,ENABLE);
  1. /* DMA Interrupt Config part*/
  2. #if Uart1TxUsedDMA
  3. if(Uartx == USART1)
  4. {
  5. DMA_ITConfig(DMA2_Stream7,DMA_IT_TC,ENABLE);
  6. NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream7_IRQn;
  7. }
  8. #endif
  9. NVIC_Init(&NVIC_InitStruct);

 注册串口空闲中断回调函数

  1. void UartxIDELHandleCallBack(USART_TypeDef *Uartx,void(*Function)(void))
  2. {
  3. if(Uartx == USART1)
  4. UartxIDELHandle[0] = Function;
  5. }

串口1中断处理函数:

  1. #if Uart1RxUsed
  2. void USART1_IRQHandler(void)
  3. {
  4. if(USART_GetITStatus(USART1,USART_IT_IDLE))
  5. {
  6. uint32_t Temp = (USART1->SR)<<16;
  7. Temp |= USART1->DR;
  8. Uart1RxFifoValue.WriteAddr = Uart1ReceBufSize - DMA_GetCurrDataCounter(DMA2_Stream5);
  9. Uart1RxFifoValue.ByteCount = ((Uart1RxFifoValue.WriteAddr > Uart1RxFifoValue.ReadAddr)?\
  10. Uart1RxFifoValue.WriteAddr : (Uart1RxFifoValue.WriteAddr + Uart1ReceBufSize)) - Uart1RxFifoValue.ReadAddr;
  11. if(UartxIDELHandle[0])
  12. UartxIDELHandle[0]();
  13. }
  14. }
  15. #endif

串口1DMA发送完成处理,置标志位

  1. #if Uart1TxUsedDMA
  2. void DMA2_Stream7_IRQHandler(void)
  3. {
  4. if(DMA_GetITStatus(DMA2_Stream7,DMA_IT_TCIF7))
  5. {
  6. UartxTxCompleteFlag |= 0x01;/*发送完成标志。下一帧数据发送时,检查该标志位*/
  7. DMA_ClearITPendingBit(DMA2_Stream7,DMA_IT_TCIF7);
  8. }
  9. }
  10. #endif

  获取接收帧长度的方法:

  1. uint16_t UartGetReceByteNum(USART_TypeDef *Uartx)
  2. {
  3. #if Uart1RxUsed
  4. if(Uartx == USART1)
  5. return Uart1RxFifoValue.ByteCount;
  6. #endif
  7. return 0;
  8. }

 获取接收完成的数据帧内容,然后进行数据拷贝的过程:

  1. uint8_t UartReadData(USART_TypeDef *Uartx,uint8_t *pBuf,uint16_t Lenth)
  2. {
  3. #if Uart1RxUsed
  4. if(Uartx == USART1)
  5. {
  6. if(Lenth > Uart1RxFifoValue.ByteCount)
  7. return 0;
  8. for(uint32_t i = 0;i < Lenth;i ++)
  9. {
  10. *pBuf++ = Uart1ReceBuf[Uart1RxFifoValue.ReadAddr ++];
  11. if(Uart1RxFifoValue.ReadAddr >= Uart1ReceBufSize)
  12. Uart1RxFifoValue.ReadAddr = 0;
  13. Uart1RxFifoValue.ByteCount --;
  14. if(Uart1RxFifoValue.ByteCount > Uart1ReceBufSize)
  15. Uart1RxFifoValue.ByteCount = 0;
  16. }
  17. return 1;
  18. }
  19. return 0;
  20. }

串口1发送数据过程:

  1. uint8_t UartSendData(USART_TypeDef *Uartx,uint8_t *pBuf,uint16_t Lenth)
  2. {
  3. #if Uart1TxUsed
  4. if(Uartx == USART1 && (Lenth <= Uart1SendBufSize))
  5. {
  6. #if Uart1TxUsedDMA
  7. /* Check DMA is Ready To Send */
  8. if(UartxTxCompleteFlag & 0x01)
  9. {
  10. for(uint32_t i = 0;i < Lenth;i ++)
  11. Uart1SendBuf[i] = pBuf[i];
  12. /* Wait for Uart Send The Last Data Complete */
  13. while(USART_GetFlagStatus(Uartx,USART_FLAG_TXE) == RESET);
  14. /* Enable DMA to Send Data */
  15. DMA_SetCurrDataCounter(DMA2_Stream7,Lenth);
  16. DMA_Cmd(DMA2_Stream7,ENABLE);
  17. UartxTxCompleteFlag &= 0xFE;
  18. return 1;
  19. }
  20. else
  21. return 0;
  22. #else
  23. /* Useing Interrupt Send Data at Here */
  24. #endif
  25. }
  26. }

复位串口1接收FIFO相关标志位

  1. void UartResetReceFifo(USART_TypeDef *Uartx)
  2. {
  3. volatile UartRxFifoDef *pRxFifo;
  4. #if Uart1RxUsed
  5. if(Uartx == USART1)
  6. pRxFifo = &Uart1RxFifoValue;
  7. else
  8. #endif
  9. pRxFifo = 0;
  10. if(pRxFifo)
  11. {
  12. pRxFifo->ReadAddr = pRxFifo->WriteAddr;
  13. pRxFifo->ByteCount = 0;
  14. }
  15. }

串口初始化调用过程:设置串口1波特率为115200

  1. UartInit(USART1,115200);
  2. UartxIDELHandleCallBack(USART1,RxCallBack);//为串口1注册空闲接收完成回调函数

函数实体为:RxCallBack();

  1. static void RxCallBack(void)
  2. {
  3. BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
  4. xSemaphoreGiveFromISR(RxSem,&pxHigherPriorityTaskWoken);/*发起信号量通知,等待相关任务处理接收到的数据*/
  5. portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
  6. }

OKay,那接下来就是接收任务的处理过程了:

  1. static uint8_t RxBuf[256];
  2. void Uart1RxTask(void *pcParameter)
  3. {
  4. while(1)
  5. {
  6. xSemaphoreTake(RxSem,portMAX_DELAY);
  7. uint16_t RxNum = UartGetReceByteNum(SCREEN_COM);
  8. UartReadData(SCREEN_COM,RxBuf,RxNum);
  9. /*在此处按照串口协议利用状态机机制处理收到的数据RxBuf*/
  10. }
  11. }

整个串口的初始化、收发处理过程都在这里了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/713317
推荐阅读
  

闽ICP备14008679号