×
嵌入式 > 技术百科 > 详情

矩阵键盘扫描程序实例

发布时间:2020-06-19 发布时间:
|

使用芯片STM8S003

所用端口:PD2~PD6, PA1~PA3

其中,PD3~PD6为输出,PA1~PA3 / PD2为输入(默认上拉)

/*
    PortCom BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0
                  PD6  PD5  PD4  PD3  PD2  PA3  PA2  PA1
  */

程序如下:


  1. /*    添加包含芯片的头文件    */  

  2. #include  

  3.   

  4.   

  5.   

  6. volatile unsigned char CF[4];     //按键触发标志(表示4列,每一列同一行的  

  7.                                   //值是一样的但列标不一样来区分不同列的键)  

  8. volatile unsigned char Cont[4];  

  9. unsigned char KeyVal;     //键值  

  10. //unsigned char KeyOut[4] = {0xef,0xdf,0xbf,0x7f};    //4X4按输出端控制  

  11. //unsigned char KeyOut[4] = {0x7f,0xbf,0xdf,0xef};  

  12. unsigned char KeyOut[4] = {0x3f,0x5f,0x6f,0x77};      //两个端口组合4x4端口输出控制  

  13. unsigned char PortCom;    //两个端口组合的端口  

  14. unsigned char cIn0,cIn1,cIn2,cIn3;  

  15.   

  16.   

  17. /******************************************************************************* 

  18. **函数名称:void delay(unsigned int ms)     Name: void delay(unsigned int ms) 

  19. **功能描述:大概延时 

  20. **入口参数:unsigned int ms   输入大概延时数值 

  21. **输出:无 

  22. *******************************************************************************/  

  23. void delay(unsigned int ms)  

  24. {  

  25.   unsigned int x , y;  

  26.   for(x = ms; x > 0; x--)  

  27.     for(y = 1000 ; y > 0 ; y--);  

  28. }  

  29.   

  30. /* 

  31. **描述:新型4X4按键扫描程序 放在1ms-10ms中断内使用(十分稳定不需要再写消抖程序) 

  32. **备注:按键弹起时 keyVal = 0 单键按下 keyVal 有16个值,你自己程序可以针对不同值 

  33. **进行不同程序操作 keyVal单键值分别为  

  34. **0x01,0x02,0x04,0x08, 

  35. **0x11,0x12,0x14,0x18, 

  36. **0x21,0x22,0x24,0x28, 

  37. **0x31,0x32,0x34,0x38, 

  38. */   

  39. void Key_Head()   

  40. {  

  41.   unsigned char ReadData[4];  

  42.   static unsigned char i;  

  43.   /* 

  44.     PortCom BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 

  45.             PD6  PD5  PD4  PD3  PD2  PA3  PA2  PA1 

  46.   */  

  47.   cIn0 = 0;  

  48.   cIn1 = 0;  

  49.   cIn2 = 0;  

  50.   cIn3 = 0;  

  51.   if(++i>=4)i=0;  

  52.   

  53. //  PortCom = KeyOut[i]|0x0f;                     //忽略低4位  

  54.   //输出扫描  

  55.   PD_ODR = KeyOut[i];  

  56.   //输入侦测  

  57.   cIn0 = PA_IDR_bit.IDR1;  

  58.   cIn1 = PA_IDR_bit.IDR2;  

  59.   cIn2 = PA_IDR_bit.IDR3;  

  60.   cIn3 = PD_IDR_bit.IDR2;  

  61.   PortCom = (cIn3<<3) | (cIn2<<2) | (cIn1<<1) | cIn0;   

  62.     

  63.   ReadData[i] = (PortCom|0xf0)^0xff;            //忽略高4位 取反   

  64.   CF[i] = ReadData[i] & (ReadData[i] ^ Cont[i]);   

  65.   Cont[i] = ReadData[i];   

  66.   //输出键值  

  67.   switch(CF[i])//第i列  

  68.   {  

  69.     case 0x08: KeyVal = ((i<<4)+8);break;  

  70.     case 0x04: KeyVal = ((i<<4)+4);break;  

  71.     case 0x02: KeyVal = ((i<<4)+2);break;  

  72.     case 0x01: KeyVal = ((i<<4)+1);break;  

  73.     default:KeyVal = 0;break;  

  74.   }   

  75.       

  76.   delay(30);  

  77. }  

  78.   

  79.   

  80. /******************************************************************************* 

  81. **函数名称:void ALL_LED_Init()    Name: void ALL_LED_Init() 

  82. **功能描述:初始化LED灯的IO口设为输出 

  83. **入口参数:无 

  84. **输出:无 

  85. *******************************************************************************/  

  86. void ALL_LED_Init()  

  87. {  

  88.   //LED1 Init  

  89. //  PD_DDR_bit.DDR2 = 1;    //设置端口PD->2的输入输出方向寄存器为输出方向  

  90. //  PD_CR1_bit.C12 = 1;     //设置PD2为推挽输出  

  91. //  PD_CR2_bit.C22 = 1;     //设置PD2的输出最大速度为10MHZ  

  92.     

  93.   //LED2 Init  

  94.   PC_DDR_bit.DDR7 = 1;    //设置端口PC->7的输入输出方向寄存器为输出方向  

  95.   PC_CR1_bit.C17 = 1;     //设置PC7为推挽输出  

  96.   PC_CR2_bit.C27 = 1;     //设置PC7的输出最大速度为10MHZ  

  97.     

  98.   //LED3 Init  

  99.   PC_DDR_bit.DDR6 = 1;    //设置端口PC->6的输入输出方向寄存器为输出方向  

  100.   PC_CR1_bit.C16 = 1;     //设置PC6为推挽输出  

  101.   PC_CR2_bit.C26 = 1;     //设置PC6的输出最大速度为10MHZ  

  102.     

  103.   //LED4 Init  

  104.   PC_DDR_bit.DDR3 = 1;    //设置端口PC->3的输入输出方向寄存器为输出方向  

  105.   PC_CR1_bit.C13 = 1;     //设置PC3为推挽输出  

  106.   PC_CR2_bit.C23 = 1;     //设置PC3的输出最大速度为10MHZ  

  107. }  

  108.   

  109.   

  110. /******************************************************************************* 

  111. **函数名称:ALLKeyInit() 

  112. **功能描述:配置Key1 , Key2 , Key3输入按键 

  113. **入口参数:无 

  114. **输出:无 

  115. *******************************************************************************/  

  116. void ALLKeyInit()  

  117. {  

  118.   //PA1_Init  

  119.   PA_DDR_bit.DDR1 = 0;      //GPA->PIN3 设置为输入模式  

  120.   PA_CR1_bit.C11 = 1;       //GPA->PIN3 带上拉电阻输入  

  121.   PA_CR2_bit.C21 = 0;       //GPA->PIN3  禁止外部中断  

  122.     

  123.   //PA2_Init  

  124.   PA_DDR_bit.DDR2 = 0;      //GPA->PIN3 设置为输入模式  

  125.   PA_CR1_bit.C12 = 1;       //GPA->PIN3 带上拉电阻输入  

  126.   PA_CR2_bit.C22 = 0;       //GPA->PIN3  禁止外部中断  

  127.     

  128.   //PA3_Init  

  129.   PA_DDR_bit.DDR3 = 0;      //GPA->PIN3 设置为输入模式  

  130.   PA_CR1_bit.C13 = 1;       //GPA->PIN3 带上拉电阻输入  

  131.   PA_CR2_bit.C23 = 0;       //GPA->PIN3  禁止外部中断  

  132.     

  133.   //PD2_Init  

  134.   PD_DDR_bit.DDR2 = 0;      //GPD->PIN3 设置为输入模式  

  135.   PD_CR1_bit.C12 = 1;       //GPD->PIN3 带上拉电阻输入  

  136.   PD_CR2_bit.C22 = 0;       //GPD->PIN3  禁止外部中断  

  137.     

  138.   //PD3_Init  

  139.   PD_DDR_bit.DDR3 = 1;      //GPD->PIN3 设置为输入模式  

  140.   PD_CR1_bit.C13 = 1;       //GPD->PIN3 带上拉电阻输入  

  141.   PD_CR2_bit.C23 = 1;       //GPD->PIN3  禁止外部中断  

  142.     

  143.   //PD4_Init  

  144.   PD_DDR_bit.DDR4 = 1;      //GPD->PIN3 设置为输入模式  

  145.   PD_CR1_bit.C14 = 1;       //GPD->PIN3 带上拉电阻输入  

  146.   PD_CR2_bit.C24 = 1;       //GPD->PIN3  禁止外部中断  

  147.     

  148.   //PD5_Init  

  149.   PD_DDR_bit.DDR5 = 1;      //GPC->PIN5 设置为输入模式  

  150.   PD_CR1_bit.C15 = 1;       //GPC->PIN5 带上拉电阻输入  

  151.   PD_CR2_bit.C25 = 1;       //GPC->PIN5  禁止外部中断  

  152.     

  153.   //PD6_Init  

  154.   PD_DDR_bit.DDR6 = 1;      //GPC->PIN5 设置为输入模式  

  155.   PD_CR1_bit.C16 = 1;       //GPC->PIN5 带上拉电阻输入  

  156.   PD_CR2_bit.C26 = 1;       //GPC->PIN5  禁止外部中断  

  157. }  

  158.   

  159. int main(void)  

  160. {  

  161.   CLK_CKDIVR = 0x00;              //内部时钟为1分频  

  162.   ALL_LED_Init();                 //调用LED1初始化函数  

  163.   ALLKeyInit();                   //调用按钮初始化函数  

  164.   

  165.   while(1)  

  166.   {    

  167.     Key_Head();  

  168.       

  169.     switch(KeyVal)  

  170.     {  

  171.     case 0x01:  

  172.       {  

  173.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  174.         break;  

  175.       }  

  176.     case 0x02:  

  177.       {  

  178.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  179.         break;  

  180.       }  

  181.     case 0x04:  

  182.       {  

  183.         PC_ODR ^= 0x08;                //异或取反LED4使其亮灭  

  184.         break;  

  185.       }  

  186.     case 0x08:  

  187.       {  

  188.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  189.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  190.         break;  

  191.       }  

  192.     case 0x11:  

  193.       {  

  194.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  195.         break;  

  196.       }  

  197.     case 0x12:  

  198.       {  

  199.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  200.         break;  

  201.       }  

  202.     case 0x14:  

  203.       {  

  204.         PC_ODR ^= 0x08;                //异或取反LED4使其亮灭  

  205.         break;  

  206.       }  

  207.     case 0x18:  

  208.       {  

  209.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  210.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  211.         break;  

  212.       }  

  213.     case 0x21:  

  214.       {  

  215.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  216.         break;  

  217.       }  

  218.     case 0x22:  

  219.       {  

  220.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  221.         break;  

  222.       }  

  223.     case 0x24:  

  224.       {  

  225.         PC_ODR ^= 0x08;                //异或取反LED4使其亮灭  

  226.         break;  

  227.       }  

  228.     case 0x28:  

  229.       {  

  230.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  231.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  232.         break;  

  233.       }  

  234.     case 0x31:  

  235.       {  

  236.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  237.         break;  

  238.       }  

  239.     case 0x32:  

  240.       {  

  241.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  242.         break;  

  243.       }  

  244.     case 0x34:  

  245.       {  

  246.         PC_ODR ^= 0x08;                //异或取反LED4使其亮灭  

  247.         break;  

  248.       }  

  249.     case 0x38:  

  250.       {  

  251.         PC_ODR ^= 0x80;                //异或取反LED2使其亮灭  

  252.         PC_ODR ^= 0x40;                //异或取反LED3使其亮灭  

  253.         break;  

  254.       }  

  255.     default:  

  256.       {  

  257.         KeyVal = 0;  

  258.         break;  

  259.       }  

  260.     }  

  261.   }  

  262. }  



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
物联传感与Atmel强强联手 达成智能家居战略合作协议