单片机通讯协议

发布者:平凡幸福最新更新时间:2017-01-09 来源: eefocus关键字:单片机  通讯协议 手机看文章 扫描二维码
随时随地手机看文章
现在大部分的仪器设备都要求能过通过上位机软件来操作,这样方便调试,利于操作。其中就涉及到通信的过程。在实际制作的几个设备中,笔者总结出了通信程序的通用写法,包括上位机端和下位机端等。 
1.自定义数据通信协议

  这里所说的数据协议是建立在物理层之上的通信数据包格式。所谓通信的物理层就是指我们通常所用到的RS232、RS485、红外、光纤、无线等等通信方式。在这个层面上,底层软件提供两个基本的操作函数:发送一个字节数据、接收一个字节数据。所有的数据协议全部建立在这两个操作方法之上。
通信中的数据往往以数据包的形式进行传送的,我们把这样的一个数据包称作为一帧数据。类似于网络通信中的TCPIP协议一般,比较可靠的通信协议往往包含有以下几个组成部分:帧头、地址信息、数据类型、数据长度、数据块、校验码、帧尾。

  帧头和帧尾用于数据包完整性的判别,通常选择一定长度的固定字节组成,要求是在整个数据链中判别数据包的误码率越低越好。减小固定字节数据的匹配机会,也就是说使帧头和帧尾的特征字节在整个数据链中能够匹配的机会最小。通常有两种做法,一、减小特征字节的匹配几率。二、增加特征字节的长度。通常选取第一种方法的情况是整个数据链路中的数据不具有随即性,数据可预测,可以通过人为选择帧头和帧尾的特征字来避开,从而减小特征字节的匹配几率。使用第二种方法的情况更加通用,适合于数据随即的场合。通过增加特征字节的长度减小匹配几率,虽然不能够完全的避免匹配的情况,但可以使匹配几率大大减小,如果碰到匹配的情况也可以由校验码来进行检测,因此这种情况在绝大多说情况下比较可靠。

  地址信息主要用于多机通信中,通过地址信息的不同来识别不同的通信终端。在一对多的通信系统中,可以只包含目的地址信息。同时包含源地址和目的地址则适用于多对多的通信系统。

  数据类型、数据长度和数据块是主要的数据部分。数据类型可以标识后面紧接着的是命令还是数据。数据长度用于指示有效数据的个数。

  校验码则用来检验数据的完整性和正确性。通常对数据类型、数据长度和数据块三个部分进行相关的运算得到。最简单的做法可是对数据段作累加和,复杂的也可以对数据进行CRC运算等等,可以根据运算速度、容错度等要求来选取。

2.上位机和下位机中的数据发送

  物理通信层中提供了两个基本的操作函数,发送一个字节数据则为数据发送的基础。数据包的发送即把数据包中的左右字节按照顺序一个一个的发送数据而已。当然发送的方法也有不同。

  在单片机系统中,比较常用的方法是直接调用串口发送单个字节数据的函数。这种方法的缺点是需要处理器在发送过程中全程参与,优点是所要发送的数据能够立即的出现在通信线路上,能够立即被接收端接收到。另外一种方法是采用中断发送的方式,所有需要发送的数据被送入一个缓冲区,利用发送中断将缓冲区中的数据发送出去。这种方法的优点是占用处理器资源小,但是可能出现需要发送的数据不能立即被发送的情况,不过这种时延相当的小。对于51系列单片机,比较倾向于采用直接发送的方式,采用中断发送的方式比较占用RAM资源,而且对比直接发送来说也没有太多的优点。以下是51系列单片机中发送单个字节的函数。

void SendByte(unsigned char ch)
{
     SBUF = ch;
     while(TI == 0);
     TI = 0;
}

  上位机中关于串口通信的方式也有多种,这种方式不是指数据有没有缓冲的问题,而是操作串口的方式不同,因为PC上数据发送基本上都会被缓冲后再发送。对于编程来说操作串口有三种方式,一、使用windows系统中自带的串口通信控件,这种方式使用起来比较简单,需要注意的是接收时的阻塞处理和线程机制。二、使用系统的API直接进行串口数据的读取,在windows和linux系统中,设备被虚拟为文件,只需要利用系统提供的API函数即可进行串口数据的发送和读取。三、使用串口类进行串口操作。在此只介绍windows环境下利用串口类编程的方式。

  CSerialPort是比较好用的串口类。它提供如下的串口操作方法:

  void WriteToPort(char* string, int len);

  串口初始化成功后,调用此函数即可向串口发送数据。为了避免串口缓冲所带来的延时,可以开启串口的冲刷机制。

3.下位机中的数据接收和协议解析

  下位机接收数据也有两种方式,一、等待接收,处理器一直查询串口状态,来判断是否接收到数据。二、中断接收。两种方法的优缺点在此前的一篇关于串口通信的文章中详细讨论过。得出的结论是采用中断接收的方法比较好。

  数据包的解析过程可以设置到不同的位置。如果协议比较简单,整个系统只是处理一些简单的命令,那么可以直接把数据包的解析过程放入到中断处理函数中,当收到正确的数据包的时候,置位相应的标志,在主程序中再对命令进行处理。如果协议稍微复杂,比较好的方式是将接收的数据存放于缓冲区中,主程序读取数据后进行解析。也有两种方式交叉使用的,比如一对多的系统中,首先在接收中断中解析“连接”命令,连接命令接收到后主程序进入设置状态,采用查询的方式来解析其余的协议。

  以下给出具体的实例。在这个系统中,串口的命令非常简单。所有的协议全部在串口中断中进行。数据包的格式如下:

  0x55, 0xAA, 0x7E, 0x12, 0xF0, 0x02, 0x23, 0x45, SUM, XOR, 0x0D

  其中0x55, 0xAA, 0x7E为数据帧的帧头,0x0D为帧尾,0x12为设备的目的地址,0xF0为源地址,0x02为数据长度,后面接着两个数据0x23, 0x45,从目的地址开始结算累加、异或校验和,到数据的最后一位结束。

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

if(state_machine == 0)     // 协议解析状态机
{
    if(rcvdat == 0x55)     // 接收到帧头第一个数据
        state_machine = 1;
    else
        state_machine = 0;    // 状态机复位
}
else if(state_machine == 1)
{
    if(rcvdat == 0xAA)     // 接收到帧头第二个数据
        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 = 4;
    else
        state_machine = 0;
}
else if(state_machine == 4)
{
    sumchkm += rcvdat;
    xorchkm ^= rcvdat;
    if(rcvdat == m_DstAdr)    // 判断源地址是否正确
        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)     // 判断是否接收到帧尾结束符
    {
        retval = 0xaa;    // 置标志,表示一个数据包接收到
    }
    state_machine = 0;     // 复位状态机
}

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

  接收过程中,只要哪一步收到的数据不是预期值,则直接将状态机复位,用于下一帧数据的判断,因此系统出现状态死锁的情况非常少,系统比较稳定,如果出现丢失数据包的情况也可由上位机进行命令的补发,不过这种情况笔者还没有碰到。

  对于主程序中进行协议处理的过程与此类似,主程序循环中不断的读取串口缓冲区的数据,此数据即参与到主循环中的协议处理过程中,代码与上面所述完全一样。

4.上位机中的数据接收和命令处理

  上位机中数据接收的过程与下位机可以做到完全一致,不过针对不同的串口操作方法有所不同。对于阻赛式的串口读函数,例如直接进行API操作或者调用windows的串口通信控件,最好能够开启一个线程专门用于监视串口的数据接收,每接收到一个数据可以向系统发送一个消息。笔者常用的CSerialPort类中就是这样的处理过程。CSerialPort打开串口后开启线程监视串口的数据接收,将接收的数据保存到缓冲区,并向父进程发送接收数据的消息,数据将随消息一起发送到父进程。父进程中开启此消息的处理函数,从中获取串口数据后就可以把以上的代码拷贝过来使用。

  CSerialPort向父类发送的消息号如下:

  #define WM_COMM_RXCHAR WM_USER+7 // A character was received and placed in the input buffer.
  因此需要手动添加此消息的响应函数:

  afx_msg LONG OnCommunication(WPARAM ch, LPARAM port);
  ON_MESSAGE(WM_COMM_RXCHAR, OnCommunication)

  响应函数的具体代码如下:

LONG CWellInfoView::OnCommunication(WPARAM ch, LPARAM port)
{
     int retval = 0;
     rcvdat = (BYTE)ch;
     if(state_machine == 0)     // 协议解析状态机
    {
      if(rcvdat == 0x55)     // 接收到帧头第一个数据
          state_machine = 1;
      else
          state_machine = 0;    // 状态机复位
    }
    else if(state_machine == 1)
    {
      if(rcvdat == 0xAA)     // 接收到帧头第二个数据
          state_machine = 2;
      else
          state_machine = 0;    // 状态机复位
    ......

5.总结

  以上给出的是通信系统运作的基本雏形,虽然简单,但是可行。实际的通信系统中协议比这个要复杂,而且涉及到数据包响应、命令错误、延时等等一系列的问题,在这样的一个基础上可以克服这些困难并且实现出较为稳定可靠的系统


关键字:单片机  通讯协议 引用地址:单片机通讯协议

上一篇:单片机实现多线程
下一篇:MSP430 flash的操作

推荐阅读最新更新时间:2024-03-16 15:29

通过PC的USB端口控制多个步进电机
USB的众多便利使设计师能将该总线用于许多应用。例如,图中显示的是一个利用现成的便宜器件搭建的基于USB的4步进电机控制器。该电路没用MCU和DSP。它利用简单逻辑电路和应用软件控制步进电机的选择、其顺/逆时针的运行方向以及三种步进幅度:全步、半步和微步。 该设计基于一个USB转FIFO的并行接口模块(IC1)。这款名为DLP-USB245M的模块提供8位双向数据总线和诸如WR、RD、RXF和TXE等控制信号,利用这些信号控制PC和任何采用USB协议的外接电路的数据流。 利用该模块免去了需应付繁琐的USB接口的工作。另外,该模块带可通过高级语言容易快速地控制模块功能的驱动器软件,从而无需太多牵挂USB协议。 该控制器电路
[工业控制]
基于STM32单片机发送字符串的函数
最近由于要调试一个SMS发送短信的模块,该模块需要发送一系列AT指令,且需要字符串发送,但是STM32官方给的usart.c中并没有直接发送字符串的函数,因此写了一个发送字符串的函数。 其实发送字符串的本质还是发送一个个字符,所以只需在字符串结束标志之前,循环发送字符即可。不罗嗦,上程序。 //程序功能:利用串口发送一个字符串 // 参数:USARTx USART编号 可取 USART1、USART2、USART3、USART4、 USART5(STM32F103ZET6) str 需要发送的字符串 #include “stm32f10x.h” void Usart_SendString(USART_TypeDef* US
[单片机]
COP8CDR9微控制器在多路数据采集中的应用
    摘要: 前端数据采集是工业生产过程中获取生产信息的必要手段。本文结合美国国家半导体的芯片COP8CDR9的A/D转换特点和应用实际,给出由COP8CDR9微控制器构成的多路数据采集系统及其在列车实时监控系统中的应用     关键词: 微控制器 多路数据采集 A/D转换 CPO8CDR9 前端数据采集能够及时获取被控对象和生产过程的有效信息,在某些实时性要求高的场合尤为重要。工业生产过程中,为了清晰地反映出生产过程的详细信息,往往需要获得多个参量的动态数据,这就有必要对被控对象和生产过程进行多路数据采集。COP8CDR9系列微控制器是美国国家半导体公司(National Semiconduto
[嵌入式]
基于51单片机的MP3方案设计
随着人们对便携式音乐播放器要求的提高,MP3播放器以其较小的体积和较好的音质赢得了广大音乐爱好者的青睐。起初,MP3文件只能由电脑来播放,随着互联网的发展,促进了MP3播放器的产生,随着人们对MP3产品进一步的认识和更高层次的需求,MP3发生了一系列的变化,其更加小巧精致,更人机化和情趣化,个性区分也越来越强。还出现了功能的融人和产品的整合,总之,MP3播放器正朝着功能强大、外观丰富、价格便宜的方向发展。这里提出一种基于AT89C51SND1C的MP3播放器设计方案。 1 MP3播放器简介 MP3播放器是一种新兴的数字音乐播放器,播放MP3、WMA等格式的文件。通过用MPEG-1 Layer 3编码技术,可以得到大约1
[单片机]
基于51<font color='red'>单片机</font>的MP3方案设计
关于PIC单片机之探讨低功耗
1、睡眠(sleep) 睡眠方式是我们最常用的一种方式来降低功耗,但睡眠期间单片机不能做任何的事情。对于那些没事情就睡着,有事情就做一下的情况睡眠无疑是功耗最低的处理方式。 比如: 睡眠+ I/O电平变化中断唤醒当按键没按下时,单片机睡眠,当按键按下后,执行相应的工作。 睡眠+数据接收中断唤醒这样单片机就可以再没有接收到数据时候进入睡眠状态,接收到数据的时候就唤醒然后处理数据。当然首先单片机要有相关的外设比如SPI ,I2C,USART,等这些支持这些通讯的模块。 睡眠+看门狗唤醒这个可以用在需要定时唤醒做事情的场合 2、降低时钟频率 如果即想功耗低,又想单片机在能低功耗的情况下工作。这无疑是个最好的选
[单片机]
基于C51系列单片机的物体分级设备的测量光幕设计
1 引言 光幕是电子测量系统中应用比较多的一种设备。利用光幕可以测量恒速传送带上的物体高度、长度或宽度等一系列数据,以便为后面的电子系统提供相应的参数。本文给出了一种利用单片机实现物体高度测量的光幕测量方法。 2 光幕测量物体高度的基本原理 图1所示是一个用普通光幕测量物体高度的测试原理结构示意图。图中,光幕的一边等间距安装有多个红外发射管,另一边相应的有相同数量同样排列的红外接收管,每一个红外发射管都对应有一个相应的红外接收管,且安装在同一条直线上。当同一条直线上的红外发射管、红外接收管之间没有障碍物时,红外发射管发出的调制信号(光信号)能顺利到达红外接收管。红外接收管接收到调制信号后,相应的电路输出低电平,而在有
[单片机]
基于C51系列<font color='red'>单片机</font>的物体分级设备的测量光幕设计
基于单片机的电脑弹簧机按键板的设计与实现
引言 电脑弹簧机是用来生产弹簧的专用设备。按键板,作为一个人机交互的操作界面,起着输入操作命令,编辑弹簧加工程序及修改数据的功能,对电脑弹簧机的操作控制起着重要作用。在实际应用中,为方便操作,需要将按键板的按键汉字化和直接化,这使得使用标准的PC键盘不太可能,所以开发一块便宜且通用的按键板就很有现实意义。在PC机中,键盘和主机的通信采用的是PS/2协议。由于电脑弹簧机的控制器是一个标准的工控PC机控制器,具有标准的键盘接口,为了使设计简单和通用,在这里使用这个标准的键盘接口,并采用PS/2协议来进行按键板和弹簧机的通信,设计时选用单片机AT89S51作为按键板的处理芯片进行按键的识别和数据的接收和发送。本文介绍的是设计并实现这个
[单片机]
基于<font color='red'>单片机</font>的电脑弹簧机按键板的设计与实现
基于GSM模块Q2403A和8051单片机实现短消息收发系统的应用方案
基于GSM短消息的业务不需要建立拨号连接,只需把待发的消息加上目的地址发送至短消息中心,再由短消息中心转发到最终目标。GSM 短消息业务以其连接简单、费用低廉、覆盖范围广、实现方便等优点得到了广泛的应用。运用 GSM 短消息实现远程测控的可靠性较高、信号传播距离远、覆盖面积广,并且可以节省建网初期的巨额投资。 本文对基于GSM短消息收发系统的设计与实现作了具体描述,给出了系统的软硬件设计方案,对主要硬件,即GSM模块Q2403A 和8051单片机作了重点介绍。给出了系统的软件设计,包括PC与单片机通信部分和短消息收发部分。最后实现系统监控功能。 系统硬件实现 总体系统结构 该系统硬件主要由8051单片机扩展电路、Q2403
[单片机]
基于GSM模块Q2403A和8051<font color='red'>单片机</font>实现短消息收发系统的应用方案
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved