你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32CUBEMX--USART通过定时器中断方式接收不定长数据

[复制链接]
STMCU小助手 发布时间:2022-4-30 22:43
概述
本文利用中断实现串口不定长接收(非DMA),使用HAL库,将接收的数据打印出去。

硬件准备
首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:

IS(PD7W85C(SQFJZNK9ANN7.png

选择芯片型号
使用STM32CUBEMX选择芯片stm32f030r8,如下所示:

]_SALSJZ8P(PKLRY7982FV0.png

配置时钟源
HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:

BQAXB@O$$I[6PQ{OUXEJ2.png

配置时钟树
STM32F0的最高主频到48M,所以配置48即可:

PVW3)EJK1N`O}GQ_H}Z0S{Q.png

串口配置

本次实验使用的串口1进行串口通信,波特率配置为115200。

MV}74_WL51128TP4MVHTQZM.png

中断


S~6PIGIOL@XGTMBDKV1V5NE.png

GPIO配置
板子上led为PA5端口,故设置PA5闪烁来验证是否正确。

R4UAW2PNKVPMFGFW`2]8]D4.png

定时器配置
本次实验使用的是TIM3来进行计数。

20201114005250315.png

PWM频率计算如下所示

20200604121517190.png

在上面配置TIM3参数,预分频系数设置为480-1, 自动重载值设置为10000-1,那么PWM频率为48,000,000/((480-1+1)*(10000-1+1))=10Hz,即 100ms一个周期。

生成工程设置

注意在生成工程设置中不能出现中文,不然会报错。

20201114010119218.png

代码生成设置

最后设置生成独立的初始化文件:

20200604142313327.png

生成代码


20200604142359253.png

配置keil

20201114010535287.png

代码

在main.c中,先加入头文件。
  1. /* USER CODE BEGIN Includes */
  2. #include "stdio.h"//printf头文件
  3. #include "string.h"//memset头文件
  4. /* USER CODE END Includes */
复制代码

定义变量存储。

  1. /* USER CODE BEGIN PV */
  2. uint8_t RxBuff[1];      //进入中断接收数据的数组
  3. uint8_t DataBuff[5000]; //保存接收到的数据的数组
  4. int RxLine=0;           //接收到的数据长度
  5. int Rx_flag=0;                                        //接受到数据标志
  6. /* USER CODE END PV */
复制代码

定义printf的重定向函数fputc。

  1. /* USER CODE BEGIN 0 */
  2. void printf_usart(void);//输出内容
  3. int fputc(int ch, FILE* file)//定义printf的重定向函数fputc,满足串口调试打印
  4. {
  5.     return HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100);
  6. }
  7. /* USER CODE END 0 */
复制代码

打开串口和定时器。

  1.   /* USER CODE BEGIN 2 */
  2.         HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //打开串口中断接收
  3.         HAL_TIM_Base_Start_IT(&htim3);//开启定时器
  4.   /* USER CODE END 2 */
复制代码

串口接受代码,当接受到最后数据为FF时候,直接打印,否则等待100ms打印。

  1. /* USER CODE BEGIN 4 */
  2. void printf_usart(void)
  3. {
  4.         printf("数据长度=%d\r\n",RxLine);
  5.         for(int i=0;i<RxLine;i++)
  6.                 printf("数据:[%d] = 0x%x\r\n",i,DataBuff<i>);                           
  7.         memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
  8.         //memset()作用:可以方便的清空一个结构类型的变量或数组。
  9.         //例句:memset(aTxbuffer,0,sizeof(aTxbuffer))  用memset清空aTxbuffer。
  10.         RxLine=0;  //清空接收长度
  11. }


  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  13. {
  14.     if (htim->Instance == htim3.Instance)
  15.     {
  16.                         HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
  17.         /* Toggle LED */
  18.                         if(Rx_flag==1)
  19.                         {
  20.                                 printf_usart();
  21.                                 Rx_flag=0;
  22.                         }
  23.                 }        
  24. }



  25. // 捕获中断回调函数,每次捕获到信号就会进入这个回调函数
  26. void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
  27. {
  28.     RxLine++;                      //每接收到一个数据,进入回调数据长度加1
  29.     DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组
  30.                 Rx_flag=1;
  31.     if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
  32.     {
  33.                         printf_usart();
  34.     }   
  35.     RxBuff[0]=0;
  36.     HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //每接收一个数据,就打开一次串口中断接收,否则只会接收一个数据就停止接收
  37.                 __HAL_TIM_SET_COUNTER(&htim3, 1); // 计数清零,从头开始计
  38. }
  39. /* USER CODE END 4 */
  40. </i>
复制代码

演示效果
可以看到 发送11 12 13需要等待100ms左右才能发送,如果最后加上ff直接发送。

20201114014530711.png
收藏 评论0 发布时间:2022-4-30 22:43

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版