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

} void KeyTa sk(void) // 按键任务函 数,放在主函 数内 { if(0==vG u8KeySec) { return; //按键的触发 序号是 0 意味着无按 键触发 ,直接退出当 前函数,不执 行此函数下面 的代码 } switch(v Gu8KeySec) //根据不同的 按键触发序 号执行对 应的代码 { case 1 : //1 号按 键。K1 的独 立按键 //GtBigBuf ferUsart. u8…

100%1 / 836
};
unsigned char Gu8QueueReceUpdate=0; //1 代表“队列发送数据后,收到了新的数据”
struct StructBigBufferUsart GtBigBufferUsart;//此结构体变量专门用来控制读取大数组的通讯事件
volatile unsigned char vGu8BigBufferUsartTimerFlag=0; //过程控制的超时定时器
volatile unsigned int vGu16BigBufferUsartTimerCnt=0;
volatile unsigned char vGu8QueueSendTimerFlag=0; //队列发送的超时定时器
volatile unsigned int vGu16QueueSendTimerCnt=0;
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
volatile unsigned char vGu8KeySec=0;
unsigned char Gu8SendByteFinish=0; //发送一个字节完成的标志
unsigned char Gu8ReceBuffer[REC_BUFFER_SIZE]; //常规控制类的小内
unsigned char *pGu8ReceBuffer; //用来切换接收内存的“中转指针”
unsigned long Gu32ReceCntMax=REC_BUFFER_SIZE; //最大缓存
unsigned long Gu32ReceCnt=0; //接收缓存数组的下
unsigned char Gu8ReceStep=0; //接收中断函数里的步骤变量
unsigned char Gu8ReceFeedDog=1; //“喂狗”的操作变量
unsigned char Gu8ReceType=0; //接收的数据类型
unsigned char Gu8Rece_Xor=0; //接收的异或
unsigned long Gu32ReceDataLength=0; //接收的数据长度
unsigned char Gu8FinishFlag=0; //是否已接收完成一串数据的标
unsigned long *pu32Data; //用于数据转换的指
volatile unsigned char vGu8ReceTimeOutFlag=0;//通讯过程中字节之间的超时定时器的开关
volatile unsigned int vGu16ReceTimeOutCnt=0; //通讯过程中字节之间的超时定时器,“喂狗”的对象
void main()
{
SystemInitial();
Delay(10000);
PeripheralInitial();
while(1)
{
UsartTask(); //串口收发的任务函数
KeyTask();
}
}
void KeyTask(void) //按键任务函数,放在主函数内
{
if(0==vGu8KeySec)
{
return; //按键的触发序号是 0 意味着无按键触发,直接退出当前函数,不执行此函数下面的代码
}
switch(vGu8KeySec) //根据不同的按键触发序号执行对应的代码
{
case 1: //1 号按键。K1 的独立按键
//GtBigBufferUsart.u8Start 在开机初始化函数里必须初始化 0!这一步很关键!
if(0==GtBigBufferUsart.u8Start) //只有在还没有启动的情况下,才能启动
{
GtBigBufferUsart.u8Status=0; //通讯过程的状态 0 为初始状态
GtBigBufferUsart.u8Step=0; //通讯过程的步骤 0 为从当前开始的步骤
GtBigBufferUsart.u8Start=1; //通讯过程的启
}
vGu8KeySec=0; //响应按键服务处理程序后,按键编号必须清零,避免一致触
break;
}
}
/* 注释一:
* 每一个通讯事件都对应的一个独立的“通讯过程的控制涵数”,一个系统中有多少个通讯事件,就存在
* 多少个“通讯过程的控制涵数”。该函数负责某个通讯事件从开始到结束的整个过程。比如本节项目,
* 在通讯过程中,如果发现接收到的数据错误,则继续启动重发的机制。当发现接收到的累加字节数等于
* 预期想要接收的数量时,则结束这个通讯的事件
*/
void BigBufferUsart(void) //读取下位机大数组的“通讯过程的控制涵数”
{
static const unsigned char SCu8ReSendCntMax=3; //重发的次数
static unsigned long *pSu32Data; //用于数据与数组转换的指针
switch(GtBigBufferUsart.u8Step) //过程控制,我首选 switch 语句!
{
case 0:
if(1==GtBigBufferUsart.u8Start) //通讯过程的启动
{
//根据实际项目需要,在此 0 步骤里可以添加一些初始化相关的数据
GtBigBufferUsart.u8ReSendCnt=0; //重发计数器清零
GtBigBufferUsart.u8Step=1; //切换到下一
}
break;
//-----------先发送“读取下位机的数组容量的大小的指令”---------------------
//-----------EB 01 00 00 00 07 ED ---------------------
case 1:
GtBigBufferUsart.u8QueueSendBuffer[0]=0xeb; //数据
GtBigBufferUsart.u8QueueSendBuffer[1]=0x01; //数据类型 读取数组容量大小
pSu32Data=(unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2];
*pSu32Data=7; //数据长度 本条指令的数据总长是 7 个字节
//异或算法的函数
GtBigBufferUsart.u8QueueSendBuffer[6]=CalculateXor(GtBigBufferUsart.u8QueueSendBuffer,
6) ; //最后一个字节不纳入计算
//队列驱动函数的状态 0 为初始状态 1 为通讯成功 2 为通讯失败
GtBigBufferUsart.u8QueueStatus=0; //队列驱动函数的通讯状态
GtBigBufferUsart.u8QueueSendTrig=1;//队列驱动函数的发送的启
vGu8BigBufferUsartTimerFlag=0;
vGu16BigBufferUsartTimerCnt=2000;
vGu8BigBufferUsartTimerFlag=1; //过程控制的超时定时器的启动
GtBigBufferUsart.u8Step=2; //切换到下一步
break;
case 2: //发送之后,等待下位机返回的数据的状
if(1==GtBigBufferUsart.u8QueueStatus) //当前批次的接收到的数据成功
{
GtBigBufferUsart.u8ReSendCnt=0; //重发计数器清零
GtBigBufferUsart.u32AlreadySendSize=0; //实际已经发送的数据量清
GtBigBufferUsart.u32CurrentAddr=0; //当前批次需要发送的起始地址
GtBigBufferUsart.u32CurrentSize=10; //从当前批次起始地址开始发送的数据量
GtBigBufferUsart.u8Step=3; //切换到下一
}
else if(2==GtBigBufferUsart.u8QueueStatus) //当前批次的接收到的数据失败
{
GtBigBufferUsart.u8ReSendCnt++;
if(GtBigBufferUsart.u8ReSendCnt>=SCu8ReSendCntMax) //大于最大的重发次数
{
GtBigBufferUsart.u8Step=0;
GtBigBufferUsart.u8Start=0; //结束当前的过程通讯
GtBigBufferUsart.u8Status=2; //对外宣布“通讯失败”