单片机/MCUwilliam hill官网
直播中

李子井

8年用户 125经验值
擅长:嵌入式技术
私信 关注
[文章]

怎样使用匿名四轴上位机

如何将串口传输给电脑的数据转化程序折线图      因为我的平衡车要滤波和PID,所以我觉的要调节这滤波系数和PID系数就必须通过观察滤波前的和滤波后的数据、PID输入前和输入后的图像才能够很好的调节。如果不这样的话都是瞎调。
找了很久找到一个叫做SerialChart的软件,好像是用在arduino单片机上的,而我用的还只是STC,所以我只好重新找过一个。

      后来经别人的推荐我找到了匿名四轴飞行器的地面站。感觉功能挺强大的。
      我现在讲讲使用他的具体步骤:

      1:我用的是这版本
                                                                                                  
2:这样能描绘波形的软件肯定有他的协议,他的协议就在帮助信息里面。只要你输入到电脑的格式是按照他的飞控通信协议写的话就能够输入到上位机上。(土豆上有使用这软件的视频  『匿名四轴』--地面站讲解0513--基本收发+高级收码    不懂的话可以去    看看,讲的挺详细的)
3:在基本功能中,设置好串口号和波特率,其他默认即可
4:在高级收码中,打开“数据校验” “数据显示”“功能帧显示”,再点击“打开串口”和开启界面下方的“高级收码”。
于是进入高级收码界面,就会收到类似这样的数据:(注意换行)
                                             

5:然后关掉“数据显示” “功能帧显示”,开启界面下方的“飞控波形”。再进入波形显示界面,然后你应该能看到波形了。(我要另外说明这数据是MPU6050的原始数据没有经过处理的)



下面我程序和协议书完全贴出来,以供大家参考:
(我在网上下载的excl格式而QQ上只能上传doc格式我就自己转换了一下,可能有点难看,但是数据没有错。大家不要介意哈      )
//****************************************
// 功能: 显示加速度计和陀螺仪的10位原始数据
//****************************************
// 原件名称:大鱼电子GY521mpu-6050IIC测试程序
// 使用单片机:STC12C5A60S2
// 晶振:11.0592M
// 显示:串口调试助手
// 编译环境 Keil uVision4
// 姓名:谢鑫
// 2015.12.17
//****************************************
#include
#include    //Keil library
#include
typedef unsigned char  uchar;
typedef unsigned short ushort;
typedef unsigned int   uint;

/**********为了匿名四轴上位机的协议定义的变量****************************/
#define BYTE0(dwTemp)       (*(char *)(&dwTemp))
#define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))

uchar data_to_send[23];
int Acc_X;      //显示X轴角度
int Acc_Y;
int Acc_Z;
int Gyr_X;   //显示X轴角速度
int Gyr_Y;
int Gyr_Z;
uchar Baby[25]={"good morning everyones"};



//****************************************
// 定义51单片机端口
//****************************************
***it    SCL=P2^0;   //IIC时钟引脚定义
***it    SDA=P2^1;   //IIC数据引脚定义
//****************************************
// 定义MPU6050内部地址
//****************************************
#define SMPLRT_DIV  0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG   0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG  0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H  0x41
#define TEMP_OUT_L  0x42
#define GYRO_XOUT_H  0x43
#define GYRO_XOUT_L  0x44
#define GYRO_YOUT_H  0x45
#define GYRO_YOUT_L  0x46
#define GYRO_ZOUT_H  0x47
#define GYRO_ZOUT_L  0x48
#define PWR_MGMT_1  0x6B //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I  0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
//函数声明
//****************************************
int GetData(uchar REG_Address);
void init_uart();
void  SeriPushSend(uchar send_data);
void Uart1_Put_Buf(uchar *data_to_send,uchar _cnt);
void Data_Send_Senser(void);



//MPU6050操作函数
void  InitMPU6050();             //初始化MPU6050
void  Delay5us();
void  I2C_Start();
void  I2C_Stop();
void  I2C_SendACK(bit ack);
bit   I2C_RecvACK();
void  I2C_SendByte(uchar dat);
uchar I2C_RecvByte();
uchar Single_ReadI2C(uchar REG_Address);      //读取I2C数据
void  Single_WriteI2C(uchar REG_Address,uchar REG_data); //向I2C写入数据
//****************************************
//**************************************
//延时5微秒(STC90C52RC@12M)
//不同的工作环境,需要调整此函数
//当改用1T的MCU时,请调整此延时函数
//**************************************
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
//**************************************
//I2C起始信号
//**************************************
void I2C_Start()
{
    SDA = 1;                    //拉高数据线
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SDA = 0;                    //产生下降沿
    Delay5us();                 //延时
    SCL = 0;                    //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
void I2C_Stop()
{
    SDA = 0;                    //拉低数据线
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SDA = 1;                    //产生上升沿
    Delay5us();                 //延时
}
//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(bit ack)
{
    SDA = ack;                  //写应答信号
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SCL = 0;                    //拉低时钟线
    Delay5us();                 //延时
}
//**************************************
//I2C接收应答信号
//**************************************
bit I2C_RecvACK()
{
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    CY = SDA;                   //读应答信号
    SCL = 0;                    //拉低时钟线
    Delay5us();                 //延时
    return CY;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(uchar dat)
{
    uchar i;
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;              //移出数据的最高位
        SDA = CY;               //送数据口
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
uchar I2C_RecvByte()
{
    uchar i;
    uchar dat = 0;
    SDA = 1;                    //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        dat |= SDA;             //读数据               
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    return dat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
    I2C_Start();                  //起始信号
    I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
    I2C_SendByte(REG_Address);    //内部寄存器地址,
    I2C_SendByte(REG_data);       //内部寄存器数据,
    I2C_Stop();                   //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
uchar Single_ReadI2C(uchar REG_Address)
{
uchar REG_data;
I2C_Start();                   //起始信号
I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始
I2C_Start();                   //起始信号
I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
REG_data=I2C_RecvByte();       //读出寄存器数据
I2C_SendACK(1);                //接收应答信号
I2C_Stop();                    //停止信号
return REG_data;
}

//*********************************************************
//主程序
//*********************************************************
void main()
{
init_uart();
InitMPU6050(); //初始化MPU6050
while(1)
{
  //    32768.0*180先将从MPU6050中读取到的16位的数据转换10进制的角度
     Acc_X=GetData(ACCEL_XOUT_H);   //显示X轴角度
  Acc_Y=GetData(ACCEL_YOUT_H);  //显示Y轴角度
  Acc_Z=GetData(ACCEL_ZOUT_H);  //显示Z轴角度
     Gyr_X=GetData(GYRO_XOUT_H);   //显示X轴角速度
  Gyr_Y=GetData(GYRO_YOUT_H);  //显示Y轴角速度
  Gyr_Z=GetData(GYRO_ZOUT_H);     //显示Z轴角速度

  Data_Send_Senser();

//  Uart1_Put_Buf(Baby,25);       //测试串口程序有没有用
//  SeriPushSend(0x0d);
//        SeriPushSend(0x0a);//换行,回车
}
}



//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x01);
}
//**************************************
//合成数据
//**************************************
int GetData(uchar REG_Address)
{
uchar H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L;   //合成数据
}
//**************************************
//在匿名上位机上显示数据
//**************************************
void init_uart()
{
  TMOD=0x20;   
TH1=0xfd;   
TL1=0xfd;  
TR1=1;
    SM0=0;
  SM1=1;
REN=1;
EA=1;
ES=1;
// ti=1;

}
void  SeriPushSend(uchar send_data)
{
     ES=0;
    SBUF=send_data;  
while(!TI);
TI=0;
ES=1;   
}
void Uart1_Put_Buf(uchar *data_to_send,uchar _cnt)
{
    uchar i;
for(i=0;i<_cnt;i++)
{
        SeriPushSend(data_to_send);
    }
}


void Data_Send_Senser(void)  //按照协议的要求处理数据
{
uchar  _cnt=0;
uchar  i=0;
uchar sum = 0;

data_to_send[_cnt++]=0xAA;
data_to_send[_cnt++]=0xAA;
data_to_send[_cnt++]=0x02;
data_to_send[_cnt++]=0;
data_to_send[_cnt++]=BYTE1(Acc_X);  //高8位
data_to_send[_cnt++]=BYTE0(Acc_X);  //低8位
data_to_send[_cnt++]=BYTE1(Acc_Y);
data_to_send[_cnt++]=BYTE0(Acc_Y);
data_to_send[_cnt++]=BYTE1(Acc_Z);
data_to_send[_cnt++]=BYTE0(Acc_Z);
data_to_send[_cnt++]=BYTE1(Gyr_X);
data_to_send[_cnt++]=BYTE0(Gyr_X);
data_to_send[_cnt++]=BYTE1(Gyr_Y);
data_to_send[_cnt++]=BYTE0(Gyr_Y);
data_to_send[_cnt++]=BYTE1(Gyr_Z);
data_to_send[_cnt++]=BYTE0(Gyr_Z);
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++)
  sum += data_to_send;
data_to_send[_cnt++] = sum;
Uart1_Put_Buf(data_to_send,_cnt);
}
飞控->上位机
帧头
功能字
长度
数据
校验
STATUS
AAAA
01
LEN
int16 ROL*100
int16 PIT*100
int16 YAW*100
int32 ALT_USE
u8 ARMED : A0加锁 A1解锁
SUM
SENSER
AAAA
02
LEN
int16 ACC_X
int16 ACC_Y
int16 ACC_Z
int16 GYRO_X
int16 GYRO_Y
int16 GYRO_Z
int16 MAG_X
int16 MAG_Y
int16 MAG_Z
SUM
RCDATA
AAAA
03
LEN
int16 THR
int16 YAW
int16 ROL
int16 PIT
int16 AUX1
int16 AUX2
int16 AUX3
int16 AUX4
int16 AUX5
int16 AUX6
SUM
GPSDATA
AAAA
04
LEN
int32 LAT
int32 LNG
float GPS_ALT/cm
float GPS_SPD/cm
int16 GPS_HAC*100
int16 GPS_VAC*100
u8 GPS_STA
u8 GPS_SVN
SUM
VOTAGE
AAAA
05
LEN
uint16 Votage1*100
uint16 Votage2*100
uint16 Votage3*100
SUM
 
AAAA
06
LEN
uint16 PWM_MOTO12345678(范围0-1000)
SUM
 
AAAA
07
LEN
 
SUM
 
AAAA
08
LEN
 
SUM
 
AAAA
09
LEN
 
SUM
 
AAAA
0A
LEN
 
SUM
 
AAAA
0B
LEN
 
SUM
 
AAAA
0C
LEN
 
SUM
 
AAAA
0D
LEN
 
SUM
 
AAAA
0E
LEN
 
SUM
 
AAAA
0F
LEN
 
SUM
PID1
AAAA
10
LEN
int16 ROL_P
int16 ROL_I
int16 ROL_D
int16 PIT_P
int16 PIT_I
int16 PIT_D
int16 YAW_P
int16 YAW_I
int16 YAW_D
SUM
PID2
AAAA
11
LEN
int16 ALT_P
int16 ALT_I
int16 ALT_D
int16 POS_P
int16 POS_I
int16 POS_D
int16 PID1_P
int16 PID1_I
int16 PID1_D
SUM
PID3
AAAA
12
LEN
int16 PID2_P
int16 PID2_I
int16 PID2_D
SUM
 
AAAA
13
LEN
 
 
 
AAAA
14
LEN
 
 
 
AAAA
15
LEN
 
SUM
 
AAAA
16
LEN
int16 OFFSET_ROL*1000
int16 OFFSET_PIT*1000
SUM
 
AAAA
17
LEN
 
 
 
AAAA
18
LEN
 
 
 
AAAA
19
LEN
 
 
 
AAAA
1A
LEN
 
 
 
AAAA
1B
LEN
 
 
 
AAAA
1C
LEN
 
SUM
上位机->飞控
帧头
功能字
长度
数据
校验
返回确认
CONMAND
AAAF
01
LEN
01 ACC校准
02 GYRO校准
03 ACC与GYRO校准
04 MAG校准
05 BARO校准
SUM
YES
 
AAAF
02
LEN
01 请求返回PID
01 请求返回Offset rol pit
SUM
NO
RCDATA
AAAF
03
LEN
int16 THR
int16 YAW
int16 ROL
int16 PIT
int16 AUX1
int16 AUX2
int16 AUX3
int16 AUX4
int16 AUX5
int16 AUX6
SUM
NO
 
AAAF
04
LEN
 
SUM
 
 
AAAF
05
LEN
 
SUM
 
 
AAAF
06
LEN
 
SUM
 
 
AAAF
07
LEN
 
SUM
 
 
AAAF
08
LEN
 
SUM
 
 
AAAF
09
LEN
 
SUM
 
 
AAAF
0A
LEN
 
SUM
 
 
AAAF
0B
LEN
 
SUM
 
 
AAAF
0C
LEN
 
SUM
 
 
AAAF
0D
LEN
 
SUM
 
 
AAAF
0E
LEN
 
SUM
 
 
AAAF
0F
LEN
 
SUM
 
PID1
AAAF
10
LEN
int16 ROL_P
int16 ROL_I
int16 ROL_D
int16 PIT_P
int16 PIT_I
int16 PIT_D
int16 YAW_P
int16 YAW_I
int16 YAW_D
SUM
YES
PID2
AAAF
11
LEN
int16 ALT_P
int16 ALT_I
int16 ALT_D
int16 POS_P
int16 POS_I
int16 POS_D
int16 PID1_P
int16 PID1_I
int16 PID1_D
SUM
YES
PID3
AAAF
12
LEN
int16 PID2_P
int16 PID2_I
int16 PID2_D
SUM
YES
 
AAAF
13
LEN
 
SUM
 
 
AAAF
14
LEN
 
SUM
 
 
AAAF
15
LEN
 
SUM
 
 
AAAF
16
LEN
int16 OFFSET_ROL*1000
int16 OFFSET_PIT*1000
SUM
YES
 
AAAF
17
LEN
 
SUM
 
 
AAAF
18
LEN
 
SUM
 
 
AAAF
19
LEN
 
SUM
 
 
AAAF
1A
LEN
 
SUM
 
 
AAAF
1B
LEN
 
SUM
 
 
AAAF
1C
LEN
 
SUM
 
 
AAAF
 
LEN
 
SUM
 
 
AAAF
 
LEN
 
SUM
 
 
AAAF
 
LEN
 
SUM
 
 
AAAF
F0
LEN
A0,12,34,56,78,90:重启飞控进入boot
SUM
 
上位机发送给飞控的设置数据(功能字为Bx)的数据,在飞控收到后,需要返回相同的数据给上位机(飞控发送回上位机时,帧头需更换为88),上位机收到返回数据后,会进行校验,通过后完成此次通信,校验不通过会重复发送该帧数据,重复10次,如果10次还未通信成功,会报通信错误.



          这个软件其实好还可通过自定义的方式输入数据,将数据转换成图像。假如你不想用固定格式(通信协议中的功能字不用0X02),发送数据想用功能字0XFA。这其实也是可以的只是要进行相应的设置。下面请看我的操作步骤:
1:下位机(主单片机中的程序要改)
2:帧格式要点在10的位置,功能字改为FA,再勾选开
3:数据帧应该点在帧10的位置,数据设置中的序号1应该对应数据位1,数据设置中的序号2应该对应数据位2,数据设置中的序号3应该对应数据位3.....依次这样设置直到最后一个序号20
4:让后软件就会有如下图的显示



























而言之我觉得这软件虽然原本是用在制作四轴上的,但是用他来调试很多东西都是可以的。




  • 无标题.png

回帖(28)

jx新秀

2015-12-27 22:12:00
我用匿名的做过四轴,你要用的话把通讯协议加进去就可以用,主要是串口
举报

wth4613906

2016-4-22 08:26:39
我的Q2578475124,你把这个整个代码发我一份呗?我有需要。。。。谢谢你啊
举报

wuhou1993

2016-5-3 20:18:40
LZ写的好,我正想试试匿名这个上位机。看看效果怎样。SerialChart我试过,大概是2010啊蒂诺的上的一个开源小程序,
程序采用了配置文件进行设置,使用起来也很简单,他是字符串形式进行通信的,数据之间用逗号做为间隔,不过发送的第一个数据类似于一种时间戳,是用QT写的一个开源的小程序。我自己也在用MFC写一个串口波形显示程序,不过还不成熟。
我想学习一下匿名的上位机设计思路。
举报

刘领导

2016-7-7 17:03:58
好东西,谢谢搂住推荐这么好的东西
举报

秋日的书生

2016-7-8 17:27:36
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报

h1654155947.8478

2016-7-14 13:17:06
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报

王洁民

2016-7-15 10:26:39
谢谢楼主的分享
举报

VVX

2016-7-15 10:57:27
你的图炸了
举报

aa849319372

2016-8-7 10:10:23
谢谢分享                          
举报

wj7106

2016-10-15 18:00:06
跟您是一模一样的模块芯片,求代码程序啊
举报

Tieda

2016-11-2 08:36:05
好东西啊,代码这么全。对于我这种新手还是很有帮助的。感谢楼主分享。

就是图片中两处注释是不是标反了。。。
举报

richthoffen

2016-11-2 08:54:02
好资料,学习了.
举报

秦呀秦

2016-11-17 17:49:47
根本方法改变
举报

一只被

2016-12-17 17:36:37
牛逼
举报

东尼菌

2017-3-10 10:54:58
感谢大大分享,不过我看了下程序貌似有错,倒数第三句应该是sum += data_to_send[i];
2 举报
  • 周云龙: void Uart1_Put_Buf(uchar *data_to_send,uchar _cnt) { uchar i; for(i=0;i<_cnt;i++) { SeriPushSend(data_to_send[i]); // 这里也少了下标 i 第290行 } }
  • 周云龙: 第290行也是这样 void Uart1_Put_Buf(uchar *data_to_send,uchar _cnt) { uchar i; for(i=0;i<_cnt;i++) { SeriPushSend(data_to_send[i]); //这里少了[i] } }

小伙伴都惊呆了

2017-3-10 15:05:32
要积分,我就只是要下周个东西
举报

吴晟

2017-5-8 16:52:49
谢谢分享,学习学习。。。
举报

吴晟

2017-5-8 16:52:50
谢谢分享,学习学习。。。
举报

徐涛

2017-5-20 20:22:24
楼主  求软件
举报

更多回帖

×
20
完善资料,
赚取积分