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

【经验分享】【STM32G0】借助串口非空中断实现空闲中断的功能

[复制链接]
STMCU小助手 发布时间:2021-11-8 15:27
1 实现原理
使用串口通信可实现数据帧的收发,完成机器人控制、采集数据的传输等任务。制定串口通信协议并定时发送一帧数据,常见的处理方法是利用空闲中断,但STM32 HAL库好像没有专用的空闲中断,自己实现起来比较麻烦,这里利用非空中断可以实现同样的功能,缺点是效率比较低,稳定性经过测试也还可以,如果有更好的思路欢迎提出。

1.1 制定串口通信协议
制定串口通信协议时一帧数据的长度和内容可以自己定义,STM32的串口传输的数据类型为uint8_t,注意取值不要超过0-255,下面给出一个电机控制的串口通信协议表做示例

PGWOK2SYP{HGB`WU`E`(@$J.png


1.2 分析中间变量
创建接收数组g_fUART1_Buf,其长度等于串口通信协议一帧的长度
创建接收一个字节的暂存变量g_fUART1_Byte,配置一个字节中断一次
创建g_fNew_Pack用于主程序中判断是否接收到完整的一帧数据
创建g_fNew_Pack_Cnt记录成功接收一帧数据的次数,方便调试
  1. uint8_t g_fUART1_Byte = 0;
  2. uint8_t g_fUART1_Buf[10] = {0};

  3. uint8_t g_fNew_Pack = 0;
  4. uint8_t g_fNew_Pack_Cnt = 0;
复制代码


1.3 接收数据的处理
新接收到的字节g_fUART1_Byte写入接收数组g_fUART1_Buf的末尾,每接收一个字节,就将前一个字节左移,保证新接收到的字节一直往数组里填充,当接收的字节超过接收数组的长度后,继续左移,去掉旧数据,填入新数据

20210317153926655.png


2 STM32CubeMX配置
2.1 SWD调试接口配置
SWD接口用于程序的下载、在线调试

20210317153912428.png


2.2 时钟树配置
STM32G0系列内嵌高精度(±1%)RC振荡时钟,无需外部时钟,所以这里并未使能外部高速时钟,开发板上也没有焊接,直接在时钟树配置选项的HCLK输入64,配置最大的64MHz时钟频率即可。

20210317154247720.png


2.3 UART1串口配置
UART1用于接收上文制定的串口通信协议,并开启非空中断

20210317154445383.png


20210317154445195.png



2.4 生成工程
输入工程名,选择存放路径(不要有中文),选择IDE为MDK-ARM;只生成用到的文件(目的是提高工程编译速度,减少工程占用空间),并生成单独的.c/.h文件,点击生成代码

20210317154512883.png


20210317154512880.png


3 添加用户代码
3.1 定义全局变量
  1. /* USER CODE BEGIN PV */
  2. uint8_t g_fUART1_Byte = 0;
  3. uint8_t g_fUART1_Buf[10] = {0};

  4. uint8_t g_fNew_Pack = 0;
  5. uint8_t g_fNew_Pack_Cnt = 0;
  6. /* USER CODE END PV */
复制代码


3.2 UART1中断初始化
  1. /* USER CODE BEGIN 2 */
  2.         HAL_UART_Receive_IT(&huart1, (uint8_t*)&g_fUART1_Byte, 1);  // 启动串口非空中断,第3个参数代表1一个字节中断一次
复制代码

3.3 UART1的printf重定向
  1. /* USER CODE BEGIN 0 */
  2. /* printf重定向 */
  3. #include "stdio.h"
  4. int fputc(int ch, FILE *f)
  5. {
  6.         uint8_t temp[1] = {ch};
  7.         HAL_UART_Transmit(&huart1, temp, 1, 5); // huart1根据需要修改
  8.         return ch;
  9. }
复制代码

3.4 UART1回调函数
  1. /* USER CODE BEGIN 4 */
  2. // 串口接收数据回调函数
  3. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  4. {
  5.         if(huart -> Instance == huart1.Instance )
  6.         {
  7.             // 往接收数组里填新数据,即实现原理的1.3
  8.                 for(int i=0;i<9;i++)
  9.                 {
  10.                         g_fUART1_Buf<i> = g_fUART1_Buf[i+1];
  11.                 </i>}
  12.                 g_fUART1_Buf[9] = g_fUART1_Byte;
  13.                 if(g_fUART1_Buf[0]==0x5a && g_fUART1_Buf[9]==0xa5) {
  14.                         g_fNew_Pack = 1;// 成功接收一帧数据,刷新标志位
  15.                 }
  16.                 HAL_UART_Receive_IT(&huart1, (uint8_t*)&g_fUART1_Byte, 1);  
  17.         }
  18. }
复制代码


3.5 接收数据的处理
  1. /* USER CODE BEGIN WHILE */
  2.   while (1)
  3.   {
  4.                 if(g_fNew_Pack) // 主程序中判断是否成功接收一帧数据
  5.          {
  6.                         g_fNew_Pack = 0; // 清除标志位
  7.                         g_fNew_Pack_Cnt++;
  8.                         printf("g_fNew_Pack_Cnt=%d\r\n",g_fNew_Pack_Cnt);// 输出成功接收一帧数据的次数
  9.                         for(int i=0;i<10;i++){
  10. <span style="font-style: italic;"><span style="font-style: normal;">                                printf("%x ",g_fUART1_Buf);// 16进制输出接收到的一帧数据
  11.                         }
  12.                         printf("\r\n");
  13.                         // uart1_handle(); // 串口1接收数据的处理函数,根据需求自己添加

  14.                 }

  15.     /* USER CODE END WHILE */

  16.     /* USER CODE BEGIN 3 */
  17.   }</span></span>
复制代码

4 效果演示
gif中为方便演示,除了帧头帧尾,没有使用上文串口协议定义的内容,用11 22等数据(16进制)代替

20210317155825530.jpg




20210317155810731.gif
收藏 评论0 发布时间:2021-11-8 15:27

举报

0个回答

所属标签

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