学习笔记|课后练习解答|电磁炉LED实战|逻辑运算|STC32G单片机视频开发教程(冲哥)|第八集(下):课后练习分析与解答

文章目录

课后练习解答

增加按键3,按下后表示启动,选择的对应的功能的LED持续闪烁,表示正在工作,且在工作的时候无法切换功能。

需求分解

  • 1 增加按键3
C 复制代码
#define KEY3 P34  //增加按键3
  • 2 按下后表示启动 电平控制
  • 3 工作状态锁定
    表示正在工作,且在工作的时候无法切换功能。
    该功能需要检测的标志位,且工作的时候无法进行切换。
    增加:bit Run_Now = 0; //0停止工作 1 开始工作。

增加KEY3控制代码如下:

C 复制代码
/*=======================按下按键3,执行本段代码=====================*/
		if (KEY3 == 0)    //必须是按键按下才会执行以下代码,key3被点击,灯在一闪一闪的时候,KEY3非按下模式
		{
			delay_ms(10);  //防抖
			if (KEY3 == 0)
			{
				while(KEY3 == 0);	//等待按键松开,将要执行按下蜂鸣
				if(Run_Mode > 0)   //表示有模式,已经选择了模式,Run_Mode=0时,未选择模式,不执行
				{
					BEEP = 0;		//打开蜂鸣
					delay_ms(10);   //延迟10ms
					BEEP = 1;		//关闭蜂鸣
					Run_Now = !Run_Now; //运行和停止之间的切换
				}

			}

		}
		if( Run_Now = 1)   //正在运行
		{
			P2 = 0XFF; 	//全部熄灭
			delay_ms(200);   //延迟200ms
			P2 = ~(1<< (Run_Mode - 1));	//点亮这个灯
			delay_ms(200);   //延迟200ms
		}
		else  			//停止运行时,没有工作,灯和上面的一样
		{
			P2 = ~(1<< (Run_Mode - 1));
		}

按动KEY2后,0位LED持续闪烁,不能实现既定功能。

第一版代码问题分析

与编译提示的" warning C137: constant in condition expression"有关,这里应该是判断,不是赋值。修改。

调整后,可以控制状态等闪动,但是接着按KEY2,移动不受影响,有逻辑错误,继续排查。

即工作的时候,功能无法切换没有实现。工作状态,变量Run_Now为1,而KEY2能切换的前提是Run_Now状态为0,所以增加条件限制:"if(Run_Now == 0) //Run_Now状态为0(未工作)时才能切换"。

另外,代码KEY2松开后才能执行,实际运行中,按下后有没有松开不太确定,改成按下就执行,等到它松开,调整while循环的位置到最后:while(KEY3 == 0); //等待按键松开,将要执行按下蜂鸣

KEY1,KEY2也可根据调整。
注意 :if ...else可看做是一个整体,中间不能加入其他保留字,如while等。

编译,写入开发板,下载成功,功能正常。

Tips:STC-ISP的设置

可保存,方便调用:

按键需要按的稍微久一点,原因后期课程会分析,讲定时器的时候优化。

Tips:定时器

参考链接:单片机定时器工作原理是什么单片机定时器工作方式有哪些

使用单片机时经常用到一个元件,那就是单片机定时器,单片机定时器的作用主要是在发生软件故障时,通过使器件复位(如果软件未将器件清零)将单片机复位,也可以用于将器件从休眠或空闲模式唤醒,还能用做精确延时处理,常被应用于时间控制、程序延时、对外部时间计数和检测等工作范围内。那么单片机定时器原理是什么呢?

单片机定时器,其实质是一个计数器,脉冲每一次下降沿,计数寄存器数值将加1,如果计数的脉冲是来源于单片机内部的晶振,由于其周期极为准确,则称为定时器;如果计数的脉冲来源于单片机外部的引脚,由于其周期一般不准确,则称为计数器。
单片机定时器工作方式有哪些

单片机定时器的工作方式有很多,大致可分为以下几种:1、方式0

方式0为13位计数,由TLO的低5位(高3位未用)和THO的8位组成TLO的低5位溢出时向THO进位,THO溢出时,置位TCON中的TFO标志,向CPU发出中断请求。

2、方式1

方式1的计数位数是16位,由TLO(TL1)作为低8位、THO(TH1 )作为高8位,组成了16位加1计数器。3、方式2

方式2为自动重装初值的8位计数方式。在方式2下,当定时器计满255( FFH)溢出时,CPU自动把TH的值装入TL中,不需用户干预,比较适合于用作较精确的脉冲信号发生器。

4、方式3

方式3只适用于定时器/计数器TO,定时器T1方式3时相当于TR1=0,停止计数。方式3将TO分成为两个独立的8位计数器TLO和THO。

实现完整电磁炉显示功能的代码

C 复制代码
void Test(void)   //电磁炉的功能
{
		if (KEY1 == 0)   //开关机键
		{
			delay_ms(1000);  //长按1s开机
			if (KEY1 == 0)
			{
/*=======================还没有开机的情况下,执行本段代码=====================*/
				if (Run_Flag == 0)  //表示还没有开机
				{
					Run_Flag = 1;   //开机变量改为1,表示已经开机
					BEEP = 0;		//打开蜂鸣
					delay_ms(10);   //延迟10ms
					BEEP = 1;		//关闭蜂鸣
					P40 = 0;		//打开了LED总电源
					P2 = 0X00;		//全部点亮
					delay_ms(300);   //延迟200ms
					P2 = 0XFF; 		//全部关闭
				}
				else
				{
					Run_Flag = 0;   //标记已关机
					BEEP = 0;		//打开蜂鸣(提醒)
					delay_ms(10);   //延迟10ms
					BEEP = 1;		//关闭蜂鸣
					P2 = 0XFF;		//状态指示全部关闭
					P40 = 1;		//关闭总电源LED
					Run_Mode = 0;   //模式清零
					Run_Now = 0;	//运行状态清零(改成停止)
				}
				while(KEY1 == 0);	//按钮按下,先执行并等待按钮松开

			}

		}
/*=======================按下按键2,执行本段代码=====================*/
		if (KEY2 == 0 && Run_Flag == 1 )   //切换模式,且处于开机状态,状态选择键有效
		{
			delay_ms(10);  //防抖
			if (KEY2 == 0)
			{
					if (Run_Now == 0)	//Run_Now状态为0(未工作)时才能切换
					{
						BEEP = 0;		//打开蜂鸣
						delay_ms(10);   //延迟10ms
						BEEP = 1;		//关闭蜂鸣
						Run_Mode++;		//每次按下,模式+1(移至下一个led)
						if (Run_Mode > 8)  //如果模式大于8,回到模式1
							Run_Mode = 1;  //Run_Mode超过8后清零,回到第一个灯
						//错误写法,执行结果是8个灯中仅1个不亮
													//灯是低电平点亮,1<< Run_Mode,即1<<1,左移以后为0000 0010,仅1个LED灭,继续左移,尾部补0,还是只有1个LED灭
													//解决方法:RunMode先减1,再左移,最后全部取反。这里用~为全取反。而!是位取反。
															//P2 = 0XFX;  P6<< 1 + 1;  也可以实现
						P2 = ~(1<< (Run_Mode - 1));
					}
					while(KEY2 == 0);	//按钮按下,并等待按钮松开
			}

		}
/*=======================按下按键3,执行本段代码=====================*/
		if (KEY3 == 0)   //必须是按键按下才会执行以下代码,key3被点击,灯在一闪一闪的时候,KEY3非按下模式
		{
			delay_ms(10);  //防抖
			if (KEY3 == 0)
			{
				if(Run_Mode > 0 )   //表示有模式,已经选择了模式且处在开机状态下,Run_Mode=0时,未选择模式,不执行
				{
					BEEP = 0;		//打开蜂鸣
					delay_ms(10);   //延迟10ms
					BEEP = 1;		//关闭蜂鸣
					Run_Now = !Run_Now; //运行和停止之间的切换
				}
				while(KEY3 == 0);	//等待按键松开,先执行
			}
		}
		if( Run_Now == 1)   //正在运行
		{
			P2 = 0XFF; 	//全部熄灭
			delay_ms(200);   //延迟200ms
			P2 = ~(1<< (Run_Mode - 1));	//点亮这个灯
			delay_ms(200);   //延迟200ms
		}
		else  			//停止运行时,没有工作,灯和上面的一样
		{
			P2 = ~(1<< (Run_Mode - 1));
		}
}

测试流程

先KEY1开机蜂鸣一声LED点亮

切换模式KEY2(需处于开机状态下)

按一下KEY3,当前LED闪(在当前模式下运行),运行状态下,切换模式短按长按都失效

再按一下KEY3,LED停闪(运行停止),可以切换模式。

后期学完定时器的章节,再解决按键反应迟钝的问题。或者学完数码管以后,既可以修理一下。

总结

厘清正常、简单的逻辑。疯狂的在用if和else做一个判断。

相关推荐
Python小老六3 小时前
冯诺依曼架构 vs 哈佛架构 对比
stm32·单片机·嵌入式硬件·架构
不灭锦鲤3 小时前
网络安全学习第48天
学习
ALKAOUA4 小时前
力扣面试150题刷题分享
javascript·笔记
無限進步D4 小时前
Java 循环 高级(笔记)
java·笔记·入门
怪侠_岭南一只猿4 小时前
爬虫工程师入门阶段一:基础知识点完全学习文档
css·爬虫·python·学习·html
TEC_INO4 小时前
Hal库的使用
单片机·hal库
左左右右左右摇晃4 小时前
Spring + SpringMVC 面试题整理笔记(二)
笔记
羽获飞4 小时前
从零开始学嵌入式之STM32——13.使用STM32自带硬件模块实现IIC协议通讯
单片机·嵌入式硬件
单片机设计星球4 小时前
51单片机的【智能婴儿床】仿真设计
单片机·嵌入式硬件·51单片机
今天你TLE了吗4 小时前
JVM学习笔记:第八章——执行引擎
java·jvm·笔记·后端·学习