STM32CubeMX 串口收发一帧数据

简介: STM32CubeMX 串口收发一帧数据

一、CubeMX配置


首先配置时钟源




打开调试



打开PC13板载小灯,方便观察板子是否正常运行



串口一、串口三 波特率选择9600



中断配置



DMA配置

rx选择正常(normal)模式



tx选择正常模式



选择好路径,生成代码




二、程序配置


串口一和串口三收发一帧数据配置

uart.c


/* USER CODE BEGIN 0 */
volatile uint8_t rx1_len = 0;  //接收一帧数据的长度
volatile uint8_t recv1_end_flag = 0; //一帧数据接收完成标志
uint8_t rx1_buffer[20]={0};  //接收数据缓存数组
 
volatile uint8_t rx3_len = 0;  //接收一帧数据的长度
volatile uint8_t recv3_end_flag = 0; //一帧数据接收完成标志
uint8_t rx3_buffer[20]={0};  //接收数据缓存数组
/* USER CODE END 0 */


 /* USER CODE BEGIN USART1_Init 2 */
  //下方为自己添加的代码
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断
 
//DMA接收函数,此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度
  HAL_UART_Receive_DMA(&huart1,rx1_buffer,BUFFER_SIZE1);
 
  /* USER CODE END USART1_Init 2 */


  /* USER CODE BEGIN USART3_Init 2 */
    __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
    HAL_UART_Receive_DMA(&huart3,rx3_buffer,BUFFER_SIZE3);
  /* USER CODE END USART3_Init 2 */


uart.h


/* USER CODE BEGIN Private defines */
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern DMA_HandleTypeDef hdma_usart3_tx;
 
#define BUFFER_SIZE1  20  
extern  volatile uint8_t rx1_len ;  //接收一帧数据的长度
extern volatile uint8_t recv1_end_flag; //一帧数据接收完成标志
extern uint8_t rx1_buffer[20];  //接收数据缓存数组
 
#define BUFFER_SIZE3  20 
extern  volatile uint8_t rx3_len ;  //接收一帧数据的长度
extern volatile uint8_t recv3_end_flag; //一帧数据接收完成标志
extern uint8_t rx3_buffer[20];  //接收数据缓存数组
/* USER CODE END Private defines */


main.c


/* USER CODE BEGIN 0 */
 
void DMA_Usart1_Send(uint8_t *buf,uint8_t len)//串口发送封装
{
 if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK)   //判断是否发送正常,如果出现异常则进入异常中断函数
  {
   Error_Handler();
  }
 
}
 
void DMA_Usart3_Send(uint8_t *buf,uint8_t len)
{
 if(HAL_UART_Transmit_DMA(&huart3, buf,len)!= HAL_OK)   //判断是否发送正常,如果出现异常则进入异常中断函数
  {
   Error_Handler();
  }
}
 
void DMA_Usart1_Read(uint8_t *Data,uint8_t len)//串口接收封装
{
  HAL_UART_Receive_DMA(&huart1,Data,len);//重新打开DMA接收
}
 
void DMA_Usart3_Read(uint8_t *Data,uint8_t len)//串口接收封装
{
  HAL_UART_Receive_DMA(&huart3,Data,len);//重新打开DMA接收
}
/* USER CODE END 0 */


  /* USER CODE BEGIN WHILE */
  while (1)
  {
  
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
       if(recv1_end_flag == 1)  //接收完成标志
    {
      
      
      DMA_Usart1_Send(rx1_buffer, rx1_len);
      rx1_len = 0;//清除计数
      recv1_end_flag = 0;//清除接收结束标志位
        memset(rx1_buffer,0,rx1_len);
  }
    HAL_UART_Receive_DMA(&huart1,rx1_buffer,BUFFER_SIZE1);//重新打开DMA接收
    
  
  
   if(recv3_end_flag == 1)  //接收完成标志
    {
      
      
      DMA_Usart3_Send(rx3_buffer, rx3_len);
      rx3_len = 0;//清除计数
      recv3_end_flag = 0;//清除接收结束标志位
        memset(rx3_buffer,0,rx3_len);
  }
    HAL_UART_Receive_DMA(&huart3,rx3_buffer,BUFFER_SIZE3);//重新打开DMA接收
    
  }
  /* USER CODE END 3 */

stm32f1xx_it.c


添加头文件


/* USER CODE BEGIN Includes */
#include "usart.h"
/* USER CODE END Includes */


使用ctl+F搜索USART1_IRQHandle并添加进去


void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
  uint32_t tmp_flag = 0;
  uint32_t temp;
  tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
  if((tmp_flag != RESET))//idle标志被置位
  { 
    __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
    //temp = huart1.Instance->SR;  //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
    //temp = huart1.Instance->DR; //读取数据寄存器中的数据
    //这两句和上面那句等效
    HAL_UART_DMAStop(&huart1); //  停止DMA传输,防止
    temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数   
    //temp  = hdma_usart1_rx.Instance->NDTR;// 读取NDTR寄存器,获取DMA中未传输的数据个数,
    rx1_len =  BUFFER_SIZE1 - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
    recv1_end_flag = 1; // 接受完成标志位置1  
   }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
 
  /* USER CODE END USART1_IRQn 1 */
}


使用ctl+F搜索USART3_IRQHandle并添加进去


void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
  uint32_t tmp_flag = 0;
  uint32_t temp;
  tmp_flag =__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE); //获取IDLE标志位
  if((tmp_flag != RESET))//idle标志被置位
  { 
    __HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除标志位
 
    HAL_UART_DMAStop(&huart3); //  停止DMA传输,防止
    temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);// 获取DMA中未传输的数据个数   
 
    rx3_len =  BUFFER_SIZE3 - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
    recv3_end_flag = 1; // 接受完成标志位置1  
   }
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
 
  /* USER CODE END USART3_IRQn 1 */
}


运行效果



链接: https://pan.baidu.com/s/1CxrKHNUcLv8lplg5WZwiKA?pwd=yaf7 提取码: yaf7


原文链接

STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA___hal_dma_get_counter-CSDN博客

目录
相关文章
|
3月前
|
传感器
【STM32】I2C练习,SHT3X温度传感器的数据读取
【STM32】I2C练习,SHT3X温度传感器的数据读取
|
1月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
167 0
|
1月前
|
芯片
STM32CubeMX 串口数据收发
STM32CubeMX 串口数据收发
23 2
|
1月前
|
监控
stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)
stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)
|
3月前
|
存储 缓存 芯片
STM32--USART串口
STM32--USART串口
|
3月前
|
Java C语言
STM32使用printf重定向到USART(串口)并打印数据到串口助手
STM32使用printf重定向到USART(串口)并打印数据到串口助手
146 0
|
2月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
156 2
|
2月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
292 4