利用串口将离散数据绘制成波形图

时间:2019-02-19
本文章向大家介绍利用串口将离散数据绘制成波形图,主要包括利用串口将离散数据绘制成波形图使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、 串口通信配置

结合stm32固件库(或其它类型单片机)中usart相关的函数,配置好串口通信的寄存器,确定(数据位、停止位、波特率等等),本文主要介绍两种方法将采集到的串口数据绘制成波形图。

二、所需软件

  • Visual Scope
  • Matlab

效果图:

三、具体步骤

1. 利用Visual Scope绘制波形

在keil中加入 Visual_Scope.c如下,使其符合Visual Scope软件的通信协议

#include "visual_scope.h"

uint16_t OutData[4]={0}; 	//存放待输出的四组数据

unsigned short CRC_CHECK(unsigned char *Buf,unsigned char CRC_CNT)
{
	unsigned short CRC_Temp;//16bit
	unsigned char i,j;
	CRC_Temp = 0xffff;
	for(i = 0;i < CRC_CNT;i++)
	{
		CRC_Temp ^= Buf[i];
		for(j = 0;j < 8;j++)
		{
			if(CRC_Temp & 0x01)
				CRC_Temp = (CRC_Temp>>1)^0xa001;
			else 
				CRC_Temp = CRC_Temp >>1;
		}
	}
	return CRC_Temp;
}

void OutPut_Data()
{
	int temp[4] = {0};
	unsigned int temp1[4] = {0};
	unsigned char databuf[10] = {0};	//The buf of 4 outputdata(low 8 bit + high 8 bit) + 2 check bit(low+high)
	unsigned char i;
	unsigned short CRC16 = 0;	//check data,depending on the outputdata

	for(i = 0;i < 4;i++)
	{
		temp[i] = (int)OutData[i];
		temp1[i] = (unsigned int)temp[i];
	}
	for(i = 0;i < 4;i++)
	{
		databuf[i*2] = (unsigned char)(temp1[i]%256);
		databuf[i*2+1] = (unsigned char)(temp1[i]/256);
	}
	CRC16 = CRC_CHECK(databuf,8);	//get check code 
	databuf[8] = CRC16%256;
	databuf[9] = CRC16/256;

    for(i = 0;i < 10;i++)
        Usart_SendByte(DEBUG_USARTx, databuf[i]);//use usart to send data to upper monitor
		
}

void display()	 //示波,将要发送的数据放到数组后,调用该函数发送数据
{
	#if 1
	OutData[0] = 50;
	OutData[1] = 1000;
	OutData[2] = 0;
	OutPut_Data();
	#endif

	#if 0
	OutData[0] = 0;
	OutData[1] = 0;
	OutData[2] = 0;
	OutPut_Data();
	#endif
}

在VisualScope里设置好参数后,有如下结果:

优点: 用VisualScope示波能比较直观地反映数据的变化情况

缺点: 仅取数值的整数部分绘制波形,无法进一步对波形进行分析(虽然有保存为matlab分析的文件选项,但好像没有办法在matlab中使用)

2. 利用Matlab绘制波形

为了能够对读取到的数据波形进行分析(如频谱分析),可直接使用matlab与stm32进行串口通信,使用时与Visual Scope类似,同样需要在matlab中先配置好串口通信的相关参数,使PC能够与stm32通信。

在matlab中创建Serial.m,并编写以下函数
matlab的串口配置同样可以设置中断来对接收数据进行处理(绘图),因此以下包括了串口配置函数和中断响应函数

function Serial()   %创建函数
delete(instrfindall);   %先关闭串口,否则可能导致出错

global x            %全局变量,供串口中断函数使用

global t;			%全局变量,这里根据需要绘制图形的个人需要而设
global m;
global i;

t = [0];      %时间轴
m = [0];      %数据轴
i = 0;        %用于计数

p = plot(t,m);
axis([i-50 i+50 -1 10]);
grid on;

%%----------------------------配置部分----------------------------

%创建串口对象,直接在命令框输入serial('com1')可查看串口参数
x = serial('com1');
%设置或修改串口通信参数
set(x,'BaudRate',115200);

%设置中断触发方式

set(x,'BytesAvailableFcnMode','Terminator') %ASCII触发,字符触发
set(x,'Terminator','CR/LF')         %接收到\r\n后触发中断

% set(x,'BytesAvailableFcnMode','byte')     %数据触发,根据发送来的数据长度来触发中断
% set(x,'BytesAvailableFcnCount',1)


x.BytesAvailableFcn = @Callback  %定义中断响应函数对象,类似于中断函数名

fopen(x);                %打开串口,类似于开关

fwrite(x,255); 	  %发送握手信号0xff,stm32接收到后开始回传数据
pause           	  %需要暂停,来接收回传数据
     
fclose(x);

end

function Callback(obj,event)   %创建中断服务函数,绘制图像

global t; %时间
global m; %纵坐标
global i; %时间变化值


    disp('I receive!')
    out = fscanf(obj);
    data = str2num(out)	%将接收到的字符转换为数值
     
     %%----------------------以下根据需要自行编写-------------------------------
    t = [t i];							
    m = [m data];
    plot(t,m)
    xlabel('t');
    ylabel('data');
    axis([i-50 i+50 0 100]);
    grid on;
    
    i=i+1;

end

stm32中的代码:
只需在适合的地方用 printf 就好,数据可以是整型也可以是浮点型,注意加上\r\n来触发中断喔!

printf("%f \r\n",data); 

优点: 通信方便,能将读取的数据存入matlab数组中,方便后续分析

缺点: 绘图时需要动态变换横坐标,来实现动态画图(图像滑动)

四、总结

本文介绍了两种将离散的串口数据绘制成连续波形图的方法供大家参考,它们也有着各自明显的优缺点。

Visual Scope:

优点: 能比较直观地反映数据的变化情况

缺点: 仅取数值的整数部分绘制波形,无法进一步对波形进行分析

Matlab:

优点: 能将读取的数据存入matlab数组中,方便后续分析

缺点: 绘图时需要动态变换横坐标,来实现动态画图

五、参考资料

更详细的matlab串口通信使用教程:

https://chuanke.baidu.com/v7399031-233850-1738542.html