[经验分享] 51单片机 数码管动态显示代码优化

[复制链接]
1459|0
观海 发表于 2025-10-11 15:36 | 显示全部楼层 |阅读模式
一  数码管的动态显示(软件篇)
1 书写代码1
我们要在这个数码管上面显示我们的所想要的数字

#include <STC89C5xRC.H>
// #define SMG_EN
typedef unsigned char u8;
typedef unsigned long u32;
//0~9数字的编码
static u8 codes[10]={
    0x3F,
    0x06,
    0x5B,
    0x4F,
    0x66,
    0x6D,
    0x7D,
    0x07,
    0x7F,
    0x6F
// 0x3F → 00111111
// 0x06 → 00000110
// 0x5B → 01011011
// 0x4F → 01001111
// 0x66 → 01100110
// 0x6D → 01101101
// 0x7D → 01111101
// 0x07 → 00000111
// 0x7F → 01111111
// 0x6F → 01101111
};

u8 buffer[8];

//pos表示的位位置      numcode表示的位数字
void digital(u8 pos, u8 numcode){
    //位选

    //p22 p23 p24是改变这个位置的
    //p2 = 110 111 11
    //pos = 0000 0011(后面三位是0~7),把后面三位赋予到中间的101
    // 110 111 11
    // 000 011 00(position左移两位)

    pos<<=2;
    //p1 &= 111 000 11
    P2 &= 0xe3;
    P2 |= pos;

    // P22 = 0;
    // P23 = 0;
    // P24 = 0;

    //段选
    P0 = numcode;
}

void digitalnum(u32 num){
    //残留问题的解决
    u8 i;
    for(i = 0; i < 8; i++){
        buffer = 0x00;
    }

     i = 7;
     while(num > 0){
        buffer = codes[num%10];
        num /= 10;
        i--;
     }
}

//动态扫描
void digitalfresh(){
    u8 i;
    //for循环里面不可以定义变量
    for(i = 0; i < 8; i++){
        digital(i, buffer);
    }
}

void main(){

    digitalnum(12345);
    while(1){
        digitalfresh();
    }
}


逻辑的分析
(1)  显示数字函数

void digitalnum(u32 num)
这个函数就是表示为我们不断地把这个数字分段分到这个数组里面,直到这个数字分到0位置,这个数字为0,就要进行特殊处理。

(2)  刷新数字函数

void digitalfresh()
这个函数是不断地更新这个数字到这个屏幕上面,然后时间很短,就显示出了一个稳定地数字在屏幕上,因为肉眼捕捉不到。

但是这个代码还是不是特别好因为会有残影,是下面这样的



(3)  残生残影的原因

    位选
    pos<<=2;
    P2 &= 0xe3;
    P2 |= pos;

    段选
    P0 = numcode;


这个残影产生的原因是当进入第一个位置赋值的时候,先进行位选,然后再进行段选,当我进行段选之后,段选是1的二进制编码,然后当进行下一次的位选的时候,由于进行完下一次位选之后,我的段暄还是保持之前的段选1,那么就会在这里留下残影,这个是我们需要去解决的问题。

2 优化代码
  为了解决上面的那一个代码,现在选择优化代码。

#include <STC89C5xRC.H>
// #define SMG_EN
typedef unsigned char u8;
typedef unsigned long u32;
//0~9数字的编码
static u8 codes[10]={
    0x3F,
    0x06,
    0x5B,
    0x4F,
    0x66,
    0x6D,
    0x7D,
    0x07,
    0x7F,
    0x6F
// 0x3F → 00111111
// 0x06 → 00000110
// 0x5B → 01011011
// 0x4F → 01001111
// 0x66 → 01100110
// 0x6D → 01101101
// 0x7D → 01111101
// 0x07 → 00000111
// 0x7F → 01111111
// 0x6F → 01101111
};

u8 buffer[8];

//pos表示的位位置      numcode表示的位数字
void digital(u8 pos, u8 numcode){
    //位选
    //每一赋值关掉上一位
    P0 = 0x00;

    pos<<=2;
    //p1 &= 111 000 11
    P2 &= 0xe3;
    P2 |= pos;

    // P22 = 0;
    // P23 = 0;
    // P24 = 0;

    //段选
    P0 = numcode;
}

void digitalnum(u32 num){
    //残留问题的解决
    u8 i;
    for(i = 0; i < 8; i++){
        buffer = 0x00;
    }

     i = 7;
     while(num > 0){
        buffer = codes[num%10];
        num /= 10;
        i--;
     }
}

//动态扫描
void digitalfresh(){
    u8 i;
    //for循环里面不可以定义变量
    for(i = 0; i < 8; i++){
        digital(i, buffer);
    }
}

void main(){

    digitalnum(12345);
    while(1){
        digitalfresh();
    }
}



但是这还是会存在一个问题,0赋值不可以,因为num循环逻辑为num>0,那么就是我们num赋值为0的话,就会导致错误。

void digitalnum(u32 num){
    //残留问题的解决
    u8 i;
    for(i = 0; i < 8; i++){
        buffer = 0x00;
    }

    if(num == 0){
        buffer[7] = codes[0];
        return;
    }

     i = 7;
     while(num > 0){
        buffer = codes[num%10];
        num /= 10;
        i--;
     }
}



这样就十分完美了
————————————————
版权声明:本文为CSDN博主「一只自律的鸡」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/2401_86738532/article/details/151762520

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

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

本版积分规则

153

主题

4405

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部