ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于stm32的自定义通信协议-模拟串行通讯

2022-02-24 17:03:07  阅读:227  来源: 互联网

标签:machine rcvdat 自定义 通信协议 else stm32 state 接收 数据包


目录

一、背景

二、方案设计

三、课程作业实施

四、测试结果

五、部分代码(完整代码可私聊我+QQ2521170001)

一、背景

  • 题目:通过数字通道进行两个计算机系统的通讯
  • 目标:设计、实现一个用于数字通道串行通讯的协议
  1. 硬件

                

   2.软件

        CLK上升沿检测DTA的值,作为1bit,存入寄存器中。


二、方案设计

(一)自定义协议格式

START

帧头

数据长度

标识

数据

数据效验

帧尾

1Byte

1Byte

1Byte

1Byte

1Byte

2Byte

1Byte

0x53

0xFE

0x01

0xDD

0x0D0C

0xFF

1、起始标志:协议数据帧开始的标志,保留字为0x53。

2、帧头:同其他设备通信时首要的一致性保证,此次为0xFE。

3、数据长度:表示当前数据包的大小。

4、标识:可以自定义,对于不同的数据包,采用不同的标识。比如当为温度采样问题时,该为温度采集器序号。当为湿度采样问题时,该为湿度采集器序号。

5、真实数据:发送的数据内容,对于温度采样问题。

6、数据校验根据前述数据所得的CRC32校验码。

7、结束标志即帧尾,协议数据结束的标志,保留字为0xFF。

(二)、自定义协议详解

        1、自定义协议采用的是端到端的通信。

        2、自定义的通信协议采用2条信号线,1条时钟线(CLK)和1条数据线(DTA),属于串行半双工通信。每个从设备有自己的标识、帧头、数据、数据长度、数据校验、帧尾,主设备发送START信号(0x53)后,紧跟着发送想要数据的帧头(0xFE),当验证了帧头之后,该数据包即是我们所需的对应数据包。

        3、CLK上升沿检测DTA的值,作为1bit,存入寄存器中。没有数据传输时,DAT上恒保持高电平。

        4、START信号:当检测到DAT的值为0x53时,开始传输数据。

        5、帧头:0xFE—>即在CLK时钟的8个周期内,此时传输了8bit数据为1111 1110时(即0xFE),该数据包即是正确的数据包,在第一个字节后,主机立即读从机,开始接收该数据包。

        6、STOP信号:当时钟线为高时,数据线上跳会产生停止信号,即为该数据包的帧尾(0xFF)。


三、课程作业实施

1、发送方法:

        按照协议的要求去组织数据,把数据装入发送缓冲区,采用中断发送的方式,所有需要发送的数据被送入一个缓冲区,利用发送中断将缓冲区中的数据发送出去。这种方法的优点是占用处理器资源小,但是可能出现需要发送的数据不能立即被发送的情况,不过这种时延相当的小。

2、下位机中的数据接收和协议解析

下位机接收数据采用中断接收。数据包的 解析过程可以设置到不同的位置。如果协议比较简单,整个系统只是处理 一些简单的命令,那么可以直接把数 据包的解析过程放入到中断处理函数中,当收到正确的数据包的时候,置位相应的标志,在主程序中再对命令进行处理。如果协议稍微复杂,比较好的 方式是将接收的数据存放于缓冲区中,主程序读取数据后进行解析。

3、数据包:

(1)数据包结构:

                数据包(8个字节)= 起始标志(1个字节)+ 帧头(1个字节) + 数据长度(1个字节) + 标识(1个字节)+ 数据(1个字节) + 校验(2个字节,高字节在前) + 帧尾(1个字节)

(2)通信处理方式:

        中断接收/发送 + 缓冲区

(3)协议的实现:

        ①接收: 我是在接收中断去实现协议功能的,即每接收中断一次(接收到一个字节)的时候,按照协议的要求去进行处理,如果这帧数据是正确的就置位Flag标志位,在大循环中再去进命令的解析,错误时则丢弃。

        ②协议解析的目的,首先判断数据包的完整性,正确性,然后提取数据类型,数据等数据,存放起来用于主程序处理。部分代码如下:

if(state_machine == 0)     // 协议解析状态机
{
    if(rcvdat == 0x53)     // 接收到START标志
        state_machine = 1;
    else
        state_machine = 0;    // 状态机复位
}
..................
else if(state_machine == 9)
{
    if(xorchkm == rcvdat)    // 判断异或校验和是否相等
        state_machine = 10;
    else
        state_machine = 0;
}
else if(state_machine == 10)
{
    if(0x0D == rcvdat)     // 判断是否接收到帧尾结束符
    {
        flag= 0xaa;    // 置标志,表示一个数据包接收到
    }
    state_machine = 0;     // 复位状态机
}

         此过程中,使用了一个变量state_machine作为协议状态机的转换状态,用于确定当前字节处于一帧数据中的那个部位,同时在接收过程中自动对接收数据进行校验和处理,在数据包接收完的同时也进行了校验的比较。因此当帧尾结束符接收到的时候,则表示一帧数据已经接收完毕,并且通过了校验,关键数据也保存到了缓冲去中。主程序即可通过flag标志位来进行协议的解析处理。


四、测试结果

 


五、部分代码(完整代码可私聊我+QQ2521170001)

if(state_machine == 0)     // 协议解析状态机
{
    if(rcvdat == 0x53)     // 接收到START标志
        state_machine = 1;
    else
        state_machine = 0;    // 状态机复位
}
else if(state_machine == 1)
{
    if(rcvdat == 0xFE)     // 接收到帧头第一个数据
        state_machine = 2;
    else
        state_machine = 0;    // 状态机复位
}
else if(state_machine == 2)
{
    if(rcvdat == 0x7E)     // 接收到帧头第二个数据
        state_machine = 3;
     else
        state_machine = 0;    // 状态机复位
}
else if(state_machine == 3)
{
    sumchkm = rcvdat;     // 开始计算累加、异或校验和
    xorchkm = rcvdat;
    if(rcvdat == m_SrcAdr)    // 判断标识是否正确
        state_machine = 5;
    else
        state_machine = 0;
}
else if(state_machine == 5)
{
    lencnt = 0;        // 接收数据计数器
    rcvcount = rcvdat;      // 接收数据长度
    sumchkm += rcvdat;
    xorchkm ^= rcvdat;
    state_machine = 6;
}
else if(state _machine == 6 || state _machine == 7)
{
    m_ucData[lencnt++] = rcvdat;     // 数据保存
    sumchkm += rcvdat;
    xorchkm ^= rcvdat;
    if(lencnt == rcvcount)    // 判断数据是否接收完毕
        state_machine = 8;
    else
        state_machine = 7;
}
else if(state_machine == 8)
{
    if(sumchkm == rcvdat)    // 判断累加和是否相等
        state_machine = 9;
    else
        state_machine = 0;
}
else if(state_machine == 9)
{
    if(xorchkm == rcvdat)    // 判断异或校验和是否相等
        state_machine = 10;
    else
        state_machine = 0;
}
else if(state_machine == 10)
{
    if(0x0D == rcvdat)     // 判断是否接收到帧尾结束符
    {
        flag= 0xaa;    // 置标志,表示一个数据包接收到
    }
    state_machine = 0;     // 复位状态机
}

标签:machine,rcvdat,自定义,通信协议,else,stm32,state,接收,数据包
来源: https://blog.csdn.net/qq_41834692/article/details/123114193

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有