从单片机基础到程序框架(全集 2019pdf版).pdf - 第760页

} void BeepC lose(void ) { P3_4=1; } void Voice Scan(void ) { static u nsigned cha r Su8Lock= 0; if(1==vGu8 BeepTimer Flag&&vGu16B eepTimerC nt>0) { if(0==Su 8Lock) { Su8Lock=1; BeepOpen (); } else { vGu16Bee …

100%1 / 836
unsigned char u8_TMOD_Temp=0;
//以下是定时 0 的中断的配
TMOD=0x01;
TH0=0xfc;
TL0=0x66;
EA=1;
ET0=1;
TR0=1;
//以下是串口接收中断的配
//串口的波特率与内置的定时器 1 直接相关,因此配置此定时器 1 就等效于配置波特率。
u8_TMOD_Temp=0x20; //即将把定时 1 设置为:工作方式 2,初值自动重装的 8 位定时器。
TMOD=TMOD&0x0f; //此寄存器低 4 位是跟定时器 0 相关, 4 位是跟定时 1 相关。先清零定时器 1。
TMOD=TMOD|u8_TMOD_Temp; //把高 4 位的定时器 1 填入 0x2,低 4 位的定时器 0 保持不变。
TH1=256-(11059200L/12/32/9600); //波特率为 9600。11059200 代表晶振 11.0592MHz,
TL1=256-(11059200L/12/32/9600); //L long 的长类型数据。根据芯片手册提供的计算公式
TR1=1; //开启定时器 1
SM0=0;
SM1=1; //SM0 SM1 的设置:选择 10 位异步通信,波特率根据定时器 1 可变
REN=1; //允许串口接收数据
//为了保证串口中断接收的数据不丢失,必须设 IP = 0x10,相当于把串口中断设置为最高优先级,
//这个时候,串口中断可以打断任何其他的中断服务函数实现嵌套,
IP =0x10; //把串口中断设置为最高优先级,必须的
ES=1; //允许串口中断
EA=1; //允许总中断
}
void Delay(unsigned long u32DelayTime)
{
for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial(void)
{
}
void BeepOpen(void)
{
P3_4=0;
}
void BeepClose(void)
{
P3_4=1;
}
void VoiceScan(void)
{
static unsigned char Su8Lock=0;
if(1==vGu8BeepTimerFlag&&vGu16BeepTimerCnt>0)
{
if(0==Su8Lock)
{
Su8Lock=1;
BeepOpen();
}
else
{
vGu16BeepTimerCnt--;
if(0==vGu16BeepTimerCnt)
{
Su8Lock=0;
BeepClose();
}
}
}
}
第一百二十九节: 接收带“动态密匙”与“累加和”校验数据的串口程序框架。
【129.1 “累加和”与“动态密匙”
上一节讲了串口基本的程序框架,但是没有讲到校验。校验在很多通信项目中是必不可少的。比如,
事关金融或者生命安全的项目,是不允许有任何的数据丢失或错误的;在容易受干扰的工业环境或者在无
线通信的项目中,这些项目往往容易丢失数据还有一种常见的人为过失是,在编写程序的层面,因为超时
重发的时间与从机不匹配,导致反馈的信息延时而造成数据丢失如果这种情况也加上校验,通信会稳定可
靠很多。
上一节讲到“数据头,数据类型,数据长度,其它数据”这四个元素,本节在此基础上增加两个校验
的元素,分别是“动态密匙”与“累加和”动态密匙”占用 2 个字节“累加和”占用 1 个字节,因此,
这两个元素一共占用最后面的 3 个字节。分析如下:
数据头(EB):占 1 个字节,作为“起始字节”,起到“接头暗号”的作用,平时用来过滤无关的数据。
数据类型(01):占用 1 个字节。数据类型是用来定义这串数据的用途。
数据长度(00 00 00 0B):占 4 个字节。用来告诉通信的对方,这串数据一共有多少个字节。
其它数据(03 E8):此数据根据不同的“数据类型”可以用来做不同的用途,根据具体的项目而定。
动态密匙(00 01):这两个字节代表一个 unsigned int 类型的数据,数据范围是 0 65535,但是考
虑到数据更加安全可靠,一般丢弃了首尾的 0(十六进制 00 00) 65535(十六进制的 FF FF)只保
1 65534 的变化。大部分的通信模型都是主机对从机“一问一应答”模式,也就是,主机每发送一条
指令给从机,从机才返回一条消息作为应答。如果主机发送了信息后,在规定的时间内,没有收到从机的应
答指令,主机就继续发送信息给从机,但是此时,从机本来应该应答主机当前指令的可能因为某种情况导
致反馈的信息发生了延时,导致此时应答的数据是主机的上一条指令,从而造成“一问一应答”的数据帧发
送了错位,这种情况加上“动态密匙就能使问题得到有效的解决。主机每发送一条信息,信息里都携带了
2 个字节的“动态密匙”从机每收到主机的一条信息在应答此信息时都把收到的“动态密匙”原封不动的
反馈给主机,主机再查看发送的“动态密匙”与接收到的“动态密匙”是否一致,以此来判断应答数据是否
有效。“动态密匙”像流水号一样,每发送一次指令后都累加 1,不断发生变化, 1 65534,依次循环
这是数据校验的一种方式
累加和(E3)“累加和”放在数据串的最后一个字节,是前面所有字节的累加之和(不包括自己本身
字节)累加的结果高于一个字节的那部分自动溢出丢掉,只保留低 8 位的一个字节的数据。比如:本例子
中,数据串是:EB 01 00 00 00 0B 03 E8 00 01 E3。其中最后一个字节 E3 就是“累加和”,前面所有字节
相加等于十六进制的 0x1E3只保留低 8 位的一个字节的数据,因此为十六进制的 0xE3。验证“累加和”
方法,可以借用电脑“附件”自带的“计算器”软件来实现,打开“计算器”软件后,在“查看”的下拉菜
单里,选择“程序员”,然后选择“十六进制”。不管是主机还是从机,每接收到一串数据后都要自己计算
一次“累加和”把自己计算得到的“累加和”与接收到的最后一个字节的累加和”进行对比,来判断
收到的数据是否发生了丢失或者错误。
【129.2 程序例程。