1、有时候需要观察单片机检测到的数据曲线,所以需要用到虚拟示波器。目前用过四款虚拟示波器。
山外的;野火的;硬石的;以及datascope;自己也用c#或者Matlab写过串口助手,显示曲线;为了简单,还是用现成的吧。
如果要用具体的数据,做分析,还是用matlab比较好。
看别人用来调试智能车,用的比较多;说明还是有可取之处;
~~
~~
目前用过的,野火,可以收,也可以发,主要是pid助手,显示电机转速,以及发送pid到单片机中,可以动态修改;还是比较方便的。
但是这个野火的协议库还是比较难懂。需要仔细琢磨如果解码等等;
有时候仅仅需要显示看曲线。那么用datascope比较方便。
这篇文章主要说DataScope的使用。
首先有两个文件,头文件和c文件;后面附上具体代码。
第一步、在工程中包括头文件,同时添加c文件。
第二步,根据自己的单片机,修改一下大小端的代码,只需要修改宏定义就行了;
第三步,就是具体使用了。
放数据---------------------------
放A数据到A通道中;
B数据到B通道中。
、、、
最多是个通道。
生成协议帧。-----------------------------
这个虚拟示波器,是按照固定的格式发送的。
假如发送一个数据。
以;;帧头 数据字节1,字节2,字节3,字节4,帧尾组成。
数据字节1,字节2,字节3,字节4,的顺序,要看大小端。进行调换。
串口发送帧字节---------------
这个一个个字节发送,属于串口的最基本内容了。
51有51的代码
32有32的代码。
就可以了。
实验步骤:
1、添头文件和c文件;
2、根据具体的单片机,进行大小端的修改;
3、写发送的浮点数到通道1中;
4、生成发送包;
5、循环发送包的字节,一个个发出去。
注意头文件的文件名。有些人修改过。
选择不同的框。不需要的就注释掉就行了。
int main(void)
{
unsigned char i; //计数变量
unsigned char Send_Count; //串口需要发送的数据个数
float d0,d1,d2,d3,d4,d5,d6,d7,d8,d9;
d0=12.3;
d1=56.3;
d2=35.2;
d3=12.5;
d4=53.3;
d5=5.6;
d6=8.5;
d7=8.5;
d8=95.2;
d9=10.2;
uart_init(72,115200); //串口1初始化, 波特率115200,数据位8,停止位1,无校验位,无流控制
while(1)
{
DataScope_Get_Channel_Data( d0 , 1 ); //将数据 d0写入通道 1
DataScope_Get_Channel_Data( d1 , 2 ); //将数据 d1写入通道 2
DataScope_Get_Channel_Data( d2 , 3 ); //将数据 d2写入通道 3
DataScope_Get_Channel_Data( d3 , 4 ); //将数据 d3 写入通道 4
DataScope_Get_Channel_Data( d4 , 5 ); //将数据 d4 写入通道 5
DataScope_Get_Channel_Data( d5 , 6 ); //将数据d5写入通道 6
DataScope_Get_Channel_Data( d6 , 7 ); //将数据 d6写入通道 7
DataScope_Get_Channel_Data( d7, 8 ); //将数据 d7写入通道 8
DataScope_Get_Channel_Data(d8 , 9 ); //将数据d8写入通道 9
DataScope_Get_Channel_Data(d9, 10); //将数据 d9写入通道 10
Send_Count = DataScope_Data_Generate(10); //生成10个通道的 格式化帧数据,返回帧数据长度
for( i = 0 ; i < Send_Count; i++) //循环发送,直到发送完毕
{
while((USART1->SR&0X40)==0);
USART1->DR = DataScope_OutPut_Buffer[i]; //从串口丢一个字节数据出去
}
delay_ms(50);
//20fps, 帧间隔时间。 不同电脑配置及 USB-TTL 设备的优劣均会影响此时间的长短,建议实测为准。
}
}
//=====================================================================================================
// DataScope 下位机协议帧生成库 v1.0
//Files : DataScope_CP.H & DataScope_CP.Lib
//Author: L.S.H. @ ACE-Tech
//Date : 2014.02.03
//=====================================================================================================
/******************************************************************************************************
// 一、前言 /
注意:
使用此库文件前,请先确保您系统的串口通讯正常工作。
若您是第一次尝试和 DataScope 建立通讯,不妨仔细浏览余下内容。
//============================================================================================
//=====================================================================================================
// 三、资源占用 /
//库文件(v1.0),ROM及RAM占用情况参考:
226 bytes of CODE memory ( At Cortex-M3 )
44 bytes of DATA memory ( At Cortex-M3 )
使用我们提供的库文件将占用您系统 226 字节的存储空间及 44 字节的随机存储空间。
若需要编写适用于您自己系统下的发送协议,
请在我们官网中 DataScope 板块中查找参考内容
//=====================================================================================================
// 四、库文件说明及使用例子 /
v1.0 版本库文件拥有一个 42 字节宽度的数组及 2 个功能函数。
数组:DataScope_OutPut_Buffer[42] ,待发送帧数据缓存区,里面存放经过功能函数格式化后的待发送帧数据。
功能函数:
1、DataScope_Get_Channel_Data(float Data,unsigned char Channel) :
此函数无返回。
函数功能说明:将指定通道的待发送单精度浮点数据转换为字节数据存放至 DataScope_OutPut_Buffer (待发送帧数据缓存区)。
参数说明:
1、Channel,单字节无符号整型,识别范围:1 - 10
含义:指定本次数据对应哪个通道。
2、Data , 单精度浮点型。
含义:传递待转换的通道数据。
2、DataScope_Data_Generate(unsigned char Channel_Number) :
返回一个单字节无符号整型。
返回说明:返回串口需要发送的字节个数,返回 0 表示发生本次帧数据生成错误。
函数功能说明:产生指定通道个数的待发送帧数据。存放至 DataScope_OutPut_Buffer (待发送帧数据缓存区),
参数说明;
1、Channel_Number,单字节无符号整型,识别范围:1 - 10
含义:设定需要发送的通道个数,最少1个通道,最多10个通道。
补充说明:与 DataScope 通讯的帧数据长度不固定,故调用 DataScope_Data_Generate 时
传递不同的Channel_Number,将在DataScope_OutPut_Buffer中生成不同长度的 格式化帧数据。
--------------------------------------------------------------------------------------------------------
//MDK下库文件使用例子(stm32 发送10个通道数据):
int main(void)
{
unsigned char i; //计数变量
unsigned char Send_Count; //串口需要发送的数据个数
float d0,d1,d2,d3,d4,d5,d6,d7,d8,d9;
d0=12.3;
d1=56.3;
d2=35.2;
d3=12.5;
d4=53.3;
d5=5.6;
d6=8.5;
d7=8.5;
d8=95.2;
d9=10.2;
uart_init(72,115200); //串口1初始化, 波特率115200,数据位8,停止位1,无校验位,无流控制
while(1)
{
DataScope_Get_Channel_Data( d0 , 1 ); //将数据 d0写入通道 1
DataScope_Get_Channel_Data( d1 , 2 ); //将数据 d1写入通道 2
DataScope_Get_Channel_Data( d2 , 3 ); //将数据 d2写入通道 3
DataScope_Get_Channel_Data( d3 , 4 ); //将数据 d3 写入通道 4
DataScope_Get_Channel_Data( d4 , 5 ); //将数据 d4 写入通道 5
DataScope_Get_Channel_Data( d5 , 6 ); //将数据d5写入通道 6
DataScope_Get_Channel_Data( d6 , 7 ); //将数据 d6写入通道 7
DataScope_Get_Channel_Data( d7, 8 ); //将数据 d7写入通道 8
DataScope_Get_Channel_Data(d8 , 9 ); //将数据d8写入通道 9
DataScope_Get_Channel_Data(d9, 10); //将数据 d9写入通道 10
Send_Count = DataScope_Data_Generate(10); //生成10个通道的 格式化帧数据,返回帧数据长度
for( i = 0 ; i < Send_Count; i++) //循环发送,直到发送完毕
{
while((USART1->SR&0X40)==0);
USART1->DR = DataScope_OutPut_Buffer[i]; //从串口丢一个字节数据出去
}
delay_ms(50);
//20fps, 帧间隔时间。 不同电脑配置及 USB-TTL 设备的优劣均会影响此时间的长短,建议实测为准。
}
}
******************************************************************************************************/
//头文件内容:
#ifndef __DATA_PRTOCOL_H
#define __DATA_PRTOCOL_H
extern unsigned char DataScope_OutPut_Buffer[42]; //待发送帧数据缓存区
extern void DataScope_Get_Channel_Data(float Data,unsigned char Channel); // 写通道数据至 待发送帧数据缓存区
extern unsigned char DataScope_Data_Generate(unsigned char Channel_Number); // 发送帧数据生成函数
#endif
#include "DataScroDP.h"
unsigned char DataScope_OutPut_Buffer[42]; //串口发送缓冲区
//函数说明:将单精度浮点数据转成4字节数据并存入指定地址
//附加说明:用户无需直接操作此函数
//target:目标单精度数据
//buf:待写入数组
//beg:指定从数组第几个元素开始写入
//函数无返回
extern void Float2Byte(float *target,unsigned char *buf,unsigned char beg)
{
unsigned char *point;
point = (unsigned char*)target; //得到float的地址
//stm32是这个
buf[beg] = point[0];
buf[beg+1] = point[1];
buf[beg+2] = point[2];
buf[beg+3] = point[3];
// buf[beg+3] = point[0];
// buf[beg+2] = point[1];
// buf[beg+1] = point[2];
// buf[beg+0] = point[3];
}
//函数说明:将待发送通道的单精度浮点数据写入发送缓冲区
//Data:通道数据
//Channel:选择通道(1-10)
//函数无返回
extern void DataScope_Get_Channel_Data(float Data,unsigned char Channel)
{
if ( (Channel > 10) || (Channel == 0) )
{
return; //通道个数大于10或等于0,直接跳出,不执行函数
}else
{
switch (Channel)
{
case 1: Float2Byte(&Data,DataScope_OutPut_Buffer,1); break;
case 2: Float2Byte(&Data,DataScope_OutPut_Buffer,5); break;
case 3: Float2Byte(&Data,DataScope_OutPut_Buffer,9); break;
case 4: Float2Byte(&Data,DataScope_OutPut_Buffer,13); break;
case 5: Float2Byte(&Data,DataScope_OutPut_Buffer,17); break;
case 6: Float2Byte(&Data,DataScope_OutPut_Buffer,21); break;
case 7: Float2Byte(&Data,DataScope_OutPut_Buffer,25); break;
case 8: Float2Byte(&Data,DataScope_OutPut_Buffer,29); break;
case 9: Float2Byte(&Data,DataScope_OutPut_Buffer,33); break;
case 10: Float2Byte(&Data,DataScope_OutPut_Buffer,37); break;
}
}
}
//函数说明:生成 DataScopeV1.0 能正确识别的帧格式
//Channel_Number,需要发送的通道个数
//返回发送缓冲区数据个数
//返回0表示帧格式生成失败
extern unsigned char DataScope_Data_Generate(unsigned char Channel_Number)
{
if ( (Channel_Number > 10) || (Channel_Number == 0) ) //通道个数大于10或等于0,直接跳出,不执行函数
{
return 0;
}else
{
DataScope_OutPut_Buffer[0] = '$'; //帧头
switch(Channel_Number)
{
case 1: DataScope_OutPut_Buffer[5] = 5; return 6; break;
case 2: DataScope_OutPut_Buffer[9] = 9; return 10; break;
case 3: DataScope_OutPut_Buffer[13] = 13; return 14; break;
case 4: DataScope_OutPut_Buffer[17] = 17; return 18; break;
case 5: DataScope_OutPut_Buffer[21] = 21; return 22; break;
case 6: DataScope_OutPut_Buffer[25] = 25; return 26; break;
case 7: DataScope_OutPut_Buffer[29] = 29; return 30; break;
case 8: DataScope_OutPut_Buffer[33] = 33; return 34; break;
case 9: DataScope_OutPut_Buffer[37] = 37; return 38; break;
case 10: DataScope_OutPut_Buffer[41] = 41; return 42; break;
}
}
return 0;
}