历史上的今天
返回首页

历史上的今天

今天是:2025年04月18日(星期五)

正在发生

2018年04月18日 | MSP430学习笔记7-4*4键盘的对应数码管显示

2018-04-18 来源:eefocus

这个例程也是开发板上面的一个经典例程,我对程序的框架进行了修改,更适合以后的调用。具体的4*4键盘扫描原理较为基础这里不再赘述,这里我认为比较重要的是要养成一个良好的写程序的习惯,想4*4键盘扫描这样的函数可以写成一个固定的C或者H文件,便于以后调用。先看看主程序:


  1. /*********************************************** 

  2. 程序功能:扫描4X4键盘并将键值在数码管上显示 

  3.  

  4. ------------------------------------------------ 

  5. 测试说明:按动K1~K16按键,观察数码管显示 

  6. ************************************************/  

  7. #include   

  8. #include "Keypad.C"  

  9.   

  10. //数码管7位段码:0--f  

  11. unsigned char scandata[16] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,  

  12.                               0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};  

  13. //记录显示位数的全局变量  

  14. unsigned char cnt = 0;  

  15. //显示缓存  

  16. unsigned char Dispbuf[2];  

  17.   

  18. //引用外部变量的声明  

  19. extern unsigned char key_Pressed;        

  20. extern unsigned char key_val;           

  21. extern unsigned char key_Flag;   

  22.   

  23.   

  24. /********************主函数********************/  

  25. void main(void)  

  26. {  

  27.     /*下面六行程序关闭所有的IO口*/  

  28.     P1DIR = 0XFF;P1OUT = 0XFF;  

  29.     P2DIR = 0XFF;P2OUT = 0XFF;  

  30.     P3DIR = 0XFF;P3OUT = 0XFF;  

  31.     P4DIR = 0XFF;P4OUT = 0XFF;  

  32.     P5DIR = 0XFF;P5OUT = 0XFF;  

  33.     P6DIR = 0XFF;P6OUT = 0XFF;  

  34.     

  35.     P6DIR |= BIT2;P6OUT |= BIT2;  //关闭电平转换        

  36.     WDTCTL = WDT_ADLY_1_9;        //设置内部看门狗工作在定时器模式,1.9ms中断一次  

  37.     IE1 |= WDTIE;                 //使能看门狗中断  

  38.     

  39.     _EINT();                      //打开全局中断  

  40.     Init_Keypad();  

  41.     while(1)  

  42.     {  

  43.         Key_Event();  

  44.       

  45.         if(key_Flag == 1)  

  46.         {  

  47.             key_Flag = 0;  

  48.             Dispbuf[1] = key_val / 10;  

  49.             Dispbuf[0] = key_val % 10;  

  50.               

  51.         }  

  52.     }  

  53. }  

  54. /******************************************* 

  55. 函数名称:watchdog_timer 

  56. 功    能:看门狗中断服务函数,在这里输出数码管的 

  57.           段选和位选信号 

  58. 参    数:无 

  59. 返回值  :无 

  60. ********************************************/  

  61. #pragma vector=WDT_VECTOR  

  62. __interrupt void watchdog_timer(void)  

  63. {   

  64.     P4OUT = 0xff;  

  65.     P5OUT = scandata[Dispbuf[cnt]];         //输出段选信号  

  66.     P4OUT &= ~(1 << (cnt+2));               //输出位选信号  

  67.     

  68.     cnt++;                                  //位计数变量在0~1之间循环  

  69.     if(cnt == 2) cnt = 0;  

  70. }  


主程序较为简单,具体的原理参见上一个笔记,在主程序中与键盘扫描相关的函数被击中在Keypad.C中,需要说明的是在主函数中需要对Keypad.C的部分变量做声明,这样才能使用Keypad.C中的变量。Keypad.C代码如下:




  1. /******************************************************** 

  2. 4*4键盘扫描函数 

  3. 作者:孙浩 

  4. 修改时间:2010.8.2 

  5. 程序说明: 

  6. 此程序以开发板的例程做部分修改,更方便程序调用。 

  7. 在调用之前需要注意需要在主函数中对程序中使用的变量做外部变量声明 

  8. 需要在主函数中声明的变量如下: 

  9. //引用外部变量的声明 

  10. extern unsigned char key_Pressed; //按键是否被按下:1--是,0--否      

  11. extern unsigned char key_val;     //存放键值     

  12. extern unsigned char key_Flag;    //按键是否已放开:1--是,0--否 

  13. 另外对应的键值可以在本文件的全局变量中修改,只需要对应修改 

  14. 数组uchar key_Map[]的对应的值即可。 

  15. 调用示例如下: 

  16. Init_Keypad();        //先进行初始化 

  17.     while(1) 

  18.     { 

  19.         Key_Event();  //在死循环中进行键值扫描 

  20.      

  21.         if(key_Flag == 1)//用来判断有无按键按下,从而读取键值进行操作 

  22.         { 

  23.             key_Flag = 0;//key_Flag需要手动清零 

  24.         } 

  25.     } 

  26. **********************************************************/  

  27. #include    

  28. //相应的函数声明  

  29. void Init_Keypad(void);//键盘初始化  

  30. void Check_Key(void);  

  31. void delay();  

  32. void Key_Event(void);//读取键盘函数,在使用时通过此函数进行键盘扫描  

  33.   

  34. //选择对应的端口  

  35. #define KEYOUT P1OUT  

  36. #define KEYIN P1IN  

  37. #define KEYDIR P1DIR  

  38.   

  39. typedef unsigned char uchar;  

  40. typedef unsigned int  uint;  

  41.   

  42. /***************全局变量***************/  

  43. uchar key_Pressed;      //按键是否被按下:1--是,0--否  

  44. uchar key_val;          //存放键值  

  45. uchar key_Flag;         //按键是否已放开:1--是,0--否  

  46. //设置键盘逻辑键值与程序计算键值的映射  

  47. uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};  

  48.   

  49. /******************************************* 

  50. 函数名称:Init_Keypad 

  51. 功    能:初始化扫描键盘的IO端口 

  52. 参    数:无 

  53. 返回值  :无 

  54. ********************************************/  

  55. void Init_Keypad(void)  

  56. {       

  57.     KEYDIR = 0xf0;       //KEY.0~KEY.3设置为输入状态, KEY.4~KEY.7设置为输出状态  

  58.     KEYOUT |= 0xf0;      // KEY.4~KEY.7输出高电平  

  59.     key_Flag = 0;         

  60.     key_Pressed = 0;     

  61.     key_val = 0;  

  62. }  

  63. /********************************************* 

  64. * Check_Key(),检查按键,确认键值 

  65. *********************************************/  

  66. /******************************************* 

  67. 函数名称:Check_Key 

  68. 功    能:扫描键盘的IO端口,获得键值 

  69. 参    数:无 

  70. 返回值  :无 

  71. ********************************************/  

  72. void Check_Key(void)  

  73. {  

  74.     uchar row ,col,tmp1,tmp2;  

  75.       

  76.     tmp1 = 0x80;  

  77.     for(row = 0;row < 4;row++)              //行扫描  

  78.     {  

  79.         KEYOUT = 0xf0;                      //KEY.4~KEY.7输出全1  

  80.         KEYOUT -= tmp1;                      //KEY.4~p1.7输出四位中有一个为0  

  81.         tmp1 >>=1;                                

  82.         if ((KEYIN & 0x0f) < 0x0f)           //是否KEYIN的KEY.0~KEY.3中有一位为0  

  83.         {                         

  84.             tmp2 = 0x01;                         // tmp2用于检测出那一位为0    

  85.             for(col = 0;col < 4;col++)              // 列检测   

  86.             {            

  87.                 if((KEYIN & tmp2) == 0x00)           // 是否是该列,等于0为是  

  88.                 {            

  89.                     key_val = key_Map[row * 4 + col];  // 获取键值  

  90.                     return;                         // 退出循环  

  91.                 }  

  92.                 tmp2 <<= 1;                        // tmp2右移1位   

  93.             }  

  94.         }  

  95.     }        

  96. }  

  97. /******************************************* 

  98. 函数名称:delay 

  99. 功    能:延时约15ms,完成消抖功能 

  100. 参    数:无 

  101. 返回值  :无 

  102. ********************************************/  

  103. void delay()  

  104. {  

  105.     uint tmp;  

  106.        

  107.     for(tmp = 12000;tmp > 0;tmp--);  

  108. }  

  109. /******************************************* 

  110. 函数名称:Key_Event 

  111. 功    能:检测按键,并获取键值 

  112. 参    数:无 

  113. 返回值  :无 

  114. ********************************************/  

  115. void Key_Event(void)  

  116. {       

  117.     uchar tmp;  

  118.        

  119.     KEYOUT &= 0x00;              // 设置KEYOUT全为0,等待按键输入  

  120.     tmp = KEYIN;                 // 获取 p1IN  

  121.     if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下  

  122.     {                       

  123.         key_Pressed = 1;        // 如果有按键按下,设置key_Pressed标识  

  124.         delay();                //消除抖动  

  125.         Check_Key();            // 调用check_Key(),获取键值   

  126.     }       

  127.     else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放  

  128.     {                       

  129.         key_Pressed = 0;        // 清除key_Pressed标识  

  130.         key_Flag    = 1;        // 设置key_Flag标识  

  131.     }  

  132.     else   

  133.     {  

  134.         _NOP();  

  135.     }       

  136. }  


具体的注意提防都已经在注释中做了说明,在原来的程序中这个文件是分为Keypad.C和Keypad.h两个文件,键盘扫描函数的声明单独为一个头文件,我觉得并不是特别需要。源程序中全局变量是单独列为一个头文件gdata.h的。这样在全局变量比较多的情况下可以使程序更有条理可以参考。


推荐阅读

史海拾趣

台湾奇力(Chip)公司的发展小趣事

奇力公司的成功离不开与奇美集团的紧密合作。奇美集团是台湾知名的面板生产厂家,拥有强大的技术实力和市场份额。奇力公司作为奇美集团的子公司,得到了奇美集团在技术、资金和市场等方面的全力支持。通过与奇美集团的紧密合作,奇力公司得以快速发展,并在LED芯片市场上取得了显著的成绩。

First Switchtech公司的发展小趣事

随着物联网、智能家居等新兴技术的兴起,First Switchtech公司(或类似公司)看到了跨界合作的新机遇。公司积极与智能家居厂商、物联网平台等合作伙伴开展深度合作,共同研发具有创新性的智能开关产品。这些产品不仅实现了开关的远程控制、智能联动等功能,还为用户提供了更加便捷、舒适的智能生活体验。通过跨界合作,First Switchtech公司成功拓展了业务领域,并在智能家居市场中占据了重要位置。

AAC [American Accurate Components]公司的发展小趣事

随着业务的不断拓展,AAC公司意识到美国市场的巨大潜力。于是,在1996年,AAC决定在美国设立分公司,专门负责美国市场的销售。与此同时,为了满足不断增长的市场需求,AAC还在深圳设立了美欧电子有限公司,专门批量生产手机用讯响器。这一系列的举措使得AAC的产品线更加丰富,产能也得到了大幅提升。

Elma Electronic Inc公司的发展小趣事

Elma致力于为个人应用量身定制解决方案,通过丰富的包装电子系统实践经验,确保能够快速、经济地开发出满足客户需求的定制解决方案。这种能力得益于其内部制造能力,确保了产品的兼容性和一致性。同时,Elma还提供设计/集成服务,以及响应迅速且知识渊博的技术支持。

弘凯光电(BRIGHTEK)公司的发展小趣事

弘凯光电股份有限公司,自2001年成立以来,便以光电半导体封装与解决方案提供商的身份,开始在电子行业中崭露头角。早期,公司以台湾为基地,凭借对技术的不断追求和对市场的敏锐洞察,逐步在光电半导体领域积累了宝贵的经验。通过持续的研发和创新,弘凯光电逐渐形成了自己的核心竞争力,为后续的快速发展奠定了坚实基础。

Appointech Inc公司的发展小趣事

为了进一步扩大市场份额,Appointech Inc公司开始积极拓展海外市场。通过与国际知名企业的合作,公司成功打入国际市场,产品销量大幅提升。同时,公司还积极参加国际电子展会和交流活动,与全球同行建立了广泛的合作关系,为公司的长远发展奠定了坚实的基础。

问答坊 | AI 解惑

可编程控制器在汽车转向泵自动装配线中的应用

汽车转向泵是一种中高档汽车的零部件,它由多种零件组成,需要借助不同的设备,按照一定的工序把它们组装起来。在整个过程中,不仅要完成基本的装配,还要对过程中诸如压力、位移、时间等参数进行实时监控,以满足工艺所提出的严格要求,保证装配质 ...…

查看全部问答>

思路决定出路--键盘扫描详解

按键扫描是每个搞单片机的都会遇到的问题,也是一个开发人员必须具备的基本功。先从最基本的说起。在此声明,没有代码,也不要向我要代码,也不想穿裤子,如果你看了帖子还写不出代码,那么我只能说你太笨了。。。。。。。。还是那句话,搞开发重要 ...…

查看全部问答>

单片机高手进,花钱找人编程

我想变成程序,但不知道要多少钱,请高手个价位 仪器的功能大概如下;1,压力传感器测得压力显示在数码管上,另外可以对通过对标定对传感器进行微调                     &nbs ...…

查看全部问答>

wince 6.0 IO 扫描键盘驱动

各位大哥:     最近在研究用 IO 来做键盘,     有几个问题不明白,     1、很多IO键盘驱动都是使用中断来实现,比如 4X4 的要 4 个中断,首先创建一个事件,然后启动一个线程,        通 ...…

查看全部问答>

編寫S3C2440總線方式控制的流式驅動程序問題

我想用nGCS2作片选,LDADDR0-LDADDR7作地址线,LDDATA0-LDDATA7作数据线进行CPLD的读写数据.于是我定义了下面的结构体: #define NGCS2_BASE     0XA4000080 #define NGCS2_PHY_BASE 0x10000080 ///定义CPLD控制寄存器地 ...…

查看全部问答>

请教关于PRO/E野火版的安装问题

大家好:     请问PRO/E野火版怎么安装?安装时要把什么来代替一下吗?本来想把安装的界面的图传上来不知道怎么搞,还是请大家帮忙看下 1. boot up your pc with windows 2. start pro/e setup 3. open ptc_licfile.dat with your fa ...…

查看全部问答>

求教周立功DP-51RPO型单片机综合仿真实验仪中KS0108B液晶汉字显示C编程

求教周立功DP-51RPO型单片机综合仿真实验仪中KS0108B液晶汉字显示C编程…

查看全部问答>

修改防盗器的振动传感部份

有那位高手设计过(加速度传感器用来检测汽车防盗器的振动传感,)…

查看全部问答>

单片机的系列比较---M0与M3

Cortex-M3和Cortex-M0的区别   ARM架构自v6开始分为A/R/M三个系列。CM0/CM3都是属于M系列的。CortexM0是基于v6架构;CortexM3是v7架构。主要区别 性能: Cortex-M0 基于32 位架构,利用一个 通过MULS 指令直接与内核相连的3 ...…

查看全部问答>

按键的硬件去抖动

1>并联电容法——电容放电延时   SW1未被按下时,P0.20上是高电平,C1右侧是VCC,左侧是0。SW1被按下时,C1两侧会放电延时,C1右侧的正电荷越来越少,直到P0.20上是低电平,SW1抖动,貌似弹起,C1右侧的正电荷会增加一点,但时间很短暂, ...…

查看全部问答>