从单片机基础到程序框架(全集 2019pdf版).pdf - 第819页
vGu8ReceTi meOutFlag =0; vGu16Rec eTimeOutCnt =RECE_TIME _OUT;//更新 一次“超时 检测的定时器” 的初值 vGu8ReceTi meOutFlag =1; } else if(Gu 8ReceStep >0&&0==vGu16 ReceTimeO utCnt) //超时, 并且步骤不 在接头暗号的 步骤 { Gu8ReceS tep=0; //串 口接…

vGu8QueueSendTimerFlag=0;
vGu16QueueSendTimerCnt=2000;
vGu8QueueSendTimerFlag=1; //队列发送的超时定时器
Su8Step=1;
}
// else if(...) //当有其它发送的指令时,可以在此处继续添加判断,越往下优先级越低
// else if(...) //当有其它发送的指令时,可以在此处继续添加判断,越往下优先级越低
break;
case 1: //发送之后,等待下位机的应答。驱动层,只管有没有应答,不管应答对不对。
if(1==Gu8QueueReceUpdate) //如果“接收数据后的处理涵数”接收到应答数据
{
Su8Step=0; //返回上一步继续处理其它“待发送的指令”
}
if(0==vGu16QueueSendTimerCnt) //发送指令之后,等待应答超时
{
Su8Step=0; //返回上一步继续处理其它“待发送的指令”
}
break;
}
}
/* 注释三:
* 整个项目中只有一个“接收数据后的处理涵数”,负责即时处理当前接收到的数据。
*/
void ReceDataHandle(void) //接收数据后的处理涵数
{
static unsigned long *pSu32Data; //数据转换的指针
static unsigned long i;
static unsigned char Su8Rece_Xor=0; //计算的“异或”
static unsigned long Su32CurrentAddr; //读取的起始地址
static unsigned long Su32CurrentSize; //读取的发送的数据量
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: //读取下位机的数组容量的大小
Gu8QueueReceUpdate=1; //告诉“队列驱动函数”收到了新的应答数据
Gu8Rece_Xor=Gu8ReceBuffer[Gu32ReceDataLength-1]; //提取接收到的“异或”
Su8Rece_Xor=CalculateXor(Gu8ReceBuffer,Gu32ReceDataLength-1); //计算“异或”
if(Gu32ReceDataLength>=11&& //接收到的数据长度必须大于或者等于 11 个字节
Su8Rece_Xor==Gu8Rece_Xor) //验证“异或”,“计算的”与“接收的”是否一致
{
pSu32Data=(unsigned long *)&Gu8ReceBuffer[6]; //数据转换。
GtBigBufferUsart.u32NeedSendSize=*pSu32Data; //提取将要接收数组的大小
GtBigBufferUsart.u8QueueStatus=1; //告诉“过程控制函数”,当前通讯成功
}
else
{
GtBigBufferUsart.u8QueueStatus=2; //告诉“过程控制函数”,当前通讯失败
}
break;
case 0x02: //读取下位机的分段数据
Gu8QueueReceUpdate=1; //告诉“队列驱动函数”收到了新的应答数据
Gu8Rece_Xor=Gu8ReceBuffer[Gu32ReceDataLength-1]; //提取接收到的“异或”
Su8Rece_Xor=CalculateXor(Gu8ReceBuffer,Gu32ReceDataLength-1); //计算“异或”
pSu32Data=(unsigned long *)&Gu8ReceBuffer[6]; //数据转换。
Su32CurrentAddr=*pSu32Data; //读取的起始地址
pSu32Data=(unsigned long *)&Gu8ReceBuffer[6+4]; //数据转换。
Su32CurrentSize=*pSu32Data; //读取的发送的数据量

if(Gu32ReceDataLength>=11&& //接收到的数据长度必须大于或者等于 11 个字节
Su8Rece_Xor==Gu8Rece_Xor&& //验证“异或”,“计算的”与“接收的”是否一致
Su32CurrentAddr==GtBigBufferUsart.u32CurrentAddr&& //验证“地址”,相当于验证“动态密匙”
Su32CurrentSize==GtBigBufferUsart.u32CurrentSize) //验证“地址”,相当于验证“动态密匙”
{
for(i=0;i<Su32CurrentSize;i++)
{
//及时把接收到的数据存储到 Gu8ReceTable 数组
Gu8ReceTable[Su32CurrentAddr+i]=Gu8ReceBuffer[6+4+4+i];
}
GtBigBufferUsart.u8QueueStatus=1; //告诉“过程控制函数”,当前通讯成功
}
else
{
GtBigBufferUsart.u8QueueStatus=2; //告诉“过程控制函数”,当前通讯失败
}
break;
}
Gu8FinishFlag=0; //上面处理完数据再清零标志,为下一次接收新的数据做准备
}
}
void UsartTask(void) //串口收发的任务函数,放在主函数内
{
BigBufferUsart(); //读取下位机大数组的“通讯过程的控制涵数”
QueueSend(); //发送的队列驱动涵数
ReceDataHandle(); //接收数据后的处理涵数
}
void usart(void) interrupt 4 //串口接发的中断函数,中断号为 4
{
if(1==RI) //接收完一个字节后引起的中断
{
RI = 0; //及时清零,避免一直无缘无故的进入中断。
if(0==Gu8FinishFlag) //1 代表已经完成接收了一串新数据,并且禁止接收其它新的数据
{
Gu8ReceFeedDog=1; //每接收到一个字节的数据,此标志就置 1 及时更新定时器的值。
switch(Gu8ReceStep)
{