● 改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改
蓝桥杯单片机第七届省赛-模拟风扇控制系统
2021.3.16
第七届省赛例程在官方蓝皮书上也有,由于模板用的就是官方的,也就没有粘贴一大段代码的必要性了。仅记录刷题过程中的感悟,和对比官方给出的第七届代码后自己写的代码的不足。
Notes1:按键按下后在某些情况下给一定的缓冲时间
第七届中,有要求按下S5后改变正在按秒递减的数值。此时如果在按下直接修改相关变量值,此变量值又会马上进行递减,所以看到的现象就是 :假设设置为60后,数码管马上变为60,之后很快递减,数码管显示59的时间不足1s,影响体验。而且是按一下S5是将倒计时时间修改为60,再按下一次修改为120,所以缓冲时间就有存在的必要了。
例程中使用的方法是设置一个延时缓冲变量ui_S5_Dly
,在按下S5后,处理完相应的任务后,将变量ui_S5_Dly
赋值为2。在60或120开始递减时先递减ui_S5_Dly
,获得2s的延迟时间。
case 5: //按键5
{
………………
………………
ui_S5_Dly = 2;
}break;
if(ui_S5_Dly) ui_S5_Dly--;
else if(uc_Work_Mode_1_Less_time) uc_Work_Mode_1_Less_time--;
Notes2:用定时器定时在IO口模拟输出矩形波PWM波
官方例程的代码的确简洁:
//变量定义声明部分
sbit PWWM_Out = P3^4;
unsigned char uc_PWM,uc_High=2;
//以下程序放在定时器0中,100us中断一次执行一次
if(++uc_PWM == 10) uc_PWM = 0; //PWM波周期为100us * 10 = 1ms
if(!uc_PWM) //uc_PWM = 0时,即每个PWM波周期开始的时候
{
PWWM_Out = 1; //输出引脚PWWM_Out输出高电平
}
else if(uc_PWM == uc_High) //输出引脚PWWM_Out输出高电平的时间已经达到预设的时间
{
PWWM_Out = 0; //输出引脚PWWM_Out输出低电平
}
Notes3:DS18B20小数部分的处理
在第七届例程中直接右移四位,将小数部分忽略。
或者可以通过sprintf的格式控制,控制小数部分的位数%02.0f
。
Notes4:DS18B20单总线onewire严格时序与定时器中断冲突的处理
单总线onewire对时序要求严格,时序图中常有us级。必须使用的定时器1(数码管驱动、按键消抖)会打断单总线时序。经过测试,不关闭中断时,只要中断服务函数ISR
中的程序量比较少,执行的时间比较短,是影响不了单总线时序的。将中断服务函数ISR
中的程序简化很困难,一般很容易写多。此时单总线时序就被打断无法正常通信。
解决方法1: 尽量精简中断服务函数里的程序,减少中断执行时间。难度较大,没有保证。官方例程采用的就是这种,可……官方代码逻辑部分的精简程度……实在难以掌握……
解决方法2: 在温度读取函数运行前,关闭中断,运行完毕再打开中断。但是缺点是定时器1的中断时间无法保证,对数码管的点亮产生影响:出现闪动。
数码管闪动弥补方法:增大数码管刷新频率,或者干脆说是,减慢温度读取的频率,比如设置标志位让温度读取500ms读取一次。减慢读取频率只能弥补闪动,即使500ms读取一次温度还是会有轻微闪动。
有好的方法求告知^^^
再补充一个点:DS18B20上电默认精度为12位,对应的温度转换时间最大为750ms。此处的温度转换时间是DS18B20内部硬件的工作时间,单总线已经空闲主机可以继续对DS18B20进行操作,没必要软件延时等待。
官方例程将部分需要放在定时器中断里处理的程序,分散到了定时器0中,减轻了定时器1的中断执行时间。
Notes5:P34引脚的定时器1输出功能
刚开始看到P34引脚输出PWM波,想到的是P34引脚是定时器0的输入输出引荐(定时器0做计数器使用时外部频率信号从P34引脚输入)。输出引脚指的是定时器0通过P34引脚对外输出时钟信号。经过查证手册,对外输出的时钟信号是系统时钟的分频信号,只能是不同频率的方波(占空比为50%的矩形波PWM波)。
所以只能通过定时器0定时来模拟PWM波的输出。