仿真电路

  • 元件:

英文名|中文名|属性
:-|:-|:-|:-
7SEG-COM-AN-GRN|绿色7段数码管|-
RX8|8位电阻排|元件值设置为100
BUTTON|按键|-
RES|电阻|元件值设置为10K

  • 电路图:
    电路图

  • 仿真图:
    仿真图

    按键功能类似右侧的键盘。
    按下按键数码管显示0-9o = Abcd

程序设计

  • main.c:
    #include <AT89X51.H>
    #define uchar unsigned char
    #define uint unsigned int
    //CA(共阳极)数码管字形码
    uchar words[16] = {
      0xc0, 0xf9, 0xa4, 0xb0, 0x99, //0-4
      0x92, 0x82, 0xf8, 0x80, 0x90, //5-9
      0xa3, 0xb7,                   //o =
      0x88, 0x83, 0xa7, 0xa1        //Abcd
    };
    //延时函数
    void delay(uint t)
    {
    uint i;
    while (t--)
    {
      for (i = 120; i; i--)
        ;
    }
    }
    //键盘扫描,无按键返回0,有按键返回坐标
    //左上角为11,右上角为14,左下角为41,右下角为44,以此类推
    uchar read_keyboard()
    {
    uchar i, keycode = 0;
    P1 = 0xf0;               //P1前4脚设为高电平,后4脚设为低电平
    if ((P1 & 0x0f) != 0x0f) //如果按键被按下,P1的电平会改变
    {
      delay(2); //消抖
      if ((P1 & 0x0f) != 0x0f)
      {
        P1 = 0xf0;
        switch (P1) //先确定行
        {
        case 0xe0:
          keycode = 10;
          break; //第一行
        case 0xd0:
          keycode = 20;
          break; //第二行
        case 0xb0:
          keycode = 30;
          break; //第三行
        case 0x70:
          keycode = 40;
          break; //第四行
        }
        // delay(3000);
        P1 = 0x0f;  //对应IO口拉高,以便检测
        switch (P1) //再确定列
        {
        case 0x0e:
          keycode += 1;
          break; //第一列
        case 0x0d:
          keycode += 2;
          break; //第二列
        case 0x0b:
          keycode += 3;
          break; //第三列
        case 0x07:
          keycode += 4;
          break; //第四列
        }
        // delay(3000);
      }
    }
    return (keycode);
    }
    //按键坐标转按键键值
    uchar code2value(uchar keycode)
    {
    uchar value;
    switch (keycode)
    {
    case 42:
      value = 0;
      break;
    case 31:
      value = 1;
      break;
    case 32:
      value = 2;
      break;
    case 33:
      value = 3;
      break;
    case 21:
      value = 4;
      break;
    case 22:
      value = 5;
      break;
    case 23:
      value = 6;
      break;
    case 11:
      value = 7;
      break;
    case 12:
      value = 8;
      break;
    case 13:
      value = 9;
      break;
    case 41:
      value = 10;
      break;
    case 43:
      value = 11;
      break;
    case 14:
      value = 12;
      break;
    case 24:
      value = 13;
      break;
    case 34:
      value = 14;
      break;
    case 44:
      value = 15;
      break;
    default:
      value = 0;
    }
    return (value);
    }
    //主程序
    void main()
    {
    uchar keycode;
    P2 = words[0];
    for (;;)
    {
      keycode = read_keyboard(); //读取按键坐标
      if (keycode)               //有按键被按下
      {
        // P2 = keycode;
        P2 = words[code2value(keycode)]; //先转换键值,然后改变数码管显示
      }
    }
    }

注解

矩阵键盘

  • 矩阵键盘
  • 独立按键的每一只按键都连接到单片机的I/O端口上,优点是检测方便,程序简单,缺点是占用端口数量多。
  • 矩阵键盘又称为行列扫描键盘,将每一列、每一行的按键的一端连起来,只需要M+N的端口就能访问M*N的按键,优点是占用端口少,缺点是控制程序相对复杂。
  • 矩阵键盘按键检测过程(假设同时只有一个按键被按下):
  • 所有行输出高电平,列输出低电平。
  • 如果某一行变为低电平,说明在那一行某个按键被按下,记为M
  • 所有行输出低电平,列输出高电平。
  • 如果某一列是低电平,说明在那一列某个按键被按下,记为N
  • MN就是按下按键的坐标。
最后修改:2020 年 04 月 10 日
Null