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

谈一谈STM32串口通信时,自定义协议问题

[复制链接]
只取一瓢 发布时间:2020-10-23 09:49
先说一下我想要实现的功能:
通过PC的串口助手发送一帧数据给STM32设备,STM32设备解析出某一位,若是1就点亮1个LED灯,若是0就把该LED灯熄灭。
自定义的通信协议如下:
AA  01  01  02  BB
AA —— 帧头
01  —— 地址
01  —— 控制字(是01就点亮LED,是00就熄灭LED)
02  —— 校验和(地址+控制字)
BB —— 帧尾

今天我们主要是讨论一下自定义协议的问题,在这里我就默认你的STM32设备已经可以和电脑的串口助手可以通信上了。如果还没有实现这一功能,建议参考STM32FX开发指南(库函数版),下方我也会提供出源代码供大家参考。
因为我硬件采用的是STM32F407,大家可以根据自己的实际情况进行移植;
你准备好了吗?接下来跟着我的节奏开始.......
第一步:替换中断服务函数;
把原来的中断服务函数用下面的函数代替(函数可以在usart.c文件中找到)
  1. void USART1_IRQHandler(void)                  
  2. {
  3.   u8 Res;//临时变量,存放串口接收的数据

  4.   if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
  5.   {
  6.     Res =USART_ReceiveData(USART1);//(USART1->DR);  //读取接收到的数据
  7.     if(rx_stack.head_flag==1)//收到了帧头
  8.     {
  9.         if(Res==0xBB)//判断当前值是不是帧尾
  10.         {
  11.           rx_stack.finish_flag = 1;
  12.           rx_stack.tail_flag=1;
  13.           rx_stack.head_flag=0;
  14.         }
  15.         else
  16.         {
  17.           rx_stack.recevie_data[rx_stack.data_pt] = Res;
  18.           rx_stack.data_pt++;
  19.           if(rx_stack.data_pt > 9)
  20.           {
  21.             rx_stack.data_pt = 0;
  22.           }
  23.         }                  
  24.     }
  25.     else//没有收到帧头
  26.     {
  27.       if(Res==rx_stack.head)
  28.         rx_stack.head_flag=1;
  29.       else
  30.       {
  31.         CommClr();
  32.         return;  
  33.       }  
  34.     }   
  35.   }
  36.   USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除接受中断标志
  37. }
复制代码
到这里你会发现,运行之后会出现很多错误,别慌别慌,问题不大,那是因为我的中断服务函数里面定义了一些原来没有的变量和函数;接着往下看.......

第二步:添加自定义的函数

  1. void rx_stack_init()
  2. {
  3.     rx_stack.head = 0xAA;         //协议栈头,起始位
  4.     rx_stack.addr=0x01;           //从机地址
  5.     memset(rx_stack.recevie_data, 0, sizeof(rx_stack.recevie_data));//把tx_stack.data[]全部初始化为零
  6.     rx_stack.tail = 0xBB;         //协议栈尾,结束位
  7.     rx_stack.head_flag = 0;
  8.     rx_stack.tail_flag = 0;
  9.     rx_stack.finish_flag = 0;
  10. //  rx_stack.lock_flag = 0;
  11.     rx_stack.data_pt = 0;
  12. }
  13. struct receive_stack rx_stack;

  14. void CommClr(void)
  15. {
  16.   rx_stack.head_flag = 0;
  17.   rx_stack.tail_flag = 0;
  18.   rx_stack.finish_flag = 0;
  19.   rx_stack.data_pt = 0;
  20.   
  21.   memset(rx_stack.recevie_data, 0, sizeof(rx_stack.recevie_data));//把tx_stack.data[]全部初始化为零
  22.   rx_stack.commPack_OK_flag=0;
  23. }
复制代码

把这两个函数放到中断服务函数前面。什么还会报错??当然了,因为我们定义的函数都没有声明,接着来......

第三步:自定义函数的声明(可以在usart.h文件中进行声明)

声明自定义的结构体变量:

  1. struct receive_stack
  2. {
  3.     u8 head;//帧头
  4.     u8 addr;//从机地址
  5.     u8 recevie_data[10];//数据
  6.     u8 check;//校验
  7.     u8 tail;//帧尾
  8.     u8 head_flag;//接收到帧头标志位
  9.     u8 tail_flag;//接收到帧尾标志位
  10.     u8 finish_flag;//接收完成标志位
  11.     u8 data_pt;//已接收的字节数
  12.     u8 commPack_OK_flag;//数据解包完成标志
  13. };
  14. extern struct receive_stack rx_stack;
复制代码

声明上文中自定义的两个函数:
  1. void rx_stack_init(void);
  2. void CommClr(void);
复制代码

现在是不是就没有错误了,但是可能还有几个警告。如果还有错误的话应该是因为_sys_exit(int x) 这个函数,把他改成void  _sys_exit(int x) 再试一试,错误应该就没有了吧。那警告怎么去呢?出现告警可能是因为我们使用了memset()这个函数,我们只需要在usart.c中包含#include <string.h>头文件就可以了。现在理论上应该是没有任何报警了,你的是不是这样的?

第四步:验证是不是能正确返回数据

仿照第二步在usart.c中添加串口发送函数

  1. void usart_send(u8 byte)
  2. {
  3.   USART_SendData(USART1,byte);
  4.   while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);//发送完成标志位
  5. }
复制代码

别忘记声明这个函数;

第五步:写主函数
  1. int main(void)
  2. {

  3.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  4.   delay_init(168);    //延时初始化
  5.   uart_init(9600);  //串口初始化波特率为115200
  6.   LED_Init();          //初始化与LED连接的硬件接口  
  7.   while(1)
  8.   {
  9.     u8 i;
  10.     u8 SendBuf[5];
  11.     if(rx_stack.finish_flag ==1)//数据接收完成
  12.     {
  13.       SendBuf[0]=0x7B;
  14.       SendBuf[1]=rx_stack.recevie_data[0];
  15.       SendBuf[2]=rx_stack.recevie_data[1];
  16.       SendBuf[3]=rx_stack.recevie_data[2];
  17.       SendBuf[4]=0x7D;
  18.       for(i=0;i<5;i++)
  19.       {
  20.         usart_send(SendBuf[i]);
  21.       }
  22.     }
  23.   }
  24. }
复制代码

编译一下,把程序下载到板子里面试一试,当你用电脑的串口助手发送AA  01  01  02  BB 给你的目标板,它能把发的数据原样传回来吗?坛友们一块讨论一下。





评分

参与人数 1 ST金币 +5 收起 理由
子曰好人 + 5 赞一个!

查看全部评分

收藏 评论0 发布时间:2020-10-23 09:49

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

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