精华内容
下载资源
问答
  • 51串口通信 数据帧

    2014-11-01 07:36:19
    应用51 开发的 串口通信 带数据包格式
  • 51单片机串口通信帧数据接收

    千次阅读 2015-12-12 21:35:42
    首先定义一个数据帧格式,Header :{ 0xAA 0x55} type:{ 0x01 | 0x02 | 0x03 } length:{ N } body :{____n个字节的数据___ } 数据的格式就是上面的定义 Header 为帧头 标记一个数据帧的开始,type 为类型 用来...


    首先定义一个数据帧格式,Header :{ 0xAA 0x55} type:{ 0x01 | 0x02 | 0x03 } length:{  N } body :{____n个字节的数据___ }

    数据的格式就是上面的定义  Header 为帧头 标记一个数据帧的开始,type 为类型 用来识别数据的类型 ,Length为长度标记 用来识别是否收完一帧的数据;

    这次的目的是为了获取来自PC端串口传来的汉字字模数据 —— 一条长为32字节的数据,所以定义N = 32;类型 因为是第一个要用到的数据就先使用type=0x01

    现在确定的格式 一帧数据 大概是  

    unsinged char code test[36]={0xaa,0x55,0x01,0x20,0x01,0x0D,0x1D,0x19,0x01,0x3F,0x3F,0x03,0x03,0x03,0x07,0x26,0x6E,0x7C,0x38,0x00,0x98,
    					0x98,0x98,0x8C,0x8C,0x8E,0xEF,0xED,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x00};

    当一个数据发来单片机进入中断程序开始接收数据

    void mReceive(){
    	uart_flag =0;//接收标志
    <span style="white-space:pre">	</span>RI=0;//手动清寄存器
    <span style="white-space:pre">	</span>receive[count]=SBUF;
    	if(count==0&&receive[count]==0xaa){
    		count=1;
    	}
    	else if(count==1&&receive[count]==0x55){
    			count=2;
    	}	
    	else if(count>=2){
    		if(count-3==receive[3]){ //当已经接收到的长度是该数据帧的长度时接收完成
    			count=0;
    <span style="white-space:pre">			</span>uart_flag=1;
    		}else if (count>=37)//超长验证,如果数据接收一帧的长度还没有完成验证一整帧则接受失败 开始新的接收
    		{
    			count  = 0;
    		}else{
                           count+=1;
                         }
    	else {
    		count=0;
    	}	
    }

    第一张是LabView上的模拟显示第二张是proteus仿真接收到的数据然后显示的结果

    展开全文
  • 串口通信同步 

    2021-05-11 16:59:02
    串口通信同步 转发大佬的 封装STM32串口的底层时,遇到了串口同步的问题。虽然以前也遇到类似场合,写出来的代码基本能够解决问题,但是在逻辑上总是不能彻底的解释一些细节。 当前的工作环境: 由于代码...

    串口通信的帧同步  转发大佬的

     

    封装STM32串口的底层时,遇到了串口帧同步的问题。虽然以前也遇到类似场合,写出来的代码基本能够解决问题,但是在逻辑上总是不能彻底的解释一些细节。

    当前的工作环境:

    由于代码想用在一个简单的PID闭环上,做在线的参数整定。假设当前PID解算周期是1ms,即每1ms,做一次串口的收包,解包,Pid解算,数据采集,然后打包,发包。也就是说是固定步长的解包。

    串口的方案是开启收发的DMA以及DMA的中断。(坚决不考虑直接使用串口中断。一个字节中断一次太费资源)。DMA数组作为串口的FIFO队列(并不是真正意义上的队列)。

    当前的需求:

    1、时间节拍到来时,检查是否有收到数据。没有则跳出,有则进入下一步

    2、检查数据中的包格式,比如包头是否正确,帧长度是否对齐,CRC(目前还没有做进去)等

    3、包格式检查出错误,回包时添加标志位,声明包格式错误请求重发。包格式没有错误则进行解包并设置对应的寄存器和赋值。

    4、具有合理的接收缓冲区,大于缓冲区的数据进行放弃。

    5、能够及时检测出丢字节,多字节等帧长度出错的问题。


    几套尝试过的方案:

    1、DMA数组的长度和帧长度相等。

    触发条件:DMA计数值减到0(即已经收满一个帧的长度的数据)产生DMA中断,将触发标志位写1。PC机上可以通过开启一个线程监视缓冲区数量实现。

    解包操作:设置共用体,其中结构体为帧协议,同时公用一个u8 数组作为DMA数组。判断触发条件,若满足,读取共用体中的包头包尾,若正确,继续读取成员,解包赋值。

    缓冲机制:无。DMA设置为normal模式,计数减到0后即停止。有新的数据到来也不会被传入数组。PC机上可以手动关闭串口。

    报错机制:

    帧错位:在包头检查中会发现,舍弃当前帧,设置重发标志位请求重发。

    字节缺失:字节缺失的帧发送完成后不会满足触发条件,等到第2帧的数据的前几个字节填满缺失的帧后,触发解包操作。在检查包围的时候,报错响应。舍弃字节缺失帧,但是难以保证字节缺失帧的后几帧能顺利接收。而且出错和报错响应不同步。即报错响应出现在错误的下一帧。

    字节超出:字节超出的帧会及时响应,并且由于包尾错误,会立即响应报错并请求重发。

    解包过快:不会出现解包速度大于收包速度。因为数据满一个帧长度才会解包。


    2、DMA数组指向元素类型为帧结构体的链表

    触发条件:DMA计数值减到0(即已经收满一个帧的长度的数据)产生DMA中断,DMA中断中对List进行Push_back操作,增加一个element,然后将DMA的内存地址指向新的element的首地址。触发条件是List的size大于1(在没有收到任何报文之前,得有一个空element用于放置马上要到来的报文);

    解包操作:检查List第1个元素的包头包尾,如果正确,读取成员解包赋值,然后对List进行pop_front,直到list的size等于1.

    缓冲机制:链表天然的缓冲机制,唯一担心的是堆溢出,可以设置一个上限,在中断里判断。

    报错机制:

    帧错位:在包头检查中会发现,但是需要丢弃缓冲区内错位帧之后所有的帧。因为后边的必然都错位了。

    字节缺失:第2帧到来时,检查包尾时发现。同样存在报错响应不同步的问题。

    字节超出:报错同步响应。丢弃缓冲区中所有帧

    解包过快:不存在这个问题。理由同 方式1.


    3、DMA数组指向多倍于帧长度的数组首地址

    触发条件:缓冲队列非空。触发响应后,立即将缓冲队列memcpy到临时数组进行解包。同时清空队列。

    解包操作:在临时数组中搜索包头的第1个字节,一单满足,立即检查:包头第2字节,包尾是否在缓冲区长度内,包尾是否正确。如果4个条件均满足,立即开始解包赋值。完成后重复上一步,在数组中搜索第2个包头。直到最后在缓冲区末端,残留帧的前一部分,舍弃该无尾帧。

    缓冲机制:由缓冲队列作为缓冲。

    报错机制:

    帧错位:在临时数组中不存在帧错位的概念,帧错位完全可以被正确解包。

    字节缺失:在解包步骤中被检测到包尾有误,则请求重发。而且能同步响应。

    字节超出:同字节缺失

    解包过快:由于触发方式为缓冲队列非空。如果查询触发条件时,恰好接收了部分帧,则仍然能满足触发条件。那么此时这个接收了一部分的帧会作为字节缺失的帧被舍弃并进行报错


    小结:

    三种方式对比下来,第3种方式有着较优越的性能,而且能够很好地移植到PC机上实现。但是对于解包过快的问题,仍然需要讨论。


    字节缺失同步响应和解包过快的矛盾:

    问题可以被化简为:一个10字节的帧,解包时,如果包里只有9个字节,那这一帧到底是没发完还是字节缺失。

    如果使用“已收到大于10个字节的数据”作为解包触发条件,那么解包时永远有10个字节,判断最后一个字节是否是包尾,即可。但是字节缺失永远只能在下一帧响应。

    如果使用“缓冲区数据多于0”作为解包触发条件,虽然字节缺失能立即被响应,但是也有可能将未发完的帧误判。


    因此需要针对当前的应用进行分析。目前对于单片机的帧率和帧长度为:

    波特率:115200

    发送帧率:5f/s

    发送帧长:20 Bytes

    接收帧检测周期:1ms

    接收帧长度:10 Bytes


    传送1Byte数据,由于没有校验位,1个停止位,因此需要10bits。

    那么传输速率为11520B/s(约11KB/S),即传输1Byte需要86.8us(约0.1ms)。

    发送帧每一帧20Bytes,需要1.736ms(约2ms)

    接收帧每一帧10Bytes,需要0.858ms(约1ms)


    因此对于当前的情况下单片机的接收条件,1ms解包一次,完全不需要缓冲区,但是却有很大可能发生在帧截断。

    因此应该采用“已收到等于帧长度个字节的数据”作为触发条件。放弃字节缺失帧的同步响应。

    但是对于PC机端,如果同样为1ms间隔检测触发条件,接收帧的时常变为1.736毫秒,那么一个间隔内是必然收不满1帧的。

    因此同样可以采用“已收到等于帧长度个字节的数据”作为触发条件。放弃字节缺失帧的同步响应。

    但是对于Qt上的串口类,现在还没有摸清他的工作原理,尚无法讨论何种方法比较合适。


    /**********************************11月1日更新分割线****************************************/

    一个能够提高缺字节帧报错响应速度的方案:

    判断帧是丢字节还是未发完的区分方式其实是在时间上。

    比如之前提到的115200波特率,20Bytes的帧,其传送时间应该小于2ms。

    因此,当:接收缓冲区有数据,单数据未到达20Bytes时,若这种状态维持超过2ms,则说明传输已经完成,缺字节。

    而程序本身的step timer已经有了计时的功能。因此,实现方式如下。


    声明一个标志位1:FIFO队列有数据但不满帧长度。

    声明一个计数器1:标志位1的计数。

    当FIFO队列数据从0跳变到1时,set标志位1。

    CheckMailBox时,标志位1已置位,则将计数器1的值加1。

    由于20Bytes的帧在2ms内应该发送完。而解算周期为1ms。

    故,当计数器1的值大于2时,如果FIFO队列数据长度仍然没有达到帧长度,说明该包有数据丢失。set报错标志位。

    即可检测出丢字节的帧。
    ————————————————
    版权声明:本文为CSDN博主「不纯洁的锌」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/buchunjiedexin/article/details/49534735

    展开全文
  • 帧数据的是这样的: 主机发出的呼叫命令之间的发送间隔不能小于100ms,一个命令字节间发送间隔不能大于5ms; [color=#FF0000]字节序号[/color] [color=#FF0000] 值[/color] [color=#FF0000]功能描述[/color] ...
  • java串口通信解析

    千次阅读 2017-05-03 21:56:38
    串口通信解包是比较复杂的,解包的情况是根据发送方发送的各种情况进行正确的解析处理。 最开始我想的比较简单, 比如假如已知发送方发送完整的一,接收方收到后,先进行转义,然后进行CRC校验判断数据是否有误,...

    串口通信解包是比较复杂的,解包的情况是根据发送方发送的各种情况进行正确的解析处理。

    最开始我想的比较简单,

    比如假如已知发送方发送完整的一帧,接收方收到后,先进行转义,然后进行CRC校验判断数据是否有误,如果无误,就取出数据

    而这种想法考虑太欠缺了,如果不知道发送方发送的是否是完整的一帧数据或者是否存在正确的数据,

    那么首先应该对收到的一串数据进行搜帧,判断有几个首尾为7E的字段,然后分别依次处理,

    若是收到首为7E,而尾不是,则应该将其存到缓存中,等后面收到的数据出现首不为7E,尾为7E的时候将这两段拼起来进行解包处理。倘若只收到一半,后面没有数据了,则应做好超时处理,一段时间后清空缓存区。

    按着这种思想,无论发送端怎么发,接收方都能够正确解析收到的每一帧数据。

    展开全文
  • 串口通信同步问题

    千次阅读 2015-10-31 17:32:28
    封装STM32串口的底层时,遇到了串口帧同步的问题。虽然以前也遇到类似场合,写出来的代码基本能够解决问题,但是在逻辑上总是不能彻底的解释一些细节。 讲一下当前的需求: 由于代码想用在一个简单的PID闭环上,做...

    封装STM32串口的底层时,遇到了串口帧同步的问题。虽然以前也遇到类似场合,写出来的代码基本能够解决问题,但是在逻辑上总是不能彻底的解释一些细节。

    当前的工作环境:

    由于代码想用在一个简单的PID闭环上,做在线的参数整定。假设当前PID解算周期是1ms,即每1ms,做一次串口的收包,解包,Pid解算,数据采集,然后打包,发包。也就是说是固定步长的解包。

    串口的方案是开启收发的DMA以及DMA的中断。(坚决不考虑直接使用串口中断。一个字节中断一次太费资源)。DMA数组作为串口的FIFO队列(并不是真正意义上的队列)。

    当前的需求:

    1、时间节拍到来时,检查是否有收到数据。没有则跳出,有则进入下一步

    2、检查数据中的包格式,比如包头是否正确,帧长度是否对齐,CRC(目前还没有做进去)等

    3、包格式检查出错误,回包时添加标志位,声明包格式错误请求重发。包格式没有错误则进行解包并设置对应的寄存器和赋值。

    4、具有合理的接收缓冲区,大于缓冲区的数据进行放弃。

    5、能够及时检测出丢字节,多字节等帧长度出错的问题。


    几套尝试过的方案:

    1、DMA数组的长度和帧长度相等。

    触发条件:DMA计数值减到0(即已经收满一个帧的长度的数据)产生DMA中断,将触发标志位写1。PC机上可以通过开启一个线程监视缓冲区数量实现。

    解包操作:设置共用体,其中结构体为帧协议,同时公用一个u8 数组作为DMA数组。判断触发条件,若满足,读取共用体中的包头包尾,若正确,继续读取成员,解包赋值。

    缓冲机制:无。DMA设置为normal模式,计数减到0后即停止。有新的数据到来也不会被传入数组。PC机上可以手动关闭串口。

    报错机制:

    帧错位:在包头检查中会发现,舍弃当前帧,设置重发标志位请求重发。

    字节缺失:字节缺失的帧发送完成后不会满足触发条件,等到第2帧的数据的前几个字节填满缺失的帧后,触发解包操作。在检查包围的时候,报错响应。舍弃字节缺失帧,但是难以保证字节缺失帧的后几帧能顺利接收。而且出错和报错响应不同步。即报错响应出现在错误的下一帧。

    字节超出:字节超出的帧会及时响应,并且由于包尾错误,会立即响应报错并请求重发。

    解包过快:不会出现解包速度大于收包速度。因为数据满一个帧长度才会解包。


    2、DMA数组指向元素类型为帧结构体的链表

    触发条件:DMA计数值减到0(即已经收满一个帧的长度的数据)产生DMA中断,DMA中断中对List进行Push_back操作,增加一个element,然后将DMA的内存地址指向新的element的首地址。触发条件是List的size大于1(在没有收到任何报文之前,得有一个空element用于放置马上要到来的报文);

    解包操作:检查List第1个元素的包头包尾,如果正确,读取成员解包赋值,然后对List进行pop_front,直到list的size等于1.

    缓冲机制:链表天然的缓冲机制,唯一担心的是堆溢出,可以设置一个上限,在中断里判断。

    报错机制:

    帧错位:在包头检查中会发现,但是需要丢弃缓冲区内错位帧之后所有的帧。因为后边的必然都错位了。

    字节缺失:第2帧到来时,检查包尾时发现。同样存在报错响应不同步的问题。

    字节超出:报错同步响应。丢弃缓冲区中所有帧

    解包过快:不存在这个问题。理由同 方式1.


    3、DMA数组指向多倍于帧长度的数组首地址

    触发条件:缓冲队列非空。触发响应后,立即将缓冲队列memcpy到临时数组进行解包。同时清空队列。

    解包操作:在临时数组中搜索包头的第1个字节,一单满足,立即检查:包头第2字节,包尾是否在缓冲区长度内,包尾是否正确。如果4个条件均满足,立即开始解包赋值。完成后重复上一步,在数组中搜索第2个包头。直到最后在缓冲区末端,残留帧的前一部分,舍弃该无尾帧。

    缓冲机制:由缓冲队列作为缓冲。

    报错机制:

    帧错位:在临时数组中不存在帧错位的概念,帧错位完全可以被正确解包。

    字节缺失:在解包步骤中被检测到包尾有误,则请求重发。而且能同步响应。

    字节超出:同字节缺失

    解包过快:由于触发方式为缓冲队列非空。如果查询触发条件时,恰好接收了部分帧,则仍然能满足触发条件。那么此时这个接收了一部分的帧会作为字节缺失的帧被舍弃并进行报错


    小结:

    三种方式对比下来,第3种方式有着较优越的性能,而且能够很好地移植到PC机上实现。但是对于解包过快的问题,仍然需要讨论。


    字节缺失同步响应和解包过快的矛盾:

    问题可以被化简为:一个10字节的帧,解包时,如果包里只有9个字节,那这一帧到底是没发完还是字节缺失。

    如果使用“已收到大于10个字节的数据”作为解包触发条件,那么解包时永远有10个字节,判断最后一个字节是否是包尾,即可。但是字节缺失永远只能在下一帧响应。

    如果使用“缓冲区数据多于0”作为解包触发条件,虽然字节缺失能立即被响应,但是也有可能将未发完的帧误判。


    因此需要针对当前的应用进行分析。目前对于单片机的帧率和帧长度为:

    波特率:115200

    发送帧率:5f/s

    发送帧长:20 Bytes

    接收帧检测周期:1ms

    接收帧长度:10 Bytes


    传送1Byte数据,由于没有校验位,1个停止位,因此需要10bits。

    那么传输速率为11520B/s(约11KB/S),即传输1Byte需要86.8us(约0.1ms)。

    发送帧每一帧20Bytes,需要1.736ms(约2ms)

    接收帧每一帧10Bytes,需要0.858ms(约1ms)


    因此对于当前的情况下单片机的接收条件,1ms解包一次,完全不需要缓冲区,但是却有很大可能发生在帧截断。

    因此应该采用“已收到等于帧长度个字节的数据”作为触发条件。放弃字节缺失帧的同步响应。

    但是对于PC机端,如果同样为1ms间隔检测触发条件,接收帧的时常变为1.736毫秒,那么一个间隔内是必然收不满1帧的。

    因此同样可以采用“已收到等于帧长度个字节的数据”作为触发条件。放弃字节缺失帧的同步响应。

    但是对于Qt上的串口类,现在还没有摸清他的工作原理,尚无法讨论何种方法比较合适。


    /**********************************11月1日更新分割线****************************************/

    一个能够提高缺字节帧报错响应速度的方案:

    判断帧是丢字节还是未发完的区分方式其实是在时间上。

    比如之前提到的115200波特率,20Bytes的帧,其传送时间应该小于2ms。

    因此,当:接收缓冲区有数据,单数据未到达20Bytes时,若这种状态维持超过2ms,则说明传输已经完成,缺字节。

    而程序本身的step timer已经有了计时的功能。因此,实现方式如下。


    声明一个标志位1:FIFO队列有数据但不满帧长度。

    声明一个计数器1:标志位1的计数。


    当FIFO队列数据从0跳变到1时,set标志位1。

    CheckMailBox时,标志位1已置位,则将计数器1的值加1。

    由于20Bytes的帧在2ms内应该发送完。而解算周期为1ms。

    故,当计数器1的值大于2时,如果FIFO队列数据长度仍然没有达到帧长度,说明该包有数据丢失。set报错标志位。

    即可检测出丢字节的帧。



    展开全文
  • 串口通信中,只传输一个字节是简单的,但是如果要传送一个(多个字节),将面临以下问题:receiver从串口接收的是字节流,那它是如何知道的开始或结束呢?它又是如何知道这个有多长?真实的物理硬件是充满...
  • PC串口连续数据帧接收方法[复制链接]本帖最后由 lb8820265 于 2019-11-30 22:15 编辑本次分享内容比较硬核,只有在使用串口做高速数据通信时候才会遇到。串口可以说是目前最常用通信方式,双方约定好波特率,只需要...
  • 串口通信中,只传输一个字节是简单的,但是如果要传送一个(多个字节),将面临以下问题:receiver从串口接收的是字节流,那它是如何知道的开始或结束呢?它又是如何知道这个有多长?真实的物理硬件是充满...
  • 串口通信帧的同步方法(识别一帧数据的起始结束)  2012-07-08 23:12:10| 分类: 我的自学实践|举报|字号 订阅   引 言  串口通信是日前单片机和DSP等嵌入式系统...
  • 串口通信是单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线模块之间的一种非常重要且普遍使用的通信方式。在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同时还要处理...
  • 串口通信数据格式

    千次阅读 2020-09-17 12:21:38
    在串行通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送。 串口收发数据的单位:字节 (Byte) '', 1Byte = 8 bits , 串口收发数据格式一般为 :1bit ...
  • 串口通信是单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线模块之间的一种非常重要且普遍使用的通信方式。在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同时还要处理...
  • 串口通信是日前单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线模块之间的一种非常重要且普遍使用的通信方式在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同时...
  • 引 言串口通信是日前单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线模块之间的一种非常重要且普遍使用的通信方式在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同时...
  • 用于接收数据格式为五位头+文本格式的模块串口通信,可用于myrio,mydAQ等开发板。
  • 串口通信 数据抽象

    2018-12-18 11:04:00
    tx_retry会计数,在尝试 SCOM_4_TX_RETRY 后仍未响应,拆除请求数据帧。 2、栈式缓冲,解决业务数据不能及时响应时,不丢失云端业务数据。  做法:将需要请求的帧,存放不同的缓冲栈,com->TxBuf[SCOM_4_TX_...
  • Labview串口通信,可以实现对尾寻找,提取其中的有效信息,针对读取接收缓存区存在对数据以及尾截断的情况作了处理,欢迎大家分析参考
  • 串口通信帧的同步方法(识别一帧数据的起始结束) 转载地址:http://blog.163.com/ssou_1985/blog/static/2953203620126811121076/ 引言串口通信是日前单片机和DSP等嵌入式系统之间...
  • 所以,嵌入式系统中的串口通信虽然看似简单,但其中仍有许多问题值得研究,例如串口通信过程中的同步问题。本文针对该问题给出了逐次比较、基于FIFO队列和基于状态机的3种同步方法。通过测试、分析和比较得出,...
  • 引 言 串口通信是日前单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线...所以,嵌入式系统中的串口通信虽然看似简单,但其中仍有许多问题值得研究,例如串口通信过程中的同步问题。本文针对该问题给出了逐
  • 单片机串口通信帧协议设计 数据格式: 0 1 2 3 … n+2 n+3 n+4 0xaa n data[0] ...
  • 异步同步通信数据帧格式

    千次阅读 2020-07-10 13:52:52
    串口扫盲六:异步通信方式 </div> 串行通信可以分为两种类型:同步通信、异步通信. 1. 异步通信的特点及信息格式: 以起止式异步协议为例,下图显示的是起止式一帧数据的格式: 图1 起止式异步通信的特点是:...
  • 对于串口通信部分来说,单片机给计算机发送字符串好说,有多大的数组就发送多少个字节即可,但是单片机接收数据,接收多少个才应该是一完整的数据呢?数据接收的起点在哪里,结束在哪里? 我们编程的思路就是这样...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 693
精华内容 277
关键字:

串口通信数据帧