从单片机基础到程序框架(全集 2019pdf版) - 第787页
if(Su8RecZ Z==Gu8Rec eZZ) //验证“异 或” , “计算 的”与“接收 的”是否 一致 { pSu16Dat a=(unsigned i nt *)&Gu 8ReceBuffer [6]; //数据转换 。 Su16Data =*pSu16Data ; //提取“蜂鸣 器声音的长度 ” vGu8Beep TimerFlag=0 ; vGu16Bee pTimerCnt=S u16Data; //让蜂 鸣…

}
}
void UsartTask(void) //串口接收的任务函数,放在主函数内
{
static unsigned int *pSu16Data; //数据转换的指针
static unsigned int Su16Data; //转换后的数据
static unsigned int i;
static unsigned char Su8RecZZ=0; //计算的“异或”
if(1==Gu8ReceFeedDog) //每被“喂一次狗”,就及时更新一次“超时检测的定时器”的初值
{
Gu8ReceFeedDog=0;
vGu8ReceTimeOutFlag=0;
vGu16ReceTimeOutCnt=RECE_TIME_OUT;//更新一次“超时检测的定时器”的初值
vGu8ReceTimeOutFlag=1;
}
else if(Gu8ReceStep>0&&0==vGu16ReceTimeOutCnt) //超时,并且步骤不在接头暗号的步骤
{
Gu8ReceStep=0; //串口接收数据的中断函数及时切换回接头暗号的步骤
}
if(1==Gu8FinishFlag) //1 代表已经接收完毕一串新的数据,需要马上去处理
{
switch(Gu8ReceType) //接收到的数据类型
{
case 0x01: //常规控制类的小内存。驱动蜂鸣器
//以下的数据转换,在第 62 节讲解过的指针法
pSu16Data=(unsigned int *)&Gu8ReceBuffer[Gu32ReceDataLength-3]; //数据转换
Gu16ReceYY=*pSu16Data; //提取“动态密匙”。本例子中暂时不做返回应答的处理
Gu8ReceZZ=Gu8ReceBuffer[Gu32ReceDataLength-1]; //提取接收到的“异或”
Su8RecZZ=Gu8ReceBuffer[0]; //提取数据串第“i=0”个数据作为异或的原始数据
for(i=1;i<(Gu32ReceDataLength-1);i++) //注意,这里是从第“i=1”个数据开始
{
Su8RecZZ=Su8RecZZ^Gu8ReceBuffer[i]; //计算“异或”
}

if(Su8RecZZ==Gu8ReceZZ) //验证“异或”,“计算的”与“接收的”是否一致
{
pSu16Data=(unsigned int *)&Gu8ReceBuffer[6]; //数据转换。
Su16Data=*pSu16Data; //提取“蜂鸣器声音的长度”
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=Su16Data; //让蜂鸣器鸣叫
vGu8BeepTimerFlag=1;
}
break;
case 0x02: //文件类的大内存。驱动蜂鸣器。
//以下的数据转换,在第 62 节讲解过的指针法
pSu16Data=(unsigned int *)&Gu8ReceBuffer[Gu32ReceDataLength-3]; //数据转换
Gu16ReceYY=*pSu16Data; //提取“动态密匙”。本例子中暂时不做返回应答的处理
//注意,请留意以下代码文件类内存数组 Gu8FileBuffer 的下标位置
Gu8ReceZZ=Gu8FileBuffer[Gu32ReceDataLength-1-6]; //提取接收到的“异或”
//前面 6 个字节是“前部分的”[数据头,数据类型,数据长度]
Su8RecZZ=Gu8ReceBuffer[0]; //提取数据串第“i=0”个数据作为异或的原始数据
for(i=1;i<6;i++) //注意,这里是从第“i=1”个数据开始
{
Su8RecZZ=Su8RecZZ^Gu8ReceBuffer[i]; //计算“前部分的”“异或”
}
//6 个字节之后是“后部分的”“文件类专用的数据”
for(i=0;i<(Gu32ReceDataLength-1-6);i++)
{
Su8RecZZ=Su8RecZZ^Gu8FileBuffer[i]; //计算“后部分的”“异或”
}
if(Su8RecZZ==Gu8ReceZZ) //验证“异或”,“计算的”与“接收的”是否一致
{
pSu16Data=(unsigned int *)&Gu8FileBuffer[0]; //数据转换。此处下标 0!
Su16Data=*pSu16Data; //提取“蜂鸣器声音的长度”
vGu8BeepTimerFlag=0;
vGu16BeepTimerCnt=Su16Data; //让蜂鸣器鸣叫
vGu8BeepTimerFlag=1;
}

break;
}
Gu8FinishFlag=0; //上面处理完数据再清零标志,为下一次接收新的数据做准备
}
}
void T0_time() interrupt 1
{
VoiceScan();
if(1==vGu8ReceTimeOutFlag&&vGu16ReceTimeOutCnt>0) //通信过程中字节之间的超时定时器
{
vGu16ReceTimeOutCnt--;
}
TH0=0xfc;
TL0=0x66;
}
void SystemInitial(void)
{
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 的长类型数据。根据芯片手册提供的计算公式。