正点原子stm32按照接收的数据在LCD上面画图

正点原子stm32按照接收的数据在LCD上面画图

背景

这段时间在练习stm32上面的LCD画图,数据来源是实时接收的。因为屏幕尺寸限制,不可能把每个时间的数据全部打在屏幕上面,而且纯数字也不方便对比,所以很多时候都会画一个折线图啥的。
但是问题来了,我在网上面想搜一下有没有什么前人总结过的简单的方法,可是真的好难找啊,偶尔有几个标题差不多的点进去以后都是要积分的,甚至直接要钱。那就算了,我自己试吧,也就半小时的时间,我就用库里面的函数把图给画出来了,感觉还不错,在这里分享给大家,只说方法,不放大的程序,因为总程序我还有用。

找函数

stm32的库很强劲,而且基本功能几乎都有,就算一时间找不到自己想要的,用循环或判断语句改一改基本上都能达成目标。比如很久以前我在画实心圆的时候很简单就找到了空心圆环,一个for循环就把数量为半径的圆环全部显示出来,看起来就像是一个实心圆一样了。所以这一次我就在LCD的函数文件里面找。
有一个函数叫LCD_Color_Fill:

//在指定区域内填充指定颜色块
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-8x+l)*(ey-sy+1)
//color:要填充的颜色
void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
{  
	u16 height,width;
	u16 i,j;
	width=ex-sx+1; 			//宽度
	height=ey-sy+1;			//高度
 	for(i=0;i<height;i++)
	{
 		LCD_SetCursor(sx,sy+i);   	
		LCD_WriteRAM_Prepare();    
		for(j=0;j<width;j++)LCD->LCD_RAM=color[i*width+j];
	}		  
}  

很显然,这个函数是画方框的,正好可以用来把数据点打出来。
但是这个函数有点复杂,我就又写了一个简单的把它引出来:

void plotdot(u16 t,u16 h,u16 *color)
{

	LCD_Color_Fill(t-1,h-1,t+1,h+1,color);
}

这样,只要用plotdot后面加上横、纵坐标,再加上颜色就可以画长宽均为2像素的大点了。
带进去用实际数据试一下。

测试

纸上谈兵

因为接收的是asc码,将它转换成十进制,然后用一个值减去它:

 plotdot(i,300-((tem10-0x30)*10+tem1-0x30)*2,BLACK);
 plotdot(i,410-((hum10-0x30)*10+hum1-0x30),LIGHTGREEN);

上面300和410的值是当tem和hum均为0时的纵坐标,之所以把待显示的数据放在除数的位置,是因为LCD的坐标原点在左上方,往右是x轴正方向,往下是y轴正方向,但是坐标轴的y轴正方向是向上,所以要把前面的正负改一下。
第一行*2是因为tem(在程序里面是温度的意思、temperature)变化幅度较小,在10-30中间的可能性较大,所以将它翻倍,容易看出来数值变化。
第二行是湿度,变化范围0%-100%,就没有翻倍了。
plotdot后面的i其实就是时间,这样,一个以时间为横轴,以接收数据为纵轴的散点图就设计好了。

实际实现

烧写到板子上,结果让我很惊喜。
在这里插入图片描述数据是我模拟的,取了比较极端的值——温度0-40摄氏度,湿度0-100%都涵盖了,看起来效果还是不错的,更为重要的是,因为每个点都连在一起,不需要再在点与点中间连线了!而且我的采样频率是1Hz,温度和湿度都是变化不会太剧烈的东西,一秒钟的时间它们很难改变1℃或1%,所以在纵向上它们也是连在一起的。

拓展

这部分的设计至此就结束了,这只是很小的一方面,在整个开发里面之占一点点,但是自我感觉还是不错的,运用的方法很巧妙。
来点拓展的:

拓展1

前面因为有段代码是

LCD_Color_Fill(t-1,h-1,t+1,h+1,color);

所以每个小方块的边长都是三个像素,如果把每次横坐标也就是i都自增1或自增2,然后再画下一个点,点与点中间也是相连的,如果需要横向拉长图像可以考虑这个方法。

拓展2

如果需要继续拉长,可能就要用线来连接了,这个我没有尝试,画线的函数是:

void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
	u16 t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 
	delta_x=x2-x1; 
	delta_y=y2-y1; 
	uRow=x1; 
	uCol=y1; 
	if(delta_x>0)incx=1; 
	else if(delta_x==0)incx=0;
	else {incx=-1;delta_x=-delta_x;} 
	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;
	else{incy=-1;delta_y=-delta_y;} 
	if( delta_x>delta_y)distance=delta_x; 
	else distance=delta_y; 
	for(t=0;t<=distance+1;t++ )
	{  
		LCD_DrawPoint(uRow,uCol);
		xerr+=delta_x ; 
		yerr+=delta_y ; 
		if(xerr>distance) 
		{ 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) 
		{ 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}  
}    

x1,y1是起点坐标,x2,y2是终点坐标。
大伙儿可以试试。

  • 11
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MATLAB卡尔曼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值