从单片机基础到程序框架(全集 2019pdf版).pdf - 第822页
} } } else //发送数据引 起的中 断 { TI = 0; //及时 清除发送中断 的标志,避免 一直无 缘无故的进入 中断。 Gu8SendB yteFinish=1 ; //从 0 变成 1 通知 主函数已经发 送完一个字节 的数据了。 } } void Usart SendByteD ata(unsigned c har u8Sen dData) //发送 一个字 节的底层驱动 函数 { static u nsigned…

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; //数据异常,直接退出当前函数,预防数组越界
}

for(i=0;i<u32SendSize;i++) //u32SendSize 为发送的数据长度
{
UsartSendByteData(pCu8SendMessage[i]); //基于“发送单字节的最小接口函数”来实现的
}
}
unsigned char CalculateXor(const unsigned char *pCu8Buffer, //此处加 const 代表数组“只读”
unsigned long u32BufferSize) //参与计算的数组的大小
{
unsigned long i;
unsigned char Su8Rece_Xor;
Su8Rece_Xor=pCu8Buffer[0]; //提取数据串第“i=0”个数据作为异或的原始数据
for(i=1;i<u32BufferSize;i++) //注意,这里是从第“i=1”个数据开始
{
Su8Rece_Xor=Su8Rece_Xor^pCu8Buffer[i]; //计算“异或”
}
return Su8Rece_Xor; //返回运算后的异或的计算结果
}
//比较两个数组的是否相等。返回 1 代表相等,返回 0 代表不相等
unsigned char CmpTwoBufferIsSame(const unsigned char *pCu8Buffer_1,
const unsigned char *pCu8Buffer_2,
unsigned long u32BufferSize) //参与对比的数组的大小
{
unsigned long i;
for(i=0;i<u32BufferSize;i++)
{
if(pCu8Buffer_1[i]!=pCu8Buffer_2[i])
{
return 0; //只要有一个不相等,则返回 0 并且退出当前函数
}
}
return 1; //相等
}
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock1; //1 号按键的自锁
static unsigned int Su16KeyCnt1; //1 号按键的计时器
//1 号按键
if(0!=KEY_INPUT1)//IO 是高电平,说明按键没有被按下,这时要及时清零一些标志位
{