找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4717|回复: 0
打印 上一主题 下一主题
收起左侧

单片机LED-KEY按键显示仿真实验 含代码 原理图

[复制链接]
跳转到指定楼层
楼主
ID:761993 发表于 2020-5-26 21:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、实验目的
  • 学习掌握Proteus仿真软件;
  • 熟悉C51编程;
  • 掌握按键、LED显示综合编程
二、实验设备和器件
  • PC机一台
  • PROTEUS仿真软件一套

三、实验原理图

图1  采用单片机I/O端口实现的键盘显示接口电路


实际应用中经常采用单片机的I/O端口实现矩阵键盘及LED数码管显示接口功能,具体电路如图3所示。单片机P3口用于矩阵键盘接口,P3.0~P3.3作为行扫描输出线,P3.4~P3.7作为读列输入线;P0口和P2口用于LED数码管显示接口,从P0口输出显示段码,P2口输出显示数位。

四、实验内容
  • 将按键内容显示在最右边的LED上。
  • 初始显示0~7,实现按键右移显示。即;初始显示01234567,按1后,显示10123456,按2后显示21012345,以此类推。
  • 自主设计一种按键+显示程序。

五.实验代码及结果5.1问题一代码及结果


  1. #include <reg51.h>
  2. #include <absacc.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. uchar key1=16;//全局变量,key1为键码,定义为16是为了让初始时灯灭
  6. uchar code value[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,
  7.                          0x5e,0x79,0x71,0x00}; //0~F的字段码表
  8. //延时函数
  9. void delay(uint i)
  10. {
  11.    uint j;
  12.    for(i=0;j<i;j++){}
  13. }
  14. //判断是否按键
  15. uchar checkkey()
  16. {
  17.      uchar key;
  18.      P3 = 0xF0;//
  19.      key = ~P3 & 0xff;//无键按下返回0fh
  20.      return ( key);
  21. }
  22. //显示函数
  23. void display(void)
  24. {
  25.    P2=0x7f; //仅亮第8个灯  
  26.    P0=value[key1]; //键值  
  27. }
  28. //求按键值,没有按键返回0ff,按键返回键值
  29. unsigned char key(void)
  30. {
  31.     unsigned char row,col=0,k=0xff,dd,scan;// 定义行、列、返回值
  32.     scan=0xfe;  // 行扫描码
  33.     for(row=0;row<4;row++) // 行扫描
  34.       {
  35.          P3=scan; dd=P3/16;  // 行扫描值送P3
  36.          if(dd!=0x0f) // 列线不全为1 ,进入列扫描
  37.             {
  38.                     switch(dd&0x0f)//用case语句求键值
  39.                     {
  40.                               case(0x0e):k=0x00+row*4; break;
  41.                               case(0x0d):k=0x01+row*4; break;
  42.                               case(0x0b):k=0x02+row*4; break;
  43.                               case(0x07):k=0x03+row*4; break;
  44.                      }            
  45.              }
  46.           scan=scan*2+1; // 左移1位
  47.       }
  48.     return k; // 返回键值
  49. }
  50. void main(void)
  51. {
  52.     while(1)
  53.    {
  54.       while(checkkey()==0x0f)//没有按键则显示当前的数字
  55.       {
  56.         display();
  57.       }
  58.       key1=key(); //有按键求键值
  59.    }
  60. }
复制代码

5.2问题二结果及代码


  1. <font color="rgb(0, 0, 0)">#include <reg51.h>
  2. #include <absacc.h>
  3. #include <intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. uchar key1=16;//全局变量,key1为键码,定义为16是为了让初始时灯灭
  7. uchar code value[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,
  8.                          0x5e,0x79,0x71,0x00}; //0~F的字段码表
  9. uchar buf[8]={0,1,2,3,4,5,6,7};  
  10. //延时函数
  11. void delay(uint i)
  12. {
  13.    uint j;
  14.    for(i=0;j<i;j++){}
  15. }
  16. //判断是否按键
  17. uchar checkkey()
  18. {
  19.      uchar key;
  20.      P3 = 0xF0;//
  21.      key = ~P3 & 0xff;//无键按下返回0fh
  22.      return ( key);
  23. }
  24. //显示函数
  25. void display(void)
  26. {
  27.    uchar i,p,scan=0xfe;
  28.    for(i=0;i<8;i++)
  29.    {
  30.      p=buf[i];
  31.      P2=scan;
  32.      P0=value[buf[i]];
  33.      delay(1000);
  34.      scan=_crol_(scan,1);
  35.    }
  36. }
  37. //求按键值,没有按键返回0ff,按键返回键值
  38. unsigned char key(void)
  39. {
  40.     unsigned char row,col=0,k=0xff,dd,scan;// 定义行、列、返回值
  41.     scan=0xfe;  // 行扫描码
  42.     for(row=0;row<4;row++) // 行扫描
  43.       {
  44.          P3=scan; dd=P3/16;  // 行扫描值送P3
  45.          if(dd!=0x0f) // 列线不全为1 ,进入列扫描
  46.             {
  47.                      switch(dd&0x0f)//用case语句求键值
  48.                               {
  49.                                  case(0x0e):k=0x00+row*4; break;
  50.                                  case(0x0d):k=0x01+row*4; break;
  51.                                  case(0x0b):k=0x02+row*4; break;
  52.                                  case(0x07):k=0x03+row*4; break;
  53.                               }            
  54.              }
  55.           scan=scan*2+1; // 左移1位
  56.       }
  57.     while(checkkey()!=0x0f);
  58.     return k; // 返回键值
  59. }
  60. void main(void)
  61. {   
  62.       while(1)
  63.       {
  64.               key1=key();
  65.          if(key1!=0xff)
  66.           {
  67.                   buf[7]=buf[6];
  68.                   buf[6]=buf[5];
  69.                   buf[5]=buf[4];
  70.                   buf[4]=buf[3];
  71.                   buf[3]=buf[2];
  72.                   buf[2]=buf[1];
  73.                   buf[1]=buf[0];
  74.                   buf[0]=key1;
  75.           }
  76.               display();
  77.       }
  78. }</font>
复制代码

5.3问题三结果及代码
实现功能为:计算并显示个位数的一次减法。手动按键,前10个键为数字1-9,第11个键为减号,第12个键为等号。当按键时,第一个灯会显示相应的数,例如输入按键‘8-2=’,第一个灯会依次显示按键对应的字符,当再按‘=’时,就会显示减法结果。弊端是只能算个位减法,仅能算一次,只有第一个灯可以显示输入的数值,不能动态显示。

  1. #include <reg51.h>
  2. #include <absacc.h>
  3. #include <intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. uchar key1=12;//全局变量,key1为键码,定义为16是为了让初始时灯灭
  7. uchar key2,key3;//全局变量,key1为键码,定义为16是为了让初始时灯灭
  8. uchar code value[13]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x09,0x00};//0-9,减号,等号
  9. uchar buf[13]={0,1,2,3,4,5,6,7,9,10,11,12};  
  10. //延时函数
  11. void delay(uint i)
  12. {
  13.    uint j;
  14.    for(i=0;j<i;j++){}
  15. }
  16. //判断是否按键
  17. uchar checkkey()
  18. {
  19.      uchar key;
  20.      P3 = 0xF0;//
  21.      key = ~P3 & 0xff;//无键按下返回0fh
  22.      return ( key);
  23. }
  24. //显示函数
  25. void display(void)
  26. {
  27.    uchar scan=0xfe;
  28.    P2=scan;
  29.    P0=value[key1];
  30. }
  31. //求按键值,没有按键返回0ff,按键返回键值
  32. unsigned char key(void)
  33. {
  34.     unsigned char row,col=0,k=0xff,dd,scan;// 定义行、列、返回值
  35.     scan=0xfe;  // 行扫描码
  36.     for(row=0;row<4;row++) // 行扫描
  37.       {
  38.          P3=scan; dd=P3/16;  // 行扫描值送P3
  39.          if(dd!=0x0f) // 列线不全为1 ,进入列扫描
  40.             {
  41.                      switch(dd&0x0f)//用case语句求键值
  42.                               {
  43.                                  case(0x0e):k=0x00+row*4; break;
  44.                                  case(0x0d):k=0x01+row*4; break;
  45.                                  case(0x0b):k=0x02+row*4; break;
  46.                                  case(0x07):k=0x03+row*4; break;
  47.                               }            
  48.              }
  49.           scan=scan*2+1; // 左移1位
  50.       }
  51.    while(checkkey()!=0x0f);
  52.     return k; // 返回键值
  53. }
  54. void main(void)
  55. {  uchar i=0,j=0;
  56.    while(1)
  57.    {  
  58.        key1=key();
  59.        if(key1!=0xff)//如果有键按下
  60.          {
  61.                   if(i==0)//如果被减数按下,键值赋给key2
  62.                     {key2=key1;}
  63.                   if(i==2)
  64.                     {key3=key1;}//如果减数按下,键值赋给key3
  65.                   if(i==4)
  66.                     {
  67.                      key1=key2-key3;//如果(被减数-减数=)操作完成,则再按=,显示减法结果
  68.                     }
  69.                   display();
  70.                   i++;
  71.                 }  
  72.      }
  73. }
复制代码

6.实验总结
我认为实验比较难的地方是按键会有延时,而机器的处理速度太快,这就导致预期的结果和实际显示的效果不一致。因此在编辑代码时,一定要考虑到手按键会有延时的影响。
在求按键值的子程序里,什么时候把按键值返回需要根据不同的实验做相应的改变,例如:按键结束后返回按键值,和按键时返回键值的效果是不一样的,这也导致在主程序中判断按键是否产生的不同。在问题二中,我就是因为没有在按键结束后返回键值,导致不能产生正确效果。
If里边不能嵌套for语句,在实验一中扫描列时,我嵌套了for,导致程序不能进入for循环。后来我改成了case语句才成功。

以上的Word格式文档51黑下载地址:
实验10.docx (219.4 KB, 下载次数: 7)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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