关于蓝桥杯嵌入式STM32G431RBT6开发板利用信号发生器在LCD上显示不同位数频率时,可能有数值残留问题的一种解决思路

        前言:本人也是第一次备赛蓝桥杯嵌入式(报名了第十四届的),对所使用的开发板也才接触一个礼拜,目前主要在b站上跟着up主的视频学习。当时在学习一位up的视频教如何使用信号发生器在显示器上显示频率时,发现频率值若从大往小的调,则会有原本属于大的值的数字残留,当然这与LCD的特性有关,需要用到清屏的操作。于是就尝试着解决这个问题,最终也算是在有一点瑕疵的情况下解决了,所以就想着写一篇小文章保存思路,如有不妥或者可以修改的更好的地方,还望各位批评和指正。

        首先给出我学习的视频,代码目前也主要跟着人家的写的:定时器-输入捕获(频率、占空比测量)_哔哩哔哩_bilibili

        然后是STM32CubeMX上的设置也与视频中的一样,只是由于用到了TIM3,而此前该定时器已经用于了按键B1的触发,所以我有设置了一个TIM4,让其作为B1的触发定时器,也仍然是10ms检测一次,TIM4的配置如下:

        接着我们就进入正题,捕获频率的代码我这里就不展示了,详见上面的视频,视频里up把代码呈现的很清楚。主函数里,在LCD上显示频率的方式为一个需要自己编写的函数,具体如下:

void disp_proc(void)
{
	if(view==0)//第一个界面
	{
		if(cl_flag==1)
		{
			LCD_Clear(Black);
			cl_flag=0;
		}
		char text[30];
		//sprintf(text,"       Data");
		//LCD_DisplayStringLine(Line1, (uint8_t *)text);
		
		
		sprintf(text,"     Frq1=%d",frq1);
		LCD_DisplayStringLine(Line3, (uint8_t *)text);
		sprintf(text,"     Frq2=%d",frq2);
		LCD_DisplayStringLine(Line5, (uint8_t *)text);
		//sprintf(text,"     IDLE:%d",z);
		//LCD_DisplayStringLine(Line7, (uint8_t *)text);
	}

发挥作用的便是最后四行代码,frq1和frq2的值已经由相应的回调函数得到了,所以直接调用LCD的相应函数即可在屏幕上显示,而在开发板上由如下两个红框框出的旋钮负责调节频率的输出大小:

(截图来自官方的CT117E-M4产品手册)

其中左边的旋钮调节Frq2,右边的旋钮调节Frq1(如果按照视频中的代码的话),顺时针旋转减小频率,逆时针旋转增大频率。若按照视频的配置,Frq1的取值在706~31250左右,Frq2的取值在724~31250左右。然后就会出现如下问题:

可以看到,两张图片上,上面的旋钮为最大值状态,下面的旋钮为最小值状态,但是下面的值却比上面的值还大,当初我也感到疑惑,后来发现最大值状态时,LCD上两个频率的值的最后两位是会由一定的变化的,但是最小值状态的两个频率的最后两位(即图中的52和50)是不变的,然后才意识到是由于值变小了,但LCD没清屏的问题,于是便开始着手解决。(但是我给的视频中的up演示时是不存在这个问题的,所以我也不知道是什么情况

        我的思路是这样的:既然可以知道频率的取值是在700~32250之间,那么就将频率分为几个档次的:>=10000的为一个档次,>=1000但是<10000的为一个档次,<1000的为一个档次。并且给着三个档次分别赋予0、1、2的权重,即相当于Frq1和Frq2中的任意一个的位数减少时就要清屏。最终,我定义了两个全局变量用于记录当前状态和前一个状态:

uchar check_flag=0;//记录当前状态
uchar temp=0;//记录前一个状态

 然后编写相应的函数:(记得声明该函数)

//完善频率捕获的LCD输出(由大数值过渡到小数值时,若不清屏,后面几位有残留)
//权重:x>=10000:0  1000=<x<10000:1   x<1000:2  权重可叠加
void check(uint a,uint b)
{
	if((a >= 10000) && (b >= 10000))
	{
		check_flag=0;
	}
	else if((a<10000 && a>=1000)&&(b>=10000))
	{
		check_flag=1;
	}
	else if((b<10000 && b>=1000)&&(a>=10000))
	{
		check_flag=1;
	}
	else if((a<10000 && a>=1000)&&(b<10000 && b>=1000))
	{
		check_flag=2;
	}
		else if((b>=10000)&&(a<1000))
	{
		check_flag=2;
	}
	else if((a>=10000)&&(b<1000))
	{
		check_flag=2;
	}
	else if((a<10000 && a>=1000)&&(b<1000))
	{
		check_flag=3;
	}
	else if((b<10000 && b>=1000)&&(a<1000))
	{
		check_flag=3;
	}
	else if((a < 1000) && (b <1000))
	{
		check_flag=4;
	}
}

 不同情况下的权重是可叠加的。然后把次函数添加到上面的显示函数中去:

void disp_proc(void)
{
	if(view==0)//第一个界面
	{
		if(cl_flag==1)
		{
			LCD_Clear(Black);
			cl_flag=0;
		}
		char text[30];
		//sprintf(text,"       Data");
		//LCD_DisplayStringLine(Line1, (uint8_t *)text);
		check(frq1,frq2);
		if(check_flag>temp)
		{
			LCD_Clear(Black);
			temp = check_flag;
		}
		if(check_flag<temp)//频率调大,需要将temp回归
		{
			temp=check_flag;
		}
		sprintf(text,"     Frq1=%d",frq1);
		LCD_DisplayStringLine(Line3, (uint8_t *)text);
		sprintf(text,"     Frq2=%d",frq2);
		LCD_DisplayStringLine(Line5, (uint8_t *)text);
		//sprintf(text,"     IDLE:%d",z);
		//LCD_DisplayStringLine(Line7, (uint8_t *)text);
	}

 当前权重大于前一状态权重时,就要清屏,不过要考虑到频率值调大的情况,所以当前权重小于前一状态权重时,就要让两者相等,不然现权重可能会一直小于前一状态权重而导致无法清屏。

至此就算是完成了,但不足的一点是位数减少时,屏幕会闪一下(也就是清屏的操作,但闪的很快),演示如下:

 

一共有九种情况,我这里就不一一演示了,就展示其中三种。

        以上就是全部的内容了,总体而言比较简单,我也只是突发奇想地写一点东西,感谢观看。

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值