问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

51单片机数码管动态显示教程

创作时间:
作者:
@小白创作中心

51单片机数码管动态显示教程

引用
CSDN
1.
https://m.blog.csdn.net/qq_19394437/article/details/144102046

本文是一篇关于51单片机数码管动态显示的详细教程。通过本教程,读者将学习到数码管动态显示的基本原理、连接方式以及多个具体的实验项目实现。内容包括静态显示和动态显示的优缺点对比、动态扫描显示的原理,以及多位数码管的动态显示等。每个实验项目都包含了需求分析、硬件连接和完整的代码实现,适合有一定基础的电子工程或嵌入式系统学习者。

项目分析

通过演示数码管动态显示的操作过程,帮助读者理解数码管动态显示的基本原理和实现方法。

技术准备

数码管动态显示

静态显示的连接方式

  • 优点:不需要动态刷新
  • 缺点:占用IO口线多

动态显示的连接方式

  • 连接:所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效
  • 缺点:需要动态刷新
  • 优点:占用IO口线少

动态扫描的原理

动态显示是多个数码管,交替显示,利用人的视觉暂停作用使人看到多个数码管同时显示的效果(就像看的电影是有一帧一帧的画面显示的,当速度够快的时候看到它就是动态的,当显示数码管的速度够快的时候,也就可以看到它们是同时显示了)。

所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示的亮度低,所以在选择限流电阻时应小于静态显示电路中电阻值。

项目实施

一位数码管动态显示

实验需求

第1位数码管从 0 - 9 循环显示

实验分析

位选:第1位数码管(P2.4)工作设置为1,其他3个数码管不工作设置为0
段选:需要数码管显示0-9,则可使用数组存储 0-9 的十六进制值。
设置段选,循环中遍历数组中的值,并赋值给段P0。

实验代码

#include<reg52.h> 
#define pos P2
// 显示数值表0-9
unsigned char code dofly_table[10] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
// 函数声明
void Delay(unsigned int t); 
void main()
{
    unsigned char i;  
    
    pos = 0x18;
    
    while (1) {       
        for (i = 0; i < 10; i++) { 
            P0 = dofly_table[i];  
            Delay(60000);     
        }
    }
}
/*------------------------------------------------
 延时函数,含有输入参数 unsigned int t,无返回值
 unsigned int 是定义无符号整形变量,其值的范围是0~65535
------------------------------------------------*/
void Delay(unsigned int t)
{
    while (--t);
}

数码管左移流动显示

实验需求

在左数第4位数码管显示4,过1秒,
在左数第3位数码管显示3,过1秒,
在左数第2位数码管显示2,过1秒,
在左数第1位数码管显示1,过1秒,
上述过程不断循环

实验分析

位选:循环让4个数码管工作
段选:让对应的位分别显示 4 3 2 1

实验代码

方式1:按位逐一设置显示

#include <REGX52.H>
#define par P0
#define pos P2
#define uchar unsigned char
#define void delay(unsigned int xms);
// 分别对应:1/2/3/4
uchar code sz[] = {0x06, 0x5b, 0x4f, 0x66};
void main()
{
    while (1)
    {
        pos = 0x88;
        par = sz[3];
        delay(1000);
        
        pos = 0x48;
        par = sz[2];
        delay(1000);
        
        pos = 0x28;
        par = sz[1];
        delay(1000);
        
        pos = 0x18;
        par = sz[0];
        delay(1000);
    }
}
void delay(unsigned int xms)
{
    unsigned int i, j;
    for(i=xms; i>0; i--)
    {
        for(j=112; j>0; j--);
    }
    return 0;
}

方式2:定时器 + 数组遍历

#include <reg52.h>
#define uint unsigned int
    
// 定义端口:P2/P0、2个数组(存储位选与段选值)、定时器次数、数组索引
#define pos P2
#define par P0
uint posValues[] = {0x18, 0x28, 0x48, 0x88};
uint parValues[] = {0x06, 0x5b, 0x4f, 0x66};
uint count = 0;
uint index = 3;
void main2()
{
    // 3.1 设置工作模式
    TMOD = 0x01;
    
    // 3.2 设置初值 - 50ms  --> 次数 * 机器周期 = 0.05s  -> 次数 = 0.05 * 12 * 10^6 / 12
    TH0 = (65536 - 50000) / 256;
    TL0 = (65536 - 50000) % 256;
    
    // 3.3 打开“开关”
    EA = 1;
    TR0 = 1;
    ET0 = 1;
    
    while(1);
}
// 中断函数
void timer0() interrupt 1
{
    TH0 = (65536 - 50000) / 256;
    TL0 = (65536 - 50000) % 256;
    
    count++;
    
    if(count == 20)   // 1s
    {
        count = 0;
        
        pos = posValues[index];
        par = parValues[index];
        
        if(index <= 0)
        {
            index = 4;
        }
        
        index--;
    }
}

数码管数字0转圈显示

实验要求

使用第1位数码管的 a b c d e f 六段依次点亮

实验分析

效果 h g f e d c b a
a亮 0 0 0 0 0 0 0 1
b亮 0 0 0 0 0 0 1 0
c亮 0 0 0 0 0 1 0 0
d亮 0 0 0 0 1 0 0 0
e亮 0 0 0 1 0 0 0 0
f亮 0 0 1 0 0 0 0 0

代码实现

#include <reg52.h>
#define pos = P2;  
unsigned int temp;
unsigned char i;
void delay(unsigned int t);
void main()
{
    pos = 0x18;
    
    while (1) {
        P0 = 0xff;
        for (i = 0; i < 6; i++) {
            delay(10000);
            temp = 0x01 << i;
            P0 = temp & 0xff;
        }
    }
}
void delay(unsigned int t)
{
    while (t--);
}

数码管显示00-99

实验要求

使用2位数码管显示00-99,每次间隔1s,如果到99则重新从0开始

实验分析

位选:使用第1位数码管显示十位,第2位数码管显示个位
段选:使用变量记录两位数,在每1秒中对该变量加1,同时分别取出个位与十位,对应到存储0-9的数组中取出对应的数,用于段选的值。

实验代码

#include <reg52.h>
 
// 宏定义:简写 unsigned int
#define uint unsigned int
 
sbit pos = P2; 
 
// 分别对应:0/1/2/3/4/5/6/7/8/9
int code_sz[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
 
// 函数声明
void show_ge(uint x);
void show_shi(uint y);
void delay(uint xms);   
 
uint val = 0;  // 记录显示的2位数
uint ge, shi;
 
void main()
{
    while (1)
    {
        val++;                   // 计数值增加1
        if (val > 99) val =0;    // 如果计数值大于99,则重新从0开始
 
        ge = val % 10;     // 计算个位的值
        shi = val / 10;    // 计算十位的值
        show_shi(shi);     // 调用显示十位的函数
        delay(10);         // 延时10ms,让十位数显示保持
        show_ge(ge);       // 调用显示个位的函数
        delay(10);         // 延时10ms,让十位数显示保持
        pos = 0;          // 位选复位(避免出现位选错乱,产生乱码)
    }
}
 
 
// 显示个位数字:左起第2位数码管
void show_ge(uint x)   // x:计算的个位数的值,对应数组中的索引,从而取到对应的值
{
    P0 = 0x00;     // P0(段选位)复位
    pos = 0x28;    // 第2位数码管
    P0 = code_sz[x];   // 数组索引取到对应的数字值赋值给P0
}
 
void show_shi(uint y)  // y:计算的十位数的值,对应数组中的索引,从而取到对应的值
{
    P0 = 0x00;     // P0(段选位)复位
    pos1 = 0x18;      // 选择第1位数码管
    P0 = code_sz[y];    // 数组索引取到对应的数字值赋值给P0
}
 
void delay(uint ms)   // 延时指定的毫秒(错略延时)
{
    uint i, j;
    for(i=ms; i>0; i--)
    {
        for(j=112; j>0; j--);
    }
}

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号