功能
一个观测任意数据波形的上位机
前提知识
数据帧
所谓数据帧(Data frame),就是数据链路层的协议数据单元,它包括三部分:帧头,数据部分,帧尾。其中,帧头和帧尾包含一些必要的控制信息,比如同步信息、地址信息、差错控制信息等;数据部分则包含网络层传下来的数据,比如IP数据包,等等。
首先介绍通信协议
(图不用细看)
可以把通信协议理解为“先对暗号,再发数据”
eg:
0xAA(帧头) +
0x05(数据发送源——'本文即stm32单片机' 匿名说可以随意更改,我也实在不明白这个有啥用,大家就用0x05吧 ) +
0xAF(数据目的地 ——‘匿名具有多项产品,都可以使用该上位机,故而区分开来’ ) +
0xF1(功能字——‘对应不同数据帧,后文会讲’ ) +
len(数据长度——‘后文会讲’) +
“/***********数据*************/”
上位机大致梳理
先来看看它具体的样子
数据帧格式设置
1.第一行1~10,十个数据帧,意思是一个上位机,可以接收十个帧的数据(我们只用一个)
2.使能和显示都勾上
3.功能码:与“通信协议”对应,十个数据帧各有十个功能字,分别为0xF1、0xF2…0xF9、0xFA
4.三十个数据位
数据容器设置
数据容器设置虽然是在高级收码功能里,但其实已经是在设置数据波形了
1.数据容器,所谓数据容器,就是数据波形功能里的二十条波形线,容器号与线号一 一对应。
2.数据来源:对应“数据帧格式”里的十个数据帧,
3.数据位置:对应“数据帧格式”里的三十个数据位
下面的 1…5 6…10 11…15 16…20是显示数据的地方
程序大致梳理
在 mpu6050正点原子程序 的基础上改的(相信大家都找得到源程序,此处截取部分)
流程图:
main
if(report)usart1_report_imu(myaacx*10,myaacy*10,myaacz*10,mygyrox*10,mygyroy*10,mygyroz*10,(int)(roll*10),(int)(pitch*10),(int)(yaw*10));
usart1_report_imu
void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw)
{
u8 tbuf[24];
u8 i;
for(i=0;i<24;i++)tbuf[i]=0;//清0
tbuf[0]=(aacx>>8)&0XFF; //高八位
tbuf[1]=aacx&0XFF; //低八位
tbuf[2]=(aacy>>8)&0XFF;
tbuf[3]=aacy&0XFF;
tbuf[4]=(aacz>>8)&0XFF;
tbuf[5]=aacz&0XFF;
tbuf[6]=(gyrox>>8)&0XFF;
tbuf[7]=gyrox&0XFF;
tbuf[8]=(gyroy>>8)&0XFF;
tbuf[9]=gyroy&0XFF;
tbuf[10]=(gyroz>>8)&0XFF;
tbuf[11]=gyroz&0XFF;
//第7数据位到第9数据位为0
tbuf[18]=(roll>>8)&0XFF;
tbuf[19]=roll&0XFF;
tbuf[20]=(pitch>>8)&0XFF;
tbuf[21]=pitch&0XFF;
tbuf[22]=(yaw>>8)&0XFF;
tbuf[23]=yaw&0XFF;
usart1_niming_report(0XF1,tbuf,24);
}
1.我们从mpu6050获得的数据类型,是short型,即十六位数据,利用移位的方式拆分它们(为什么不直接传u16呢?因为库函数USART_SendData只能传u8数据 拆开后数据不就不完整了嘛?上位机会把它们合在一起的 见图:)
2.上位机能接收30位,我们传输了十二位(12位的short,24位的u8),余下的不传也没关系
usart1_niming_report
//fun:功能字. 0XA0~0XAF
//data:数据缓存区,最多28字节!!
//len:data区有效数据个数
void usart1_niming_report(u8 fun,u8*data,u8 len) //笔记都以usart1_report_imu为例
{
u8 send_buf[34];
u8 i;
if(len>24)return; //最多存储28字节数据
send_buf[len+3]=0; //校验数置零
send_buf[0]=0xAA; //帧头
send_buf[1]=0x05; //0x05为数据发送源,具体请参考匿名协议,本字节用户可以随意更改
send_buf[2]=0xAF; //0xAF为数据目的地,AF表示上位机,具体请参考匿名协议
send_buf[3]=0xF1; //功能字
send_buf[4]=len; //数据长度
for(i=0;i<len;i++)send_buf[5+i]=data[i]; //1.data从0到len-1位 2.从第5位开始复制数据 send_buf的3~len+2位存储data的到len-1位
for(i=0;i<len+5;i++)send_buf[len+5]+=send_buf[i]; //在send_buf最后一位计算校验和 send_buf的第len+3位用来存储数据和
for(i=0;i<len+6;i++)usart1_send_char(send_buf[i]); //1.send_buf全部位 发送数据到串口1 0~31位功32个数据
}
这个程序主要是把“暗号”给加进去,形成一个新的数组
usart1_send_char
//c:要发送的字符
void usart1_send_char(u8 c)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
USART_SendData(USART1,c);
}
你看,结果层层的数据处理,最终还是回到了最基本的库函数USART_SendData,化繁为简
波形显示地设置
进入
设置–>用户数据波形–>确定
实际演示
结语
如果有问题,欢迎在评论区留言
补充
1.传数据需要把数据给拆开了
这里是把数据都从u16拆成了u8
怎样复原呢?
这就需要在上位机里设置了
设置成int16,上位机就会自动把两个u8合起来形成一个u16