这篇文章主要介绍“如何使用单片机独立按键输入”,在日常操作中,相信很多人在如何使用单片机独立按键输入问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用单片机独立按键输入”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
在《 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); }
到此,关于“如何使用单片机独立按键输入”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。