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

case 0: //“前部 分的”数据头。接 头暗号 的步骤。 Gu8ReceBuf fer[0]=SB UF; //直接读取刚 接收完的一个 字节的数据 。 if(0xeb==G u8ReceBuf fer[0]) //等于 数据头 0xeb,接 头暗号吻合。 { Gu32Rece Cnt=1; //接收 缓存的下标 Gu8ReceS tep=1; //切换到 下一个步骤 ,接收其它有 效的数据 } break; case 1: //…

100%1 / 836
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)
{
case 0: //“前部分的”数据头。接头暗号的步骤。
Gu8ReceBuffer[0]=SBUF; //直接读取刚接收完的一个字节的数据
if(0xeb==Gu8ReceBuffer[0]) //等于数据头 0xeb,接头暗号吻合。
{
Gu32ReceCnt=1; //接收缓存的下标
Gu8ReceStep=1; //切换到下一个步骤,接收其它有效的数据
}
break;
case 1: //“前部分的”数据类型和长度
Gu8ReceBuffer[Gu32ReceCnt]=SBUF; //直接读取刚接收完的一个字节的数据。
Gu32ReceCnt++; //每接收一个字节,数组下标都自 1,为接收下一个数据做准
if(Gu32ReceCnt>=6) //前 6 个数据。接收完了“数据类型”和“数据长度”
{
Gu8ReceType=Gu8ReceBuffer[1]; //提取“数据类型”
//以下的数据转换,在第 62 节讲解过的指针法
pu32Data=(unsigned long *)&Gu8ReceBuffer[2]; //数据转换
Gu32ReceDataLength=*pu32Data; //提取“数据长度”
if(Gu32ReceCnt>=Gu32ReceDataLength) //靠“数据长度”来判断是否完成
{
Gu8FinishFlag=1; //接收完成标志“ 1”,通知主函数处理。
Gu8ReceStep=0; //及时切换回接头暗号的步
}
else //如果还没结束,继续切换到下一个步骤,接收“有效数据”
{
//本节只用到一个接收数组,把指针关联 Gu8ReceBuffer 本身的数组
pGu8ReceBuffer=(unsigned char *)&Gu8ReceBuffer[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; //及时清除发送中断的标志,避免一直无缘无故的进入中断。
Gu8SendByteFinish=1; //从 0 变成 1 通知主函数已经发送完一个字节的数据了。
}
}
void UsartSendByteData(unsigned char u8SendData) //发送一个字节的底层驱动函数
{
static unsigned int Su16TimeOutDelay; //超时处理的延时计时器
Gu8SendByteFinish=0; //在发送以字节之前,必须先把此全局变量的标志清零。
SBUF =u8SendData; //依靠寄存器 SBUF 作为载体发送一个字节的数据
Su16TimeOutDelay=0xffff; //超时处理的延时计时器装载一个相对合理的计时初始
while(Su16TimeOutDelay>0) //超时处理
{
if(1==Gu8SendByteFinish)
{
break; //如果 Gu8SendByteFinish 1,则发送一个字节完成,退出当前循环等待
}
Su16TimeOutDelay--; //超时计时器不断递
}
//Delay();//在实际应用中,当连续发送一堆数据时如果发现丢失数据,可以尝试在此增加延
}
//发送带协议的函数
void UsartSendMessage(const unsigned char *pCu8SendMessage,unsigned long u32SendMaxSize)
{
static unsigned long i;
static unsigned long *pSu32;
static unsigned long u32SendSize;
pSu32=(const unsigned long *)&pCu8SendMessage[2];
u32SendSize=*pSu32; //从带协议的数组中提取整包数组的有效发送长度
if(u32SendSize>u32SendMaxSize) //如果“有效发送长度”大于“最大限制的长度”,数据异常
{
return; //数据异常,直接退出当前函数,预防数组越界
}