匿名上位机的使用(51版)
这个软件不仅仅可以用在调试飞机上面,平时用他来看一个数据波形什么的,也是非常有用的。
之前用他看单独的6050数据,过了一段时间就忘记了怎么用的,所以就浪费了很多时间再次学习,今天就记录下来。
要想实现单片机与上位机的通信,就要按照上位机给定的数据格式来编写传输数据的格式。其实质就是串口发送数据包的格式。
在上位机的界面上就能找到数据格式的说明:
这是我使用的版本。
按照他给定的格式,我们可以这样打包数据(89C52单片机版本,32上也能用):
/****************************************** ** 说明: 1、 发送给上位机的数据帧定义 @桢头--功能字--长度--数据(一个或多个,具体看协议说明)-校验 @前2个字节为帧头0xAAAA @第3个字节为帧ID,也就是功能字,应设置为0xF1~0xFA中的一个 @第4个字节为报文数据长度(dlc) @第5个字节开始到第5+dlc-1个字节为要传输的数据内容段,每个数据场为高字节在前,地字节在后 @第5+dlc个字节为CheckSum,为第1个字节到第5+dlc-1个字节所有字节的值相加后,保留结果的低八位作为CheckSum 2、 外部直接调用这个函数。 3、 需要在此文件中引用需要发送的其他文件中的数据。 4、 发送的数据必须是 int_16 型的数据 *****************************************/ void uart_send_senser(void) { unsigned char xdata data_to_send[23] = {0}; unsigned char i = 0; unsigned char cnt = 0; unsigned char sum = 0; int int_set_distance_2 = (int)set_distance_2; int int_real_distance = (int)real_distance; int int_ASR_output = (int)ASR.output; data_to_send[cnt++]=0xAA; //帧头:AAAA data_to_send[cnt++]=0xAA; data_to_send[cnt++]=0x02; //功能字:OXFn只接受数据,不显示图像。0x0n显示数据和图像 data_to_send[cnt++]=0; //需要发送数据的字节数,暂时给0,后面在赋值。 data_to_send[cnt++] = BYTE1(int_set_distance_2); //高字节 data_to_send[cnt++] = BYTE0(int_set_distance_2); //低字节 data_to_send[cnt++] = BYTE1(int_real_distance); data_to_send[cnt++] = BYTE0(int_real_distance); data_to_send[cnt++] = BYTE1(int_ASR_output); data_to_send[cnt++] = BYTE0(int_ASR_output); data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[cnt++] = 0; data_to_send[3] = cnt-4;//计算总数据的字节数。 for(i=0;i<cnt;i++) //对于for语句,当不写大括号的时候,只执行到下面第一个分号结束。 { sum+=data_to_send[i]; } data_to_send[cnt++] = sum; //计算校验位 uart_send_string(data_to_send,cnt); }
其中那个BYTE()函数就是按照协议写的数据类型转换。
/**********为了匿名四轴上位机的协议定义的变量****************************/ //cup为小端模式存储,也就是在存储的时候,低位被存在0字节,高位在1字节 #define BYTE0(dwTemp) (*(char *)(&dwTemp)) //取出int型变量的低字节 #define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1)) // 取存储在此变量下一内存字节的内容,高字节 #define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2)) #define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))
单片机的程序写好了,下一步就是设置上位机中数据的接收方式。上图:
根据自己定义的数据包的大小,其实就是数组的长度,最多可以发送20个数据。
数据设置好之后,打开串口,选择波特率,在高级收码里面看自己的数据是否符合格式。
最后一部观察数据波形
这篇博客也有说明:http://bbs.elecfans.com/jishu_536667_1_5.html
题外话:
在用51单片机与上位机进行串口通信的时候,波特率是个问题。这时可以使用89C52系列的定时器2作为波特率发生器。但是要特别注意自己晶振的选择,这个细节让我找了好久。
/* ******************************************************** ** 作者 :Andrew ** 日期 :2018.3.11 ** 说明 : 1、使用定时器2做波特率发生器,11.0592M晶振,可以产生115200的波特率 2、使用85C52系列的单片机时,一般P3.1-TXD, P3.0-RXD ,且与USB共地。 3、115200波特率的时候,必须使用11.0592的晶振,12M的不行,这个细节让我找了半天的bug。发疯ing 4、12M晶振时的波特率最好时4800,误差最小。 ******************************************************** */ void uart_init() { SCON = 0X50; //SCON:串行口工作方式1, 8-bit UART,允许串行接收位(REN=1) TH2 = RCAP2H = 0XFF; //baud : 115200 TL2 = RCAP2L = 0XFD; //0xdc 为9600 baud ,0XFD为115200 baud T2CON = 0X34; //控制寄存器,可设置三种工作模式:捕获、计数器、波特率发生器 IE = 0X90; //IE中断允许寄存器,0x90是开总中断和串口中断。 }