微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 小弟需要一个4*4键盘的按键服用的程序。

小弟需要一个4*4键盘的按键服用的程序。

时间:10-02 整理:3721RD 点击:
小弟初学单片机,已经调通了单个按键的驱动,但是连续点击或者长按的程序始终没法搞定,还请大家多多帮助啊

用状态机思想能很容易实现你需要的功能,一般方式也可以实现但个人建议用状态机做,你先查些资料,试着自己实现它,对你更有利,遇到问题再交流

把4*4键盘的原理明白了,就很简单了,就是简单地扫描

扫描,有个美国的牛人,5个i/o口控制25个按键。

下载实例就会明白

终于搞定了这个,前后两天半时间啊。

  1. #include <msp430x14x.h>

  2. #define CPU_F ((double)8000000)
  3. #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
  4. #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

  5. #define uchar unsigned char
  6. #define uint  unsigned int
  7. #define ulong unsigned long

  8. ;//*************************************************************************
  9. //                    系统时钟初始化
  10. //*************************************************************************
  11. void Clock_Init()
  12. {
  13.   uchar i;
  14.   BCSCTL1&=~XT2OFF;                 //打开XT振荡器
  15.   BCSCTL2|=SELM1+SELS;              //MCLK为8MHZ,SMCLK为8MHZ
  16.   do{
  17.     IFG1&=~OFIFG;                   //清除震荡标志
  18.     for(i=0;i<100;i++)
  19.        _NOP();                      //延时等待
  20.   }
  21.   while((IFG1&OFIFG)!=0);           //如果标志为1,则继续循环等待
  22.   IFG1&=~OFIFG;
  23. }
  24. //*************************************************************************
  25. //              MSP430内部看门狗初始化
  26. //*************************************************************************
  27. void WDT_Init()
  28. {
  29.    WDTCTL = WDTPW + WDTHOLD;       //关闭看门狗
  30. }

  31. //*************************************************************************
  32. //                    延时函数
  33. //*************************************************************************
  34. void delay(unsigned int m){
  35. for(unsigned int i=0;i<m;i++);

  36. }
  37. //*************************************************************************
  38.           //串行通信传输函数 ,transdata为要写入的数据或指令
  39. //*************************************************************************

  40. void Lcd_InsWrite(uchar type,uchar transdata)
  41. {
  42. P5SEL=0X00;  
  43. P5DIR=0XFF;
  44. P5OUT&=~BIT0;
  45. P5OUT|=BIT1;
  46. uchar firsttype=0xf8; //firsttype为第一字节,用来判断是写数据还是写指令。默认是写指令
  47. uchar temp;
  48. uchar i,j=3;
  49. //P1DIR=0xff;//P1口所有引脚设置为输出方向               
  50. if(type) //判断是是写数据还是写指令,0为写指令,1为写数据
  51. firsttype=firsttype|0x02; //如果要写数据,则把第一字节的第二位至高
  52. P5OUT|=BIT5; //给CS高电平开始写入操作
  53. P5OUT&=~BIT7; //给SCLK时钟脉冲,在每个上升沿把数据写入到LCD
  54. while(j>0) //把写数据指令方式和要写入的数据发送给LCD
  55. {
  56. if(j==3) temp=firsttype; //确认要写入第一字节数据,及数据指令判断
  57. else if(j==2) temp=transdata&0xf0;//确认要写入第二字节数据
  58. else temp=(transdata<<4)&0xf0; //确认要写入第三字节数据
  59. for(i=8;i>0;i--) //把要写入的数据每个位由STD发送到LCD,写入
  60. {
  61. if(temp&0x80) P5OUT|=BIT6; //写入第一字节,及最高字节
  62. else P5OUT&=~BIT6;
  63. P5OUT|=BIT7; //给SCLK一个上升沿,写入一位
  64. temp<<=1; //把数据指令左移一位,开始写入下一位数据
  65. P5OUT&=~BIT7; //给SCLK一个低电平,确保下一次写入数据正常
  66. }
  67. delay(1); //做简单的延时
  68. j--; //准备写入下一字节数据
  69. }
  70. P5OUT&=~BIT5; //写入数据指令完毕,给STD和CS低电平
  71. P5OUT&=~BIT6;
  72. }

  73. //*************************************************************************
  74. //               MSP430 LCD初始化
  75. //*************************************************************************
  76. void init_lcd(void)
  77. {
  78. Lcd_InsWrite(0,0x30); //基本指令
  79. delay(400);
  80. Lcd_InsWrite(0,0x04); //清除显示
  81. delay(400);
  82. Lcd_InsWrite(0,0x0c); //
  83. delay(400);

  84. Lcd_InsWrite(0,0x01);
  85. delay(400);// 显示状态设定:整体显示,游标on,游标位置反白
  86. Lcd_InsWrite(0,0x02);//DDRAM地址归位
  87. delay(400);
  88. }
  89. //********************************************************************
  90. //               MSP430 读入键盘值
  91. //*************************************************************************

  92. char GetKey()
  93. {
  94.     P1DIR |= 0XF0;                  //高四位输出
  95.     for(int i=0;i<4;i++)
  96.     {
  97.         P1OUT = 0XEF << i;
  98.         for(int j=0;j<4;j++)
  99.         {
  100.             if((P1IN&(0x01<<j))==0)
  101.             {
  102.                 return (i+4*j);
  103.             }
  104.         }
  105.     }
  106.     return 0xff;
  107. }
  108. //*************************************************************************
  109. //           主函数
  110. //***********************************************************************void main(void)
  111. void main()
  112. {
  113.   int i;
  114.   char Data[30]="abcdefghijklmnopqrstuvwxyz,' .";
  115.   int ID=0;
  116.   WDT_Init();                         //看门狗设置
  117.   Clock_Init();                       //系统时钟设置
  118.   init_lcd();
  119.   while(1)                            //无限循环
  120.     {
  121.       char temp1=GetKey();
  122.       if(temp1==15){
  123.       delay_ms(10);
  124.       if(temp1==15){
  125.       ID=0;
  126.       delay_ms(200);
  127.       }

  128.     }
  129. if(temp1==14){
  130.   if(Data[0]=='a'){
  131.   for( int j=0;j<26;j++)
  132.   Data[j]=Data[j]-32;
  133.   }
  134.   else{
  135.    for(int j=0;j<26;j++)
  136.   Data[j]=Data[j]+32;
  137. }
  138. }  
  139. for(i=0;i<14;i++){      
  140.       if(temp1==i)
  141.    {  
  142.      delay_ms(10);
  143.      if(temp1==i)
  144.      {
  145.      ID++;
  146.      
  147.      if(ID==4){
  148.   
  149.        ID=1;
  150.      }
  151.      delay_ms(200);
  152.      }
  153.    switch(ID){
  154.    case 1:
  155.     Lcd_InsWrite(1,Data[3*i]);
  156.      delay_ms(200);
  157.       break;
  158.             
  159.    case 2:
  160.      Lcd_InsWrite(1,' ');
  161.      Lcd_InsWrite(0,0x10);
  162.      delay_ms(200);
  163.     Lcd_InsWrite(1,Data[3*i+1]);
  164.     break;
  165.       
  166.    case 3:
  167.      Lcd_InsWrite(1,' ');
  168.      Lcd_InsWrite(0,0x10);
  169.      Lcd_InsWrite(1,Data[3*i+2]);
  170.      delay_ms(200);
  171.      break;   
  172. }
  173.    }
  174.     }
  175. }
  176. }

复制代码

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top