登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] 使用扫描按键和数码管实现连+和连-

[复制链接]
发表于 2022-1-11 20:38:56 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 单片机
学习安排: 暂无
开始时间: 2022-01-11
结束时间: 2022-01-11
                                                                               使用扫描按键和数码管实现连+和连-
   本次程序有一点点复杂,但是基于我对本次程序的理解。主要使用函数完成按键的扫描,消抖,数码管的扫描,消影。程序主体部分就是按键驱动函数,通过调用按键驱动函数检测按键状态,然后将按键对应的映射表显示到数码管上,进而进行加法或减法运算。
#include<reg52.h>
sbit ADDR0 = P2^0;
sbit ADDR1 = P2^1;
sbit ADDR2 = P2^2;
sbit ENLED = P1^1;
sbit KEY_IN_1 = P2^0;
sbit KEY_IN_2 = P2^1;
sbit KEY_IN_3 = P2^2;
sbit KEY_IN_4 = P2^3;
sbit KEY_OUT_4= P2^4;
sbit KEY_OUT_3 = P2^5;
sbit KEY_OUT_2 = P2^6;
sbit KEY_OUT_1 = P2^7;
    unsigned char code LedChar[] = {  
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,         //数码管转换表
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
        };
    unsigned char LedBuff[6] = {                              
    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF                       //用于数码管的消除鬼影
        };
        unsigned char code KeyCodeMap[4][4] = {   //按键映射键盘表
    { 0x31, 0x32, 0x33, 0x26 },
    { 0x34, 0x35, 0x36, 0x25 },
    { 0x37, 0x38, 0x39, 0x28 },
    { 0x30, 0x1B, 0x0D, 0x27 }
        };
        unsigned char KeySta[4][4] = {                  //按键扫描当前值
        {1,1,1,1},        {1,1,1,1},        {1,1,1,1},        {1,1,1,1}               
        };
void KeyDriver();


void main()
{
    EA = 1;
        ENLED = 0;
        TMOD = 0x01;
        TH0 = 0xF5;
        TL0 = 0x55;
        TR0 = 1;
        ET0 = 1;
        LedBuff[0] = LedChar[0];
        while(1)
        {
          KeyDriver();           //主函数用于现实输入和输出
        }
}
void ShowNumber(unsigned long num)       //用于显示输入和输出数字,并且弥补了高位自动消除0.
                                                                        
{
   signed char i;
   unsigned char buf[6];


   for(i=0;i<6;i++)
   {
      buf = num % 10;
          num = num/10;


   }
   for(i=5;i>=1;i--)
   {
      if(buf == 0)
          
           LedBuff = 0xFF;
          else
            break;
   }
   for(; i>=0;i--)
   {
      LedBuff = LedChar[buf];
   }


   
}
void KeyAction(unsigned char keycode)              //运算函数
{
   static unsigned long result = 0;
   static unsigned long addend = 0;
   if((keycode>=0x30)&&(keycode<=0x39))
   {
      addend = (addend*10) + (keycode-0x30);
          ShowNumber(addend);
   }
   else if(keycode == 0x26)
   {
       result += addend;
           addend = 0;
           ShowNumber(result);


   }
   else if(keycode == 0x0D)
   {
      result += addend;
          addend = 0;
          ShowNumber(result);
          }
   else if(keycode == 0x1B)
   {
      addend = 0;
          result = 0;
          ShowNumber(addend);
   }
   


}
void KeyDriver()
{
     unsigned char i,j;
         static unsigned char backup[4][4] = {                //按键扫描消抖函数,16ms扫描所有按键
         {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
         };
         for(i=0;i<4;i++)
         {
            for(j=0;j<4;j++)
                {
                   if(backup[j]!= KeySta[j])
                   {
                      if(backup[j]!= 0)
                          {
                             KeyAction(KeyCodeMap[j]);
                          }
                          backup[j] = KeySta[j];
                   }
                }
         }
}
void KeyScan()
{
    unsigned char i;
    static unsigned char keyout = 0;  
    static unsigned char keybuf[4][4] = {  
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
    };


   
    keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
    keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
    keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
    keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
   
    for (i=0; i<4; i++)
    {
        if ((keybuf[keyout] & 0x0F) == 0x00)
        {  
            KeySta[keyout] = 0;
        }
        else if ((keybuf[keyout] & 0x0F) == 0x0F)
        {   
            KeySta[keyout] = 1;
        }
    }
   
    keyout++;              
    keyout = keyout & 0x03;
    switch (keyout)         
    {
        case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
        case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
        case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
        case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
        default: break;
    }
}
void LedScan()
{
    static unsigned char i = 0;                                              //数码管消除鬼影和消除数码管显示错位现象
   
    P0 = 0xFF;   
    switch (i)
    {
        case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[5]; break;
        case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[4]; break;
        case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[3]; break;
        case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[2]; break;
        case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[1]; break;
        case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[0]; break;
        default: break;
    }
}


void InterruptTimer0() interrupt 1
{
    TH0 = 0xF5;                                                      详细点击下方链接
    TL0 = 0x55;
    LedScan();   
    KeyScan();                        简易加法计算器_哔哩哔哩_bilibili                  www.bilibili.com/video/BV1za411q7WJ/
}
              本次程序大概思路就是这样,但是有一个问题就是由于38译码器,数码管,LED灯,和矩阵按键的输入引脚是接在一起的,这就造成了,当对37译码器ADDR0,ADDR1,ADDR2,进行赋值的时候,就给按键输入一个错误的信息,并且当按键按下时,也会对LED和数码管造成影响,这个问题暂且我还没有解决。

好懒~~不想说~~~
发表于 2022-1-12 16:05:55 | 显示全部楼层
sbit KEY_OUT_4= P2^4;
sbit KEY_OUT_3 = P2^5;
sbit KEY_OUT_2 = P2^6;
sbit KEY_OUT_1 = P2^7;
这些引脚都接错了,当然如果是自定义的话,请忽略
好懒~~不想说~~~
发表于 2022-1-12 16:57:04 | 显示全部楼层
本帖最后由 房一鹏 于 2022-1-12 16:59 编辑
房一鹏 发表于 2022-1-12 16:05
sbit KEY_OUT_4= P2^4;
sbit KEY_OUT_3 = P2^5;
sbit KEY_OUT_2 = P2^6;

unsigned char buf[6];


   for(i=0;i<6;i++)
   {
      buf = num % 10;
          num = num/10;


   }
   for(i=5;i>=1;i--)
   {
      if(buf == 0)
         
           LedBuff = 0xFF;
          else
            break;
   }
   for(; i>=0;i--)
   {
      LedBuff = LedChar[buf];

这段程序中buf应为buf[ i ]
好懒~~不想说~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表