博主在最近的一次项目中需要使用格式帧的传输以及累加校验的方式,在以前大多数的情况下我们都是一位开始位一位结束位8位数据位而且无校验,在现在的项目实现主动上传的目的帧格式,主动上传的间隔为用户自己设定,需要如下编写:
输出数据:
帧头 | 序列号 | A类型 | A型号 | B类型 | 版本号 | 长度 | 数据 | 校验 | 帧尾 |
0xFE | 8B | 1B | 1B | 2B | 3B | 1B |
| 1B | 0xFA |
长度:指数据的长度。
校验:指累加和校验
那么在写这个主动上传的帧格式的时候,我们必须先定义一个合适的数据结构用来存储数据,于是博主在一开始定义了一个数组。u8 rxbuf[100],txbuf[40]; //串口数据的缓冲数据
用这两个数据缓存来存储数据,定时器的定时由用户给的需求手册,使用定时器0或者定时器2定时,触发标志位的改变,然后使用填充串口中断首字母的方式触发发送数据帧的中断,发送一帧数据。
总体思路如上,具体实现我们还要考虑一个累加校验的校验位来进行校验,累加校验是一种基本的校验方式,将数据累加起来使用十六进制储存编成一个校验位,并发送给上位机。
博主采用的方法是通过帧格式来确定校验位处于帧的哪一个数据段,编写一个简单函数返回帧校验位,具体的实现函数如下:
u16 getaddcheck(u8 txbufsave[],int i)
{
u16 addcheck=0x0000;
addcheck=txbufsave[i]+txbufsave[i+1];
return addcheck;
}
这个函数的功能便是返回一个校验累加数的方法;
定时器的设置在博主的博客已经讲过了,贴上一个简单的定时2.5s的代码
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //在这里直接打开中断向量地址TOV0 所以程序中没有涉及到TIFR寄存器的操作
{
// Place your code here
TCNT0=0x3C; //重新赋值
t0cnt++; //外部定义了一个8位的计数量
#asm("wdr")
if(t0cnt>100) //2min
{
t0cnt=0;
readvalueflag=1;
}
}
至此,代码的思路便很清晰了,定时完毕后改变定时器的标志readvalueflag,然后在主函数里进行帧发送。
if(readvalueflag)
{
sendbasicflag=0;//清零 序列号20170320010200020001
Tx; //发送使用C1端口发送 发送缓冲区使用20个字节,每个字节8位形式数组
txbuf[0]=0xFE; //帧头
。
。
。
txbuf[30]=getaddcheck(txbuf,28)>>8; //数据校验高八位
txbuf[31]=getaddcheck(txbuf,28); //数据校验低八位
txbuf[32]=0xFA; //帧结束
txcnt=33; //显示发送了几个字节
UDR=txbuf[0]; //中断发送填充首字节 发送一个首字节
}
完毕