作者共發了8篇帖子。 字體大小:較小 - 100% (默認)▼  內容轉換:不轉換▼
 
點擊 回復
525 7
【STM32入门级程序12】矩阵键盘——行扫描法
一派護法 十九級
1樓 發表于:2016-7-1 10:38

【接线】

一派護法 十九級
2樓 發表于:2016-7-1 10:39
【程序】
#include <stm32f10x.h>
// 共阳数码管段码表
unsigned char table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, 0xbf};
// 用于按键延时
void delay(void)
{
 uint16_t i;
 for (i = 0; i < 20000; i++);
}
// 在数码管上显示指定段码
void display(uint8_t n)
{
 GPIO_ResetBits(GPIOB, 0xff00);
 GPIO_SetBits(GPIOB, n << 8);
}
int main(void)
{
 GPIO_InitTypeDef init;
 uint8_t i, temp;
 uint8_t keycode;
 
 // 同时开启PA和PB的时钟
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
 
 // PB8~15用作数码管显示,为输出
 init.GPIO_Mode = GPIO_Mode_Out_PP;
 init.GPIO_Pin = 0xff00;
 init.GPIO_Speed = GPIO_Speed_2MHz;
 GPIO_Init(GPIOB, &init);
 
 // PA0~7用作矩阵键盘
 init.GPIO_Pin = 0x0f;
 GPIO_Init(GPIOA, &init); // 行线为输出
 init.GPIO_Mode = GPIO_Mode_IPU; // 没有信号输入时,视为输入了高电平
 init.GPIO_Pin = 0xf0;
 GPIO_Init(GPIOA, &init); // 列线为输入
 
 display(0xbf); // 默认显示'-'
 while (1)
 {
  GPIO_ResetBits(GPIOA, 0x0f); // 行线输出0
  temp = GPIO_ReadInputData(GPIOA) & 0xf0; // 读列线。如果按键没有按下,则没有信号输入(引脚悬空);如果有按键按下,则输入的是按键对面输出的0
  
  // 如果读出来列线中有为0的位,则表明有按键按下
  if (temp != 0xf0)
  {
   // 按键消抖
   delay();
   temp = GPIO_ReadInputData(GPIOA) & 0xf0;
   if (temp != 0xf0)
   {
    // 如果确实按下了按键
    
    // 行扫描
    for (i = 0; i < 4; i++)
    {
     GPIO_SetBits(GPIOA, 0x0f); // 行线全设为1
     GPIO_ResetBits(GPIOA, 1 << i); // 将要检查的行设为0
     temp = GPIO_ReadInputData(GPIOA) & 0xf0; // 按同样的方法读列线
     if (temp != 0xf0) // 如果不全为1, 则表明该行有按键按下
     {
      // 根据temp和i的值计算键码
      temp = ~temp >> 4 & 0x0f;
      keycode = i * 4;
      if (temp == 8)
       keycode += 3;
      else
       keycode += temp >> 1;
      
      // keycode为最终计算出来的键码, 取值范围是0~15
      // 可在这里进行按键处理
      
      // 显示键码并退出行扫描
      display(table[keycode]);
      break;
     }
    }
    
    // 等待按键释放
    while ((GPIO_ReadInputData(GPIOA) & 0xf0) != 0xf0);
   }
  }
 }
}

一派護法 十九級
3樓 發表于:2016-7-1 10:40
【讲解】
与GPIO操作有关的8个库函数
https://zh.arslanbar.net/post.php?t=24223
一派護法 十九級
4樓 發表于:2016-7-1 10:40
【电路图】

一派護法 十九級
5樓 發表于:2016-7-1 10:43
【原理讲解】
一派護法 十九級
6樓 發表于:2016-7-1 10:45
一派護法 十九級
7樓 發表于:2016-7-1 10:48
一派護法 十九級
8樓 發表于:2016-7-1 11:09

在行扫描循环中,当1 << i == 二进制的1101时,i = 2
此时读列线为二进制的1101????,取反后右移四位并屏蔽掉高4位:
temp = ~temp >> 4 & 0x0f;

得:temp = 二进制00000010 = 2

keycode = i * 4 + (temp >> 1) = 8 + 1 = 9

因此按下的键为9

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:525 回複數:7
評論數: ?
作者:巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2016-7-1 11:09
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。