历史上的今天
返回首页

历史上的今天

今天是:2025年05月07日(星期三)

正在发生

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

2018-05-07 来源: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。直接上代码。

#include "reg51.h"  

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

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

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

 void main()  

 {  

    P0 = seg[6];  

    QIAN = 0;  

    while(1)  

    {  

          

    }  

 }  

程序中,显示定义了段码,进入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。直接上代码:

#include "reg51.h"  

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

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

 sbit QIAN = P2^0;  

 char i;  

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

  

 void delay(unsigned int x)  

 {  

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

    {  

        x--;  

    }     

 }  

  

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

 {  

    char i;  

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

    {  

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

        P0 = seg[smgbuf[i]];  

        P2 = ~(1<

        delay(200);  

    }  

 }  

  

 void main()  

 {  

    while(1)  

    {  

        load_smg();  

    }  

 }  

实验三

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


main.c文件



#include "reg51.h"  

unsigned int count;  

extern void load_smg();  

  

void main()  

 {  

    int a;  

    while(1)  

    {  

        load_smg();  

        a++;  

        if(a>=200)  

        {  

            count++;  

            a=0;              

        }  

    }  

 }  

smg.c文件


 #include "reg51.h"   

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

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

 char i;  

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

 sbit QIAN = P2^0;  

 extern unsigned int count; //外部申明  

  

 void delay(unsigned int x)  

 {  

    while(x)     

    {  

        x--;  

    }     

 }  

  

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

{  

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

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

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

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

}  

  

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

 {  

    char i;  

    fill_smgbuf();  

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

    {  

        P0=0xFF;    

        P0 = seg[smgbuf[i]];  

        P2 = ~(1<

        delay(200);  

    }  

 }  

实验四

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

main.c文件


#include "reg51.h"  

  

extern void load_smg();  

extern delay(unsigned int x);  

extern void key1();  

extern void key2();  

  

unsigned int count;  

  

void main()  

 {  

    while(1)  

    {  

        load_smg();  

        key1();  

        key2();  

    }  

 }  

smg.c文件


 #include "reg51.h"   

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

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

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

 extern unsigned int count;   

  

 void delay(unsigned int x)  

 {  

    while(x)     

    {  

        x--;  

    }     

 }  

  

void fill_smgbuf()   

{  

    smgbuf[0]=count/1000;    

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

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

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

}  

  

void load_smg()     

 {  

    char i;  

    fill_smgbuf();  

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

    {  

        P0=0xFF;     

        P0 = seg[smgbuf[i]];  

        P2 = ~(1<

        delay(200);  

    }  

 }  

key.c文件


#include "reg51.h"  

extern delay(unsigned int x);  

extern unsigned int count;  

sbit K1=P2^4;  //+1  

sbit K2=P2^5;   //-1  

  

void key1()  

{  

    static char st;  

    if(K1==0)  

    {  

        if(st==0)  

        {  

            delay(5000);  

            if(K1==0)  

            {  

                st=1;  

                count++;  

            }  

        }  

    }  

    else  

    {  

        st=0;  

    }  

}  

  

void key2()  

{  

    static char st;  

    if(K2==0)  

    {  

         if(st==0)  

         {  

            delay(5000);  

            if(K2==0)  

            {  

                st=1;  

                count--;  

            }  

         }  

    }  

    else  

    {  

        st=0;  

    }  

}  

这个实验有一个地方需要注意,即每当复位,按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、尝试分别用四个键去控制个十百千四个数码管的闪烁。


推荐阅读

史海拾趣

川土(Chipanalog)公司的发展小趣事

2016年,上海川土微电子有限公司(简称“川土微电子”)正式成立,标志着Chipanalog川土微电子的诞生。作为一家专注于模拟芯片产品研发与销售的高科技公司,川土微电子从成立之初就明确了其核心使命——为中国电子信息制造企业提供高品质进口替代模拟芯片。在创始人及团队的共同努力下,公司迅速确定了发展方向,并开始着手研发首款模拟芯片产品。

First Switchtech公司的发展小趣事

面对日益激烈的全球竞争,First Switchtech公司(或类似公司)制定了积极的国际化战略。公司首先在欧洲市场设立了分支机构,通过深入了解当地市场需求和文化背景,成功推出了符合欧洲标准的电子开关产品。随后,公司进一步拓展北美、亚洲等市场,通过本地化生产和营销策略,实现了全球市场的覆盖。这一过程中,公司不仅提升了品牌知名度,还积累了丰富的国际市场运营经验。

FILTRONIC公司的发展小趣事

随着市场需求的不断增长,FILTRONIC开始着手拓展产品线,从单一的滤波器产品扩展到包括射频模块、天线等在内的多种无线通信产品。同时,公司也积极实施国际化战略,通过参加国际展会、设立海外办事处等方式,逐步打开了国际市场的大门。FILTRONIC的产品以其卓越的性能和可靠的质量赢得了全球客户的信赖,公司也因此实现了业务的快速增长。

AIM - American Iron and Metal公司的发展小趣事

为了进一步提升竞争力,AIM开始着手整合电子行业的上下游产业链。公司通过收购、合资等方式,与多家供应商和合作伙伴建立了紧密的合作关系。这种整合不仅降低了生产成本,还提高了产品的质量和交付速度,使AIM在激烈的市场竞争中保持领先地位。

GigPeak公司的发展小趣事

为了进一步增强市场地位和扩大产品线,GigPeak在2010年实施了一项重要的并购战略。公司成功收购了另一家在光纤通信领域具有深厚技术积累的企业,这次并购不仅为GigPeak带来了先进的产品线和研发资源,还显著提升了其在全球市场的份额。通过整合双方的优势资源,GigPeak在光纤通信领域的技术实力和市场份额均实现了质的飞跃。

Exar公司的发展小趣事

面对日益激烈的市场竞争和不断变化的市场需求,Exar公司始终坚持以创新为核心竞争力。公司不断投入研发资金,加强技术创新和产品研发力度,推出了一系列具有自主知识产权的新产品。同时,Exar还积极关注行业发展趋势和市场动态,不断调整和优化产品线,以适应市场的变化和发展。在未来,Exar将继续坚持创新驱动的发展战略,努力成为电子行业的领军企业。

请注意,以上故事框架仅供参考,具体的故事内容需要根据实际情况进行补充和完善。

问答坊 | AI 解惑

请教通讯线上的高压问题

在监控线路上通讯线了时常被高压损坏是什么原因阿,主要损坏通讯芯片,基本上芯片会被击穿…

查看全部问答>

关于shellexcuteEX问题

我想要用shellexcuteEX来实现打开CMD,输入这样一行代码:CEMGRC.EXE /S /T:TCPIPC.DLL /Q /D:10.100.148.124:2777 然后还要输入回车,应该怎么用?很急,对了给全分,PS:我是要在EVC下面做这个程序.…

查看全部问答>

请大家帮忙

我重装系统,需要显卡驱动,不过当时厂家,没有送驱动盘,我在网上找了一些,不过都不是兼容的,没用,我用的是windows vist的系统,显卡是   geforce 7100gs ,请大家帮忙找一下,谢谢!…

查看全部问答>

Altium Designer Winter 09 一问

本人是PCB的新手,最近使用Altium Designer Winter 09 Build8.3.0.16776 在绘一张板,绘完发现一个问题,就是板子沒法显示通扎九孔。后来嘗试把文件另存为比较低版本的Altium Designer 文件后,便可以显示通孔了。可惜在文件转換中很多元件位置、线 ...…

查看全部问答>

to版主,STM32F107的以太网PHY能使用DM9161AEP吗?

                                 to 版主,STM32F107的以太网PHY能使用DM9161AEP吗?…

查看全部问答>

烂C-SPY,设不了断点...

在C-SPY,中设断点时, 总出现: Error[130]:"some breakpoint could not be set", 不论在那条语句上设都设不了。 ???????????????? 比其它51系列或者96系列的仿真器来说,C-SPY 的调试简直就是地狱!!!…

查看全部问答>

ulink2 如何给板子供电啊?需要怎么设置啊

本帖最后由 paulhyde 于 2014-9-15 03:48 编辑 ulink2 如何给arm板子供电啊?需要怎么设置啊 请问有人知道吗?求教啊  …

查看全部问答>

关于LM3S8962的I2C读取honeywell传感器实验

honeywell新一代的传感器很多是I2C输出。 手头有两个气体流量传感器,于是想在EK-LM3S8962开发板上测试一下。   程序参考周立功的I2C读取LM75A例程,以及本版面的经验贴:https://bbs.eeworld.com.cn/viewthread.php?tid=231364 honeywell ...…

查看全部问答>

这个问题太奇怪了 紧急求助啊

parameter D0=3\'b000;                     D1=3\'b001;                     D2=3\'b010;   &nb ...…

查看全部问答>

codewarrior 警告C1420

codewarrior 在编译时提示警告信息如下:Warning : C1420: Result of function-call is ignored 哪位大哥告诉我一下这是什么意思,怎么解决? 芯片为MC9S08DZ60 [ 本帖最后由 kwq498901 于 2012-3-31 09:29 编辑 ]…

查看全部问答>