关于51单片机串口1发送完整的数据包
在参考这样的协议的条件下我们想发送一套完整的数据包该如何发送呢?可以设计这样的程序。
1. 串行口1接收特定包头数据包函数。
参数: Uart_Rec_Data:串口接收到的数据 ; USER_Get_DataPacket: 数据存储目标数组。
返回: 0:未接收到完整的数据包; 1:接收到完整的数据包。
注:数组 USER_Get_DataPacket[2] 代表的是数据段的长度,通过【 数据段长度 + (地址,命令,数据长度标记码以及校验码的个数之和)= 数据包位的总个数】 及可判断数据包是否完整。
static uint8_t USER_Uart_1_Receive_DataPacket(uint8_t Uart_Rec_Data, uint8_t *USER_Get_DataPacket)
{static uint8_t DataPacket_Sequence = 0; //定义数据包顺序静态变量并赋值为“0”static uint16_t i = 3; //定义数据包存储位置静态变量并赋值为“3”switch (DataPacket_Sequence){case 0:if (Uart_Rec_Data == 0x01) //判断数据包第0个数据{DataPacket_Sequence = 1; //跳转到下一个步骤USER_Get_DataPacket[0] = Uart_Rec_Data; //将数据包第0个数据存入数组第0位}elseDataPacket_Sequence = 0; //维持在本步骤break;case 1:if (Uart_Rec_Data == 0x03) //判断数据包第1位数据{DataPacket_Sequence = 2; //跳转到下一个步骤USER_Get_DataPacket[1] = Uart_Rec_Data; //将数据包第1个数据存入数组第1位}elseDataPacket_Sequence = 0; //跳转到第0步骤break;case 2:USER_Get_DataPacket[2] = Uart_Rec_Data; //将数据包中表示有效数据个数值存入数组第2位DataPacket_Sequence = 3; //跳转到下一个步骤break;case 3:USER_Get_DataPacket[i] = Uart_Rec_Data; //将数据包中有效数据存入数组第i位i++;if (i >= (USER_Get_DataPacket[2] + 5)) //判断接收有效数据个数是否完成//{i = 3; //数据包存储位置变量重新赋值为“3”DataPacket_Sequence = 0; //跳转到第0步骤return 1; //接收到完整的数据包}break;default:break;}return 0; //未接收到完整的数据包
}
2. MCU外设异步串行通信口Uart_1中断服务函数。
对串口1是否接收到数据进行判断以及对数据进行读取。
void MCU_Uart_1_Isr() interrupt 4
{uint8_t Uart_1_R_Data = 0; //定义串行口1数据接收缓存器数据读取变量并赋值为“0”if (RI) //判断串行通信口Uart_1是否接收到数据{RI = 0; //清除串行通信口Uart_1接收数据标志位RI清“0”Uart_1_R_Data = SBUF; //读出串行通信口Uart_1数据缓冲器数据MCU_Uart_1_Receive_Finsh = USER_Uart_1_Receive_DataPacket(Uart_1_R_Data, MCU_Uart_1_Get_DataPacket);}
}
3. 主函数。
通过对相关IO口以及串口1进行初始化,循环对数据包的完整性进行判断,若数据包完整则通过串口1发送出去,并对标志位进行清0。
int main(void)
{uint8_t xdata i = 0; //定义变量i并赋值为“0”MCU_GPIO_All_Init(); //MCU 所有I/O口初始化为准双向口模式函数MCU_Uart_1_Init_Isr(0, 2, 115200); //P3.0/RxD, P3.1/TxD 12分频定时/计数器T2 115200bpswhile (1) //死循环{/*********************测试串行口1接收数据包******************************/if (MCU_Uart_1_Receive_Finsh) //判断串行口1是否接收到完整数据包{MCU_Uart_1_Send_DataPacket(MCU_Uart_1_Get_DataPacket, MCU_Uart_1_Get_DataPacket[2] + 5); //将数据包通过串行口1发送出去MCU_Uart_1_Receive_Finsh = 0; //串行口1接收到完整数据包标志位清"0"}}
}
4. 测试
编译以及烧录成功后用串口助手对串口进行测试!
如上图所示,若发送缓冲区发送数据包不完整,则接收缓冲区接收不到串口1所发来的数据包。
同理,若数据包发送完整,即可接收到串口1所发来的数据包。
测试完毕,证明该程序是可行的。