先说点题外话,都说这个比赛很水,但是我认为准备这个比赛是最好的单片机入门途径,对我后期开发430、STM32、ESP32等搭建相关外设很有帮助,比如那些简单而经典的:按键扫描、矩阵键盘、按键消抖之类的,写法都是和大科的思路差不多,所以就算没有得奖,也能有相当大的收获。
同上篇:考题实际应用情况———转化为———>单片机显示的现象(没想清楚前不要动手!!)
上电后--->按键(不同模式)-->其它驱动
可能有一部分人类和我刚开始的思路一样,什么yi++,if(yi == 9){er ++;yi = 0;}这样程序写得很冗长很愚蠢,一般采用以下这种写法:
取一个数M, 在定时器中一定间隔M++,(例:4位)yi = M/1000; er = M%1000/100; san = M%100/10; si = M%10;
(例:第三届“自动售水机”:假定水价为0.5元/升,出水速度为100ml/s(数码管精度到了0.01L))所以定时器间隔可以为0.1s,基准选为1ms,则
(例:“第五届:简易温度采集与控制装置”)
if((flag == 1)&&(yi == 21))
{
flag = 0;yi = matnum;
}
if((flag == 1)&&(er == 21))
{
flag = 0;er = matnum;
}
if((flag == 1)&&(san == 21))
{
flag = 0;san = matnum;
}
........
在矩阵键盘的函数中写:
case ....:flag = 1;matnum = ....;break;
case ....:flag = 1;matnum = ....;break;
.......
从原理图上看得出来它俩一伙的,继电器接通了,L10就亮了;继电器灭了,L10就灭了
接通,亮:P2 = 0xA0;P0 = 0x10;
断开,灭:P2 = 0xA0;P0 = 0x00;
例:“第三届:“自动售水机”:
设定按键 S7 为出水控制按键,当 S7 按下后,售水机持续出水(继电器接通,指示 灯 L10 点亮)。设定按键 S6 为停水控制按键,当 S6 按下后,停止出水(继电器断开, 指示灯 L10 熄灭)。"
开:P2 = 0xA0;P0 = 0x40; //叫4(注记:“叫死”)
关:P2 = 0xA0;P0 = 0x00;
例:“第四届:模拟智能灌溉系统”
“按下 S6 关闭蜂鸣器提醒功能,再次按下 S6 打开蜂鸣器提醒功能,如此循环”
if(P31 == 0)
{
delay_ms(5);
if(P31 == 0)
{
Beep_flag++;
if(Beep_flag == 1)
{P2 = 0xA0;P0 = 0x00;}
if(Beep_flag == 2)
{P2 = 0xA0;P0 = 0x00;Beep_flag = 0;}
}
}
定义一个全局变量Mode,在按键扫描函数中
例:“第九届:彩灯控制系统”:
if(P31 == 0)
{
delay_ms(5);
if(P31 == 0)
{
Mode++;
if(Mode == 4)Mode = 1;
}
while(!P31);
}
if(P30 == 0)
{
if(RUN == 0)RUN = 1;
else if(RUN == 1)RUN = 0;
}
打开烧录软件,右侧选择定时器计算器,一般的时间基准选择1ms或100us,其它开哪个定时器都行,我喜欢就定时器0,点击生成初始化程序
复制Timer0Init函数粘贴定义在main.c中,别忘了在最上面申明
再在右侧范例程序中随便选一个相应定时器中断的例子,查一下中断号
例:如图查得定时器0的中断号为1
void tm0() interrupt 1
{
。。。。。(相关操作)
}
根据上面初始化定时器中断后,你要加一个定时器开始或停止,如下,不要根据
开:ET0 = 1;EA = 1;
关:ET0 = 0;EA = 0;
(第三届“自动售水机”:“S7按下后定时器持续出水”)
if (P30 == 0)
{
delay_ms(5);
if(P30 == 0)
{
ET0 = 1;EA = 1;
}
}
注:完成这件事定的时应该是2*t0(文字游戏了)
例"第五届:简易温度采集与控制装置"
void timer0() interrupt 1
{
tt++;
if((qujian == 0)&&(tt == 160))
{
tt = 0;
if(fla == 0){fla = 1;P2 = 0X80;P0 = 0XFE;}
else if(fla == 1){fla = 0;P2 = 0X80;P0 = 0XFF;}
}
else if((qujian == 1)&&(tt == 80))
{
tt=0;
if(fla == 0){fla = 1;P2 = 0X80;P0 = 0XFE;}
else if(fla == 1){fla = 0;P2 = 0X80;P0 = 0XFF;}
}
else if((qujian == 2)&&(tt == 40))
{
tt=0;
if(fla == 0){fla = 1;P2 = 0X80;P0 = 0XFE;}
else if(fla == 1){fla = 0;P2 = 0X80;P0 = 0XFF;}
}
(第七届“模拟风扇控制系统”)出了一个PWM,大部分人吓死了,怕个屁哇,它又没有强制你用片内的PWM,你用定时器输出高低电平呗......
void Time0() interrupt 1
{
PWM_tt++;
if(PWM_tt == 11)PWM_tt = 1;
if(PWM_tt < x) PAB = 1;//PAB引脚输出占空比为x/10的PWM
else PAB = 0;
}
例:第一个灯:P2 = 0x80;P0 = 0xFE;
第N+1个灯亮:P2 = 0x80;P0 = ~(0x01 << N);
注:尽量别用for循环,不好计数,到处流:从左往右,从右往左,从中间往两边,从两边往中间,别死记,用头想
(“第九届:彩灯控制器”)
P2 = 0x80;
P0 = ~(0x01 << LED_x);
LED_x++;
if(LED_xx == 8)LED_x = 0;
P2 = 0x80;
P0 = ~(0x80 >> LED_x);
LED_x++;
if(LED_xx == 8)LED_x = 0;
3)两边往中间移:(一个一个列)
P2 = 0x80;
if(LED_x == 0)P0 = 0x7E;
else if(LED_x == 1)P0 = 0xBD;
else if(LED_x == 2)P0 = 0xDB;
else if(LED_x == 3)P0 = 0xE7;
LED_x++;if(LED_x == 4)LED_x = 0;
4)中间往两边移:(一个一个列)
P2 = 0x80;
if(LED_x == 0)P0 = 0xE7;
else if(LED_x == 1)P0 = 0xDB;
else if(LED_x == 2)P0 = 0xBD;
else if(LED_x == 3)P0 = 0x7E;
LED_x++;if(LED_x == 4)LED_x = 0;
第九届:“彩灯控制系统”
不详细写了,学过“呼吸灯”的应该知道,通过控制PWM的占空比来给人产生视觉错觉,跟Rb2没有什么关系。
准备省赛的朋友也可以看看第三篇国赛的部分的代码(尤其是超声波部分,这年头省赛已经考国赛内容了)