这篇文章主要介绍“如何使用单片机独立按键输入”,在日常操作中,相信很多人在如何使用单片机独立按键输入问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用单片机独立按键输入”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
在《 52单片机独立按键输入 》中,在主函数中通过循环扫描得到按键输入,这种设计的缺点是整个过程CPU主进程一直被占用。为了改变这种情况,本次练习采用中断机制改进独立按键输入的设计。使用中断时,主函数不需要扫描按键输入;当有按键按下时,通过与门首先向单片机发起中断请求,通过中断函数处理按键按下事件;当按键弹起时,外部电路向单片机发起另一个中断请求,通过另一个中断函数处理按键的弹起事件。
通过本练习,可以学习到:
与门电路的使用
中断的使用
1. 电路设计
有按键按下时,对应引脚会被下拉为低电平。通过与门电路将这些电路连接起来,有任何一个引脚为低电平0时,与门都会输出低电平0,该低电平正好用作按键按下事件的中断源。按键按下和按键弹起是互斥事件,因此将按键按下的中断源通过非门取非,即可用作按键弹起事件的中断源。
细节:与门的检索关键词 AND,非门的检索关键词 NOT。
2. 程序设计
(1)中断的启用 主函数开始,设置启用中外部断。
// 启用中断
EA = 1; // 开中断(总开关)
EX0 = 1; // 允许外部中断0中断
IT0 = 1; // 下降沿触发IT0=1。
// *下降沿触发只触发一次,低电平触发则可能会反复触发。
EX1 = 1; // 允许外部中断1中断
IT1 = 1; // 下降沿触发IT1=1。
// 启用中断
(2)按键按下中断函数 按键按下发起中断后,临时关闭中断,检测按键,检测完成后重新开启中断。这种设计的目的是避免按键抖动引发多重中断。
/**
* @brief 按键按下时的中断函数
*
*/
void onKeyDown() interrupt 0
{
// 临时关闭中断
EA = 0;
// 临时关闭中断
if (P1_0 == 0)
{
delayNms(10); // 消除抖动
if (P1_0 == 0)
{
displayNum(0);
goto FUNCEND;
}
}
if (P1_1 == 0)
{
delayNms(10); // 消除抖动
if (P1_1 == 0)
{
displayNum(1);
goto FUNCEND;
}
}
if (P1_2 == 0)
{
delayNms(10); // 消除抖动
if (P1_2 == 0)
{
displayNum(2);
goto FUNCEND;
}
}
if (P1_3 == 0)
{
delayNms(10); // 消除抖动
if (P1_3 == 0)
{
displayNum(3);
goto FUNCEND;
}
}
if (P1_4 == 0)
{
delayNms(10); // 消除抖动
if (P1_4 == 0)
{
displayNum(4);
goto FUNCEND;
}
}
if (P1_5 == 0)
{
delayNms(10); // 消除抖动
if (P1_5 == 0)
{
displayNum(5);
goto FUNCEND;
}
}
if (P1_6 == 0)
{
delayNms(10); // 消除抖动
if (P1_6 == 0)
{
displayNum(6);
goto FUNCEND;
}
}
if (P1_7 == 0)
{
delayNms(10); // 消除抖动
if (P1_7 == 0)
{
displayNum(7);
goto FUNCEND;
}
}
FUNCEND:
// 重启中断
EA = 1;
// 重启中断
}
(3)按键弹起中断函数 按键弹起后,数码管停止显示。
/**
* @brief 按键抬起时的中断函数
*
*/
void onKeyUP() interrupt 2
{
display4N(0x10, 0x10, 0x10, 0x10);
}
1. 用到的全局变量的声明。
// 全局变量
sbit P1_0 = P1 ^ 0;
sbit P1_1 = P1 ^ 1;
sbit P1_2 = P1 ^ 2;
sbit P1_3 = P1 ^ 3;
sbit P1_4 = P1 ^ 4;
sbit P1_5 = P1 ^ 5;
sbit P1_6 = P1 ^ 6;
sbit P1_7 = P1 ^ 7;
const unsigned char HexBCD[] = {0xC0, 0xF9, 0xA4, 0xB0,
0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83,
0xC6, 0xA1, 0x86, 0x8E, 0x7F};
// 全局变量
2. 用到的其它函数。
/**
* @brief 延时 ms 毫秒。 0 <= ms <= 65535
*
**/
void delayNms(unsigned int ms)
{
unsigned int n = 124;
while (ms)
{
while (n)
n--;
ms--;
n = 124;
}
}
/**
* @brief 分别在4根数码管上显示数字。每个数字的范围都是0-F。
*
* @param n1 第一个数码管上显示的数字。
* @param n2 第二个数码管上显示的数字。
* @param n3 第三个数码管上显示的数字。
* @param n4 第四个数码管上显示的数字。
*/
void display4N(UCHAR n1, UCHAR n2, UCHAR n3, UCHAR n4)
{
P2 = 0x01; // 选择第一个数码管
if (n1 >= 0 && n1 < 0x10)
P0 = HexBCD[n1]; // 显示n1
else
P0 = 0xFF;
delayNms(5);
P2 = 0x02; // 选择第二个数码管
if (n2 >= 0 && n2 < 0x10)
P0 = HexBCD[n2]; // 显示n2
else
P0 = 0xFF;
delayNms(5);
P2 = 0x04; // 选择第三个数码管
if (n3 >= 0 && n3 < 0x10)
P0 = HexBCD[n3]; // 显示n3
else
P0 = 0xFF;
delayNms(5);
P2 = 0x08; // 选择第四个数码管
if (n4 >= 0 && n4 < 0x10)
P0 = HexBCD[n4]; // 显示n4
else
P0 = 0xFF;
delayNms(5);
}
/**
* @brief 显示给定的数n
*
* @param n 给定的数n
*/
void displayNum(int n)
{
UCHAR thousand; // 千位
UCHAR hundred; // 百位
UCHAR decade; // 十位
UCHAR ones; // 个位
thousand = n / 1000;
hundred = (n % 1000) / 100;
decade = (n % 100) / 10;
ones = n % 10;
if (n < 1000) // 若n小于1000, 则不显示千位
thousand = 0xff;
if (n < 100) // 若n小于100,, 则不显示百位
hundred = 0xff;
if (n < 10) // 若n小于10,, 则不显示十位
decade = 0xff;
display4N(thousand, hundred, decade, ones);
}
到此,关于“如何使用单片机独立按键输入”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/2370800/blog/5015186