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

谈一谈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个回答

所属标签

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