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

} } void Usart Task(void ) //串口接收的 任务函数,放 在主函 数内 { static u nsigned in t *pSu16D ata; //数据 转换的指针 static u nsigned in t Su16Dat a; //转换后的数 据 static u nsigned in t i; static u nsigned ch ar Su8RecZZ =0; //计算的“ 异或” if(1==Gu…

100%1 / 836
//以下的数据转换,在第 62 节讲解过的指针法
pu32Data=(unsigned long *)&Gu8ReceBuffer[2]; //数据转换
Gu32ReceDataLength=*pu32Data; //提取“数据长度”
if(Gu32ReceCnt>=Gu32ReceDataLength) //靠“数据长度”来判断是否完成
{
Gu8FinishFlag=1; //接收完成标志“ 1”,通知主函数处理。
Gu8ReceStep=0; //及时切换回接头暗号的步
}
else //如果还没结束,继续切换到下一个步骤,接收“有效数据”
{
//以下几行代码是本节的破题关键!!!
if(0x02==Gu8ReceType) //如果是文件类,把指针关联到 Gu8FileBuffer
{
pGu8ReceBuffer=(unsigned char *)&Gu8FileBuffer[0];//下标 0
Gu32ReceCntMax=FILE_BUFFER_SIZE+6; //最大缓存
}
else //如果是常规类,继续把指针关联 Gu8ReceBuffer 本身的数组
{
pGu8ReceBuffer=(unsigned char *)&Gu8ReceBuffer[6];//下标 6
Gu32ReceCntMax=REC_BUFFER_SIZE; //最大缓存
}
Gu8ReceStep=2; //切换到下一个步骤
}
}
break;
case 2: //“后部分的”数据
pGu8ReceBuffer[Gu32ReceCnt-6]=SBUF; //这里的指针就是各种不同内存的化身!!!
Gu32ReceCnt++; //每接收一个字节,数组下标都自 1,为接收下一个数据做准
//靠“数据长度”来判断是否完成。也不允许超过数组的最大缓存的长
if(Gu32ReceCnt>=Gu32ReceDataLength||Gu32ReceCnt>=Gu32ReceCntMax)
{
Gu8FinishFlag=1; //接收完成标志“置 1”,通知主函数处理。
Gu8ReceStep=0; //及时切换回接头暗号的步骤
}
break;
}
}
}
else //发送数据引起的中
{
TI = 0; //及时清除发送中断的标志,避免一直无缘无故的进入中断。
//以下可以添加一个全局变量的标志位的相关代码,通知主函数已经发送完一个字节的数据了。
}
}
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;
}