前言
在此篇文章中,默认读者已经掌握 51单片机定时器中断初始化以及使用 独立按键的读取等的基本使用方法,以下内容仅为对此的应用,若还未掌握,则可以在学习过后(可以参考B站江协视频)再来学习本篇文章。
文末附有主函数源码以及讲解
先展示结果
51单片机独立按键控制流水灯方向及状态(利用中断)
对现象进行简单说明
再次使用上篇文章内容说明现象,四个独立按键从左至右依次为S1,S2,S3,S4
在简单的流水灯基础上,S1使流水灯向左,S2使流水灯向右,S3使流水灯停止,S4使流水灯继续暂停前方向
观前提示
在芯片中,所有的逻辑判断与赋值包括之后使用的goto语句跳转运行时间都是极快的,若你在阅读内容的过程中出现疑惑,可以好好的想想这句话,或许能帮到你
利用中断
首先,流水灯肯定需要某种时间间隔来实现,以目前的知识,仅有Delay()函数和定时器中断。 而本次打算使用按键来改变流水灯的方向及状态,可在使用Delay()函数时,芯片会被占用,无法及时响应对按键的读取和处理(当按下并松开按键完成一次点击时,若函数在Delay函数中延时则会使程序忽略此次输入)。 而使用中断则可以在主函数的循环中不断读取按键状态,转而在中断函数中实现流水灯,以及判断按键来实现目的结果。
goto函数
程序中使用的goto函数可能某些读者并不常用,故在此做简单补充,若已掌握可跳过此部分。
goto label; label: xxx;
… 或 …
label: xxx; goto label;
其中label只是一个标记,其可以是任意一个有效的标识符,当程序执行到goto语句时,它会立即跳转到label所指定的位置,并从该位置开始执行代码。
以下为main函数部分
#include <REGX52.H>
#include <INTRINS.H>
#include "Timer0.h"
#include "Key.h"
unsigned char KeyNum,LEDMode=1;
void main()
{
Timer0_Init();
P2=0XFE;
while(1)
{
KeyNum=Key();
switch(KeyNum)
{
case 1:
LEDMode=0;break;
case 2:
LEDMode=1;break;
case 3:
LEDMode=2;break;
case 4:
LEDMode=3;break;
default:
break;
}
}
}
void T0Routine() interrupt 1
{
static unsigned char Pre,T0Count=0;
T0Count++;
TL0 = 0x00; //设置定时初始值
TH0 = 0x4C; //设置定时初始值
if(T0Count>=10)
{
T0Count=0;
a:switch(LEDMode)
{
case 0:
P2=_cror_(P2,1);Pre=LEDMode;break;
case 1:
P2=_crol_(P2,1);Pre=LEDMode;break;
case 2:
break;
case 3:
LEDMode=Pre;goto a;
}
}
}
内容讲解
经过初始化和点亮第一颗LED灯,就进入了主函数(声明的全局变量会在之后讲解)
main函数
1:首先读取独立按键,相对应将KeyNum附为1、2、3、4,若没有按按键,Key()函数的返回值为零
2:之后进入switch语句,KeyNum相对应给LEDMode四种情况。若未按按键,则KeyNum为0,故退出switch语句又重新进入while(1)的循环
中断函数
正式介绍前需先讲解一下_crol_和_cror_函数(l和r为left和right)。 它们都需要两个参数,第一个为被操作对象,第二个为位移动的位数。 在本文中分别为 P2 和 1 ,即将P2向左(右)位移一位。 其与<<和>>的区别我将用一个例子解释。 当P2=1000 0000时, 若使用_crol_(向左)时,其值会变为0000 0001,而若使用<<时,其值会变为0000 0000。更详细的讲解读者可自行学习,本文不过多解释
本人的51单片机频率为11.0952,则给定时器赋赋值,以及if(T0Count>=10)结果为每500ms进入一次中断。 进入中断后判断LEDMode的值
按S1时 LEDMode为0,对应结果则P2右移,即向0(亮灯位)向低位移动,在本人的板子上表现为左移(若您的板子与我相反可以自行做简单调整)。
按S2时 与上同理,故略过。
按S3时 LEDMode为2,即执行空语句,即P2不进行位移,在单片机上表示为停止
按S4时 LEDMode为3,将Pre的值(即暂停前的LEDMode)赋给LEDMode,并通过goto语句再次回到switch()语句前(使用goto语句而不是退出等待下一次中断,可使当流水灯运行时按下S4并不改变流水灯的原有频率)
后记
以上即为所有讲解,因作者水平有限和时间原因,有些部分可能讲解的并不清晰,若有疑问可私信问我,若需要源码,也可将全部源码发送。