Mike_python小 发表于 2023-1-19 09:15:40

51单片机 静态/动态数码管

本帖最后由 Mike_python小 于 2023-1-19 09:17 编辑

51单片机 静态/动态数码管

数码管在我们的生活中非常常见,但是这节课可能有点不一样
你需要学习2进制转16进制(1248码)
和10进制转2进制(短除法)

1248码
比如我有一串2进制,10100010,使用1248码转换16进制就应该这么写:

1248码从右向左写
二进制先写右边的,依次对应
如果二进制不从右向做写的话,可能出现以下问题:
101001

第一个结果是29,而第二个是A4

在16进制中,A代表着10,B代表着11,以此类推

总结:
1248和二进制从右向左写,最后读数正读

短除法
10进制转2进制的短除法非常简单
比如我要短除23这个数

先用23/2=11余1
然后以此类推
到1/2=0余1的时候也就结束了

最后从下往上读,结果就是10111

我们一般采用第二种写法,第一种是方便大家理解

静态数码管
说了这么多了,该说说静态数码管了

这是一个数码管的原理图,上面是共阳,下面是共阴,我用的数码管就是共阴的

共阴极:当某个发光二极管的阳极为高电平时,发光二极管点亮,相应的段被显示。
共阳极:将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管。

如右图所表,数码管上的8个小部分分别对应着几个IO口,所以我们只需要接通他们相对应的IO口,就可以实现点亮

比如我想点亮一个6,就需要知道abcdefg dp中需要哪个给1
AFGCDE,这几个点亮就可以变成一个6
所以我们看右图这几个对应的引脚
74219 10,把这几个引脚点亮就行了(PS:点亮需要给16进制,这里的太乱了,我懒得算了,等后面再算)

但是这只是一个数码管啊,我们的是4个连城一体的啊

看到这么多先不要着急,听我慢慢到来
首先左边的那些我们都不用看,只看两个大黄色的数码管就可以

这个数码管跟我们看到的一个的数码管很想,从下方都截出来了abcdefg dp这8个引脚,但是有一个问题,我们这8个数码管练成一体了,怎么就出来8条线(1一个数码管的线)?不应该是8x8=64条线吗?!

厂家为了减少IO口,就用了以下的方法:

看没看见每个数码管上方的LED8,LED7等等?这就是妙处

我们想要点亮比如说LED8的abcd,我们先给LED8一个1,就表明我们只要点亮led8,其他的是熄灭的,然后再把abcd点亮就行了~

如何把abcd点亮
我们把abcd点亮和单个数码管的一样,需要给abcd “1”,其他的 “0”

再从下网上数就是00001111,转化为16进制就是 0x0F

再看左侧,引脚都是P01,P02,P03,这时候我们采用统一赋值,给P0 = 0x0F
就可以把abcd点亮了

如何把LED8点亮

看这张图的右边,LED8对应着Y7,LED6对应着Y6,LED5对应着Y5

再看这张图的左边,有P22, P23, P24

这是有就有人要说了,为什么8个数码管用3个IO口就能控制????

好问题,这也是节省IO口的妙用

3个IO口正好可以表现0~7的10进制,比如P22, P23, P24都为1的时候就是7,都为0的时候就是0

那要控制LED7就是111,从下网上读对应的就是P24是1,P23也是1,P22也是1

那要控制LED6呢?就是110, P24是1,P23是1,P22就是0了
注意!二进制第一位要对应P24而不是P22

通过代码实现

#include <8052.h>
void main() {
    P2_4=1;
    P2_3=1;
    P2_2=1;

    P0 = 0x7D;
    while (1) {

    }


}


这里,我给大家总结了一个库,你们直接调用这个库就行
nixie.c

#include "Sleep.h"
#include <8052.h>

char num = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
    0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x00
};

void Nixie(unsigned char weizhi, unsigned char number) {
    P2 &= ~0x1c;
    P2 |= (~weizhi & 0x07) << 2;
    /*
    switch (weizhi) {
      case 1:
            P2_4 = 1;
            P2_3 = 1;
            P2_2 = 1;
            break;
      case 2:
            P2_4 = 1;
            P2_3 = 1;
            P2_2 = 0;
            break;
      case 3:
            P2_4 = 1;
            P2_3 = 0;
            P2_2 = 1;
            break;
      case 4:
            P2_4 = 1;
            P2_3 = 0;
            P2_2 = 0;
            break;
      case 5:
            P2_4 = 0;
            P2_3 = 1;
            P2_2 = 1;
            break;
      case 6:
            P2_4 = 0;
            P2_3 = 1;
            P2_2 = 0;
            break;
      case 7:
            P2_4 = 0;
            P2_3 = 0;
            P2_2 = 1;
            break;
      case 8:
            P2_4 = 0;
            P2_3 = 0;
            P2_2 = 0;
            break;
    }
    */
    // 因为这个number所表示的含义有点乱
    // 要改这个switch就得改number所表示的含义
    switch (number) {
      case 0: P0 = num; break;
      case 1: P0 = num; break;
      case 2: P0 = num; break;
      case 3: P0 = num; break;
      case 4: P0 = num; break;
      case 5: P0 = num; break;
      case 6: P0 = num; break;
      case 7: P0 = num; break;
      case 8: P0 = num; break;
      case 9: P0 = num; break;
      case 'A': P0 = num; break;
      case 'B': P0 = num; break;
      case 'C': P0 = num; break;
      case 'D': P0 = num; break;
      case 'E': P0 = num; break;
      case 'F': P0 = num;
      case ' ': P0 = num;
    }
    Sleep(2);
    P0 = 0x00;
}

这里要感谢@人造人 大佬

然后你们添加一个头文件
nixie.h

#ifndef __NIXIE_H__
#define __NIXIE_H__

void Nixie(unsigned char weizhi, unsigned char number);

#endif

之后直接调用这个库就行

比如说我想要在3处显示9
直接
Nixie(3, 9);
想在2处显示空
Nixie(2, ' ');
想在5处显示A
Nixie(5, 'A');

大家也可以自己丰富一下

动态数码管
因为厂家为了减少IO口,这8个数码管中不能同时打开,那怎么办呢?

利用数码管的余晖和人眼的残影保留,快速的开关开关数码管,欺骗人眼实现全部显示

在nixie库中我就已经做好了动态需要的步骤了
也就是最后的

    Sleep(2);
    P0 = 0x00;

sleep2是为了不要太快,不然就会有很明显的上一个的残影
P0=0x00也是为了消除数码管上次太多的残影

完整代码是这样的

#include <8052.h>
// #include "../Sleep.h"
#include "../nixie.h"



void main() {
    // P2_4=0;
    // P2_3=0;
    // P2_2=1;
    P2 = 0x00;
   

    while (1) {

      Nixie(1, 4);

      Nixie(2, 6);

      // Sleep(3);
      // P2_2 = 0;

    }


}




这节课有点难理解,建议去看看江科大的视频
如果有什么不理解的地方或者我有什么错误,请联系我
也可以在我的博客里看哦~https://cxwindlight.online/

Mike_python小 发表于 2023-1-19 09:19:10

AUV,评个分回回血吗{:10_280:}

MIke_python小小 发表于 2023-1-19 09:19:40

AUV{:10_256:}{:10_256:}{:10_256:}

Python_tkinter 发表于 2023-1-19 09:20:28

Mike_python小 发表于 2023-1-19 09:20:51

Python_tkinter 发表于 2023-1-19 09:20
AUV,您吉祥~我们北京没有马路,全是地道~

AUV吃了吗您

MIke_python小小 发表于 2023-1-19 09:21:19

Mike_python小 发表于 2023-1-19 09:20
AUV吃了吗您

要一盘西红柿炒鸡蛋(模糊)

人造人 发表于 2023-1-19 09:46:37

改成这样试试

#include "Sleep.h"
#include <8052.h>

static unsigned char code = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
    0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x00
};

void Nixie(unsigned char addr, unsigned char number) {
    if(number >= 17) return;
    P2 &= ~0x1c;
    P2 |= (~addr & 0x07) << 2;
    P0 = code;
    Sleep(2);
    P0 = 0x00;
}

// main.c
unsigned char i;
for(i = 0; i < 17; ++i) {
    Nixie(0, i);
    Sleep(1000);
}

Python_tkinter 发表于 2023-1-19 09:50:35

人造人 发表于 2023-1-19 09:55:21

所以说,你这14-15行是什么意思,去掉
#include "Sleep.h"
#include <8052.h>

static unsigned char code = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
    0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x00
};

void Nixie(unsigned char addr, unsigned char number) {
    if(number >= 17) return;
    P2 &= ~0x1c;
    P2 |= (~addr & 0x07) << 2;
    P0 = code;
}

// main.c
unsigned char i;
for(i = 0; i < 17; ++i) {
    Nixie(0, i);
    Sleep(1000);
}

人造人 发表于 2023-1-19 10:16:30

#include "Sleep.h"
#include <8052.h>

static unsigned char code = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
    0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x00
};

void Nixie(unsigned char addr, unsigned char number) {
    if(number >= 17) return;
    P0 = 0x00;      // 消影
    P2 &= ~0x1c;
    P2 |= (~addr & 0x07) << 2;
    P0 = code;
}

// main.c
unsigned char i;
for(i = 0; i < 17; ++i) {
    Nixie(0, i);
    Sleep(1000);
}
页: [1]
查看完整版本: 51单片机 静态/动态数码管