历史上的今天
返回首页

历史上的今天

今天是:2025年05月06日(星期二)

正在发生

2018年05月06日 | 单片机C语言实现数码管控制

2018-05-06 来源:eefocus

数码管作为人机接口的重要显示部件,广泛应用于各行各业。本文将围绕数码管的原理和使用展开讨论,实验内容也是由浅入深,结合C语言特性,着意于在实验中掌握数码管和C语言知识。文章采用与单片机C语言实现独立按键检测与矩阵键盘操作同样的开发板。以下先给出数码管的电路原理图。


上图中的4个数码管为共阳极数码管。数码管实际是由8个发光二极管组成的,而共阳极是指将这8个二极管的正极连接到一个公共端。所以当这8个二极管的任何一个负极通低电平的时候,相应的二极管就会被点亮,相反,通高电平则灭。详细请参照以下原理图。


图中任取一个数码管,有a, b, c, d, e, f, g, p分别代表组成该数码管的发光二极管。当要该数码管显示0到9之间任一数字的时候,要给每一个二极管不一样的电平(0或1),8个二极管分别由P0口的8个I/O口控制,P0口的控制输出即为段码。

上面说的是单个数码管的显示,然后我们有四个数码管,怎么选择我要用哪个数码管呢?回到数码管原理图,可以看到数码管底下的DIG口分别连接到4个驱动三极管,并最终由P2口的4个端子来控制。这样就可以选择哪个数码管工作,譬如希望最左侧数码管亮,我们称其为千位数码管(因为有4个数码管,分别代表个十百千),则只需给P2.0口送低电平。

实验一

好了,现在就来做个实验,实验目标是使千位数码管显示数字6。直接上代码。


  1. #include "reg51.h"  

  2.  //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  3.  code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  4.  sbit QIAN = P2^0; //QIAN表示千位  

  5.  void main()  

  6.  {  

  7.     P0 = seg[6];  

  8.     QIAN = 0;  

  9.     while(1)  

  10.     {  

  11.           

  12.     }  

  13.  }  

程序中,显示定义了段码,进入main函数后,先给P0口数字6的显示段码,再选通千位数码管,这样千位数码管就顺利地显示6。这里我们重点讲解seg数组。

char seg[10]

10:10个数连续存放。

seg:代表了第一个数的首地址。

char:每个数最大值不超过255,即一个内存单元(如果定义成int则每个数要占用两个内存单元)。

但是这10个数存在哪呢?

有两种方法。第一种也就是当我们采用char seg[...]={...}这种定义方法时,程序下载烧到ROM后,当下次上电时候,程序会自动将这数组拷贝到RAM。第二种当定义成code char seg[...]={...}时候,程序下载烧到ROM后,内核只从ROM中读取,并不通过RAM。这样的好处是节省了内存资源,但同时程序执行时seg数组也不能被更改。

实验二

接下来我们要使4个数码管都显示,本例显示1234。直接上代码:

  1. #include "reg51.h"  

  2.  //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  3.  code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  4.  sbit QIAN = P2^0;  

  5.  char i;  

  6.  char smgbuf[4]={1,2,3,4}; //从RAM的smgbuf这个地址开始连续存放4个数,并且每个数占一个单元。  

  7.   

  8.  void delay(unsigned int x)  

  9.  {  

  10.     while(x)   //注意这里不是1  

  11.     {  

  12.         x--;  

  13.     }     

  14.  }  

  15.   

  16.  void load_smg()   //将数码管显示缓冲区的数据,显示到数码管上  

  17.  {  

  18.     char i;  

  19.     for(i=0;i<4;i++)   

  20.     {  

  21.         P0=0xFF;   //消除上一个循环的影子,因为i每一次叠代时,数码管都会有上一次叠代的痕迹,0xFF则是使所有数码管灭掉。  

  22.         P0 = seg[smgbuf[i]];  

  23.         P2 = ~(1<

  24.         delay(200);  

  25.     }  

  26.  }  

  27.   

  28.  void main()  

  29.  {  

  30.     while(1)  

  31.     {  

  32.         load_smg();  

  33.     }  

  34.  }  

实验三

下面我们希望用四个数码管显示一个可变的数字,这个数字记录了程序执行进入main函数的次数。还是直接上代码(为了方便代码管理,拆分代码到main.c和smg.c):

main.c文件

  1. #include "reg51.h"  

  2. unsigned int count;  

  3. extern void load_smg();  

  4.   

  5. void main()  

  6.  {  

  7.     int a;  

  8.     while(1)  

  9.     {  

  10.         load_smg();  

  11.         a++;  

  12.         if(a>=200)  

  13.         {  

  14.             count++;  

  15.             a=0;              

  16.         }  

  17.     }  

  18.  }  

smg.c文件

  1.  #include "reg51.h"   

  2.   //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  3.  code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  4.  char i;  

  5.  char smgbuf[4]={1,2,3,4}; //从RAM的smgbuf这个地址开始连续存放4个数,并且每个数占一个单元。  

  6.  sbit QIAN = P2^0;  

  7.  extern unsigned int count; //外部申明  

  8.   

  9.  void delay(unsigned int x)  

  10.  {  

  11.     while(x)     

  12.     {  

  13.         x--;  

  14.     }     

  15.  }  

  16.   

  17. void fill_smgbuf() //向LED缓冲区填充数据  

  18. {  

  19.     smgbuf[0]=count/1000;  //千位,我们希望千位数码管来显示数字的千位  

  20.     smgbuf[1]=(count%1000)/100;  //百位  

  21.     smgbuf[2]=((count%1000)%100)/10;   //十位  

  22.     smgbuf[3]=((count%1000)%100)%10;   //个位  

  23. }  

  24.   

  25. void load_smg()   //将缓冲区的数据,显示到数码管上  

  26.  {  

  27.     char i;  

  28.     fill_smgbuf();  

  29.     for(i=0;i<4;i++)   

  30.     {  

  31.         P0=0xFF;    

  32.         P0 = seg[smgbuf[i]];  

  33.         P2 = ~(1<

  34.         delay(200);  

  35.     }  

  36.  }  

实验四
接下来我们要引入独立按键控制数码管上的数字加1(K1键)或减1(K2键)。还是上代码:

main.c文件


  1. #include "reg51.h"  

  2.   

  3. extern void load_smg();  

  4. extern delay(unsigned int x);  

  5. extern void key1();  

  6. extern void key2();  

  7.   

  8. unsigned int count;  

  9.   

  10. void main()  

  11.  {  

  12.     while(1)  

  13.     {  

  14.         load_smg();  

  15.         key1();  

  16.         key2();  

  17.     }  

  18.  }  

smg.c文件


  1.  #include "reg51.h"   

  2.   //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  3.  code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};  

  4.  char smgbuf[4]={1,2,3,4};   

  5.  extern unsigned int count;   

  6.   

  7.  void delay(unsigned int x)  

  8.  {  

  9.     while(x)     

  10.     {  

  11.         x--;  

  12.     }     

  13.  }  

  14.   

  15. void fill_smgbuf()   

  16. {  

  17.     smgbuf[0]=count/1000;    

  18.     smgbuf[1]=(count%1000)/100;    

  19.     smgbuf[2]=((count%1000)%100)/10;     

  20.     smgbuf[3]=((count%1000)%100)%10;     

  21. }  

  22.   

  23. void load_smg()     

  24.  {  

  25.     char i;  

  26.     fill_smgbuf();  

  27.     for(i=0;i<4;i++)   

  28.     {  

  29.         P0=0xFF;     

  30.         P0 = seg[smgbuf[i]];  

  31.         P2 = ~(1<

  32.         delay(200);  

  33.     }  

  34.  }  

key.c文件

  1. #include "reg51.h"  

  2. extern delay(unsigned int x);  

  3. extern unsigned int count;  

  4. sbit K1=P2^4;  //+1  

  5. sbit K2=P2^5;   //-1  

  6.   

  7. void key1()  

  8. {  

  9.     static char st;  

  10.     if(K1==0)  

  11.     {  

  12.         if(st==0)  

  13.         {  

  14.             delay(5000);  

  15.             if(K1==0)  

  16.             {  

  17.                 st=1;  

  18.                 count++;  

  19.             }  

  20.         }  

  21.     }  

  22.     else  

  23.     {  

  24.         st=0;  

  25.     }  

  26. }  

  27.   

  28. void key2()  

  29. {  

  30.     static char st;  

  31.     if(K2==0)  

  32.     {  

  33.          if(st==0)  

  34.          {  

  35.             delay(5000);  

  36.             if(K2==0)  

  37.             {  

  38.                 st=1;  

  39.                 count--;  

  40.             }  

  41.          }  

  42.     }  

  43.     else  

  44.     {  

  45.         st=0;  

  46.     }  

  47. }  

这个实验有一个地方需要注意,即每当复位,按K2键,数码管显示535。这是因为开机后程序默认count值为0,即16个0。当按下K2键后,减1,变成负1。而负1在内存中为16个1(负数的补码为其绝对值的原码取反再加1),又因为count定义为unsigned,所以显然count为65535。65535再被1000除,得到了535。

总结:

1、掌握数的分离方法,例如求出5678的个十百千位。

2、C语言数组是数据批量处理的基础。

3、尝试分别用四个键去控制个十百千四个数码管的闪烁。


推荐阅读

史海拾趣

Dawning Precision Co Ltd公司的发展小趣事

在国内市场取得一定成绩后,Dawning开始将目光投向国际市场。公司积极参加国际电子展会,与全球知名企业进行交流合作。同时,Dawning还根据不同国家和地区的市场需求,调整产品策略,推出符合当地消费者喜好的产品。经过几年的努力,Dawning的产品已经成功打入欧美、东南亚等多个国家和地区的市场,公司的国际化进程取得了显著进展。

Big-Sun Electronics Co Ltd公司的发展小趣事

Big-Sun Electronics Co Ltd公司在追求经济效益的同时,也积极履行社会责任。公司注重环保和节能减排,采用先进的生产工艺和设备,减少生产过程中的环境污染。此外,Big-Sun还积极参与社会公益事业,为当地社区的发展和教育事业做出了积极贡献。


这些故事旨在展示Big-Sun Electronics Co Ltd公司可能的发展历程,但请注意,这些并非基于实际发生的事件。如果需要了解Big-Sun Electronics Co Ltd公司的真实历史和发展故事,建议查阅相关官方资料或新闻报道。

粤翔(FlyWin)公司的发展小趣事
根据需求分析结果,选择合适的电压监测元件、电源管理元件、储能元件和保护元件。
Circuit Assembly公司的发展小趣事
如二极管、电阻等,用于防止电流反向或过载,保护电路安全。
广芯电子(BROADCHIP)公司的发展小趣事
如DC-DC升压/降压电路,用于在电压异常时调整电压输出,确保关键部件仍能正常工作。
全鹏(CHAMPION)公司的发展小趣事

随着全鹏在巴西市场的稳固地位,公司决定在2006年创立C3 TECH品牌,以进一步提升其品牌影响力。C3 TECH品牌的创立不仅增强了全鹏在巴西市场的竞争力,还为公司带来了更多的商机。通过精心策划的市场营销活动和优质的产品质量,C3 TECH品牌迅速获得了当地消费者的认可,并在市场上树立了良好的口碑。

问答坊 | AI 解惑

摩托罗拉出售汽车电子部 潜心发展通讯技术

   据外电报道,手机制造商摩托罗拉周一表示,公司将把其汽车电子业务部以10亿美元的价格出售给德国的一家轮胎公司大陆公司,这样摩托罗拉就可以更加专心致志地把重点放在发展通讯技术上。   这个拥有4500名员工的部门去 ...…

查看全部问答>

消费类电子产品仍然主宰MCU市场

本帖最后由 jameswangsynnex 于 2015-3-3 20:01 编辑 2006年,在消费类电子产品制造继续快速发展的带动下,中国MCU市场依旧保持了较好的发展势头,增长率继续维持在25%以上的高水平。从应用领域来看,一方面,消费电子产品仍是中国MCU市场需求的主 ...…

查看全部问答>

IR2110的问题

不知道大家有没有人用过IR2110的,我调了好长时间有一个问题始终无法解决。还请知道的人帮忙提示一下。 具体电路图如图所示: 当DTP结束,即上面的功率管截止的时候,下面的功率管的控制信号就会有一个类似于下降沿干扰的信号产生使得下面的功率 ...…

查看全部问答>

嵌入式系统资料

收集了一些东东,希望与大家一起分享…

查看全部问答>

模数转换后的8路二进制数用7段译码显示器输出电路---要硬件的

模数转换后的8路二进制数用7段译码显示器输出电路---要硬件的。。。。。。。。。。。。。。急急急,我作的毕业设计急用,哪位高手指点指点,发个图过来啊谢谢了…

查看全部问答>

未来电源的新功率半导体器件

这篇文章介绍了一些新型器件在电源设计上的应用,对电源设计人员来说,值得一读。 上传宣言:分享资料,分享快乐。…

查看全部问答>

LTIB介绍和安装(一)

因为eewrold每个帖子指数限制是1万字,只能切开分几个帖子,顺便说下,这个字数限制实在是没理由。 LTIB (Linux Target Image Builder)是飞思卡尔公司开发的一个工具,用于简化嵌入式bsp开发的工具,基本上就是一些脚本加上预先制作成功交叉工 ...…

查看全部问答>

PC连接windows mobile串口通信的问题

我用数据线连接mobile的USB口和电脑的USB口。想用串口通信的方法,写程序让这两个设备通信,这样可行吗?用CreateFile函数,但我不知道具体到哪一个串口。一个一个的试过了也没有成功接收到数据。手机上面的那个USB口我怎么才能知道是哪个口呢?电 ...…

查看全部问答>

知名公司高薪诚聘 hardwarePE

知名公司招聘硬件产品工程师,要求有硬件电路设计经验,熟练使用各种电子测试设备。 如下jd,有意者可咨询alice Job Title Hardware PE  (Shanghai) Roles and Responsibilities 1. This position will be to work as a member of ...…

查看全部问答>