如何实现从串口接收一串不定长度的数据

如何实现从串口接收一串不定长度的数据,第1张

这个问题的提法本身就有问题,串口受到的是数据流本身就没有长度的问题.关键是接收端如何处理数据,或者说如何按照规则处理数据流的分组.总结一下就三个方法1.按时间分,视两段数据中间的停顿为分割依据,这方法不会有问题开销也小,缺点就是停顿时间降低了传输速率2.按特定标识分割,每个段前面或后面加上特定的识别符号,识别符号过短可能会误判(比如插拔接口时会乱数据)3.按特定长度区分段,比如人为规定好每8个字节一包,这个方法开销小速率高,但是只要有一个字节错后面全错.当然也可组合使用1,2,3再加校验,要结合你的硬件出错概率带宽占用...综合考虑.

串口接收数据的时候  接收一个字节进入一次中断,此时SBUF寄存器里面存放的是接收的数据,只要把SBUF里面的数据取出来就可以了,同时中断里要把RI清零,以便下次进入中断接收数据,

上面数据的是一个字节一个字节的接收数据,  接收一串数据,有成一帧数据的时候,怎么接收呢

。定义一个足够长的数组,比如 一帧数据  最长会有20个字节,那么定义的数组长度,要大于等于20 ;

定义一个计数变量,在中断里 对接收的数据进行计数  ; 例如

void interruptUartS1() interrupt 4

{

if(RI)

{

RI = 0

bufS1Rxd[cntS1Rxd++] = SBUF

idletmrS1 = 0

}

if(TI)

{

TI = 0

flagS1Txd = 1

}

}

bufS1Rxd   就是定义的一个数组,用于存放数据, cntS1Rxd 就是计数变量,用于记录接收的数据长度,

3,。那么如何判断一帧数据什么时候接收完毕呢 , 这里就用到了idletmr这个变量,,这个就是在定时器中端里   不停的累加的一个计时变量,,定时器初值1ms     累加一次就是1ms 的时间,  一般是判断间隔30ms左右的时间  没有接收数据,那么 就表示一帧数据接收完毕,,,这个间隔时间跟波特率有关的,,因为,,波特率就是数据传输的速度,,,

void interrupttimer0() interrupt 1

{

static uint16 t = 0

t++

if(t >= 1000)

{

t = 0

}

if(idletmrS1 <10)

{

idletmrS1++

if(idletmrS1 >= 10)

{

CmdArrivedS1 = 1

}

}

}

上面就是定时器中断的内容, 采用的是16位自动重装模式,是STC15系列单片机独有的定时器模式,   我这里是9600的波特率,10ms没有接收数据就会把 CmdArrived 这个标志位置1 ,用此判断  已经一帧数据接收完毕, 如果在10ms以内接收到数据,就会把idletmr清零,重新计时的

4, 一般防止干扰引起的数据错误,会加入校验位,这里有奇偶校验,CRC校验==  ,很多校验方式, 一般采用CRC校验,,还有更简单的和校验,,  和校验就是把一帧数据中的不是校验位的数据  累加起来,取和的低8位,这个就是和校验的高字节,,和校验的低字节就是 高字节的补码‘

以上就是简单的介绍些一帧数据的接收原理,,

实际应用中, 还会有加入固定数据 进行判断,==之类的校验,,都是防止数据被干扰


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/6423582.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-21
下一篇 2023-03-21

发表评论

登录后才能评论

评论列表(0条)

保存