从单片机基础到程序框架(全集 2019pdf版).pdf - 第828页
unsigned c har Gu8Se ndByteFinish =0; //发送一个字 节完成的 标志 unsigned c har Gu8Re ceBuffer[REC _BUFFER_S IZE]; //常规 控制类的小内 存 unsigned c har *pGu8 ReceBuffer; //用来 切换接收内存 的“中转 指针” unsigned l ong Gu32R eceCntMax=RE C_BUFFER_ SIZE…

void T0_time(); //定时器的中断函数
void QueueSend(void); //发送的队列驱动涵数
void ReceDataHandle(void); //接收数据后的处理涵数
void UsartTask(void); //串口收发的任务函数,放在主函数内
unsigned char CalculateXor(const unsigned char *pCu8Buffer, //异或的算法的函数
unsigned long u32BufferSize);
void UsartSendByteData(unsigned char u8SendData); //发送一个字节的底层驱动函数
//发送带协议的函数
void UsartSendMessage(const unsigned char *pCu8SendMessage,unsigned long u32SendMaxSize);
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;
//下面表格数组的数据与上位机的表格数据一模一样,目的用来让上位机检测接收到的数据是否正确
code unsigned char Cu8TestTable[]=
{
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,
0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,
0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,
0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,
0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,
0x51,0x52,0x53,0x54,0x55,0x56,0x57
};
//把一些针对某个特定事件的全局变量放在一个结构体内,可以让全局变量的分类更加清晰
struct StructBigBufferUsart //应答读取大数组的通讯过程的结构体
{
unsigned char u8QueueSendTrig;//队列驱动函数的发送的启动
unsigned char u8QueueSendBuffer[30]; //队列驱动函数的发送指令的数组
unsigned char u8QueueStatus; //队列驱动函数的通讯状态 0 为初始状态 1 为通讯成功 2 为通讯失败
};
unsigned char Gu8QueueReceUpdate=0; //1 代表“队列发送数据后,收到了新的数据”
struct StructBigBufferUsart GtBigBufferUsart;//此结构体变量专门用来应答读取大数组的通讯事件
volatile unsigned char vGu8QueueSendTimerFlag=0; //队列发送的超时定时器
volatile unsigned int vGu16QueueSendTimerCnt=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(); //串口收发的任务函数
}
}
/* 注释一:
* 整个项目中只有一个“发送的队列驱动涵数”,负责“通讯管道的占用”的分配,负责数据的具体发
* 送。当同时存在很多“待发送”的请求指令时,此函数会根据“if ,else if...”的优先级,像队列一
* 样安排各指令发送的先后顺序,确保各指令不会发生冲突。
*/
void QueueSend(void) //发送的队列驱动涵数
{
static unsigned char Su8Step=0;
switch(Su8Step)
{
case 0: //分派即将要发送的任务
if(1==GtBigBufferUsart.u8QueueSendTrig)
{

GtBigBufferUsart.u8QueueSendTrig=0; //及时清零。驱动层,不管结果,只发一次。
Gu8QueueReceUpdate=0; //接收应答数据的状态恢复初始值
//发送带指令的数据
UsartSendMessage((const unsigned char *)&GtBigBufferUsart.u8QueueSendBuffer[0],
30);
//注意,这里是从机应答主机的数据,不需要等待返回的数据,因此不需要切换 Su8Step
}
// 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) //每被“喂一次狗”,就及时更新一次“超时检测的定时器”的初值