原创 二位半 5线数码管的驱动方法

2025-5-7 15:06 103 0 1 分类: MCU/ 嵌入式 文集: STM32 软件
二位半 5线数码管的驱动方法

这个2位半的7段数码管只用5个管脚驱动。如果用常规的7段+共阳/阴则需要用10个管脚。

https://img.alicdn.com/imgextra/i4/3606845757/O1CN01268XYl1sOkz8GqXx1_!!3606845757.jpg

如果把每个段看成独立的灯。5个管脚来点亮,任选其中一个作为COM端时,另外4条线可以单独各控制一个灯。所以实际上最多能驱动5*4 = 20个段。但是这里会有一个小问题。如果想点亮B1,可以让第3条线(P3)置高,P4 置低,其它阳极连P3的灯对应阴极P2 P1都应置高,此时会发现C1也会点亮。实际操作时,可以把COM端线P3设置为PP输出,其它线为OD输出。就可以单独控制了。

实际的驱动程序如下:

先定义一个二维数组描述数码管段与管脚对应关系

const uint8_t DotDecode[16][2] =

{

/*

3   4   B1

2   4   C1

2   3   A2

3   2   B2

4   3   C2

4   2   D2

5   2   E2

5   3   F2

5   4   G2

1   2   A3

2   1   B3

1   3   C3

3   1   D3

1   4   E3

4   1   F3

5   1   G3*/    

{3, 4},{2,  4},{2,  3},{3,  2},{4,  3},{4,  2},{5,  2},{5,  3},

{5, 4},{1,  2},{2,  1},{1,  3},{3,  1},{1,  4},{4,  1},{5,  1}

};

定义段与要显示的数据译码

const uint8_t SEGMENT_CODES[] = {

    0x7E, // 0

    0x30, // 1

    0x6D, // 2

    0x79, // 3

    0x33, // 4

    0x5B, // 5

    0x5F, // 6

    0x70, // 7

    0x7F, // 8

    0x7B, // 9

    0x77, // A

    0x1F,   // b

    0x4E,   // C

    0x3D, // d

    0x4F, // E

    0x47, // F

};

定义一个16位变量,用于存储需要点亮的段。

uint16_t vram;

编写一个函数,将需要显示的数据映射到vram中,如果不显示把vram清零

void RefreashVram(uint8_t dat,uint8_t on){

    uint8_t temp;

    uint16_t temp16 = 0;

    temp = dat;

    if(on){

        if(temp >= 100){

           temp16 = 0xc000;

           temp %= 100;

           temp16 |= (SEGMENT_CODES[temp/10] << 7);

           temp16 |= SEGMENT_CODES[temp%10];

        }

        else if(temp >= 10){

           temp16 |= (SEGMENT_CODES[temp/10] << 7);

           temp16 |= SEGMENT_CODES[temp%10];

        }

        else

           temp16 |= SEGMENT_CODES[temp];

        vram = temp16;

    }

    else

        vram = 0;

}

下面是对操作引脚的定义,为方便编程序,定义一个端口指针数组和一个引脚号数组,然后就可以定引脚设置PP OD 置高置低操作了。

GPIO_TypeDef *drvport[5] = {DRV1_GPIO_Port,DRV2_GPIO_Port,DRV3_GPIO_Port,DRV4_GPIO_Port,DRV5_GPIO_Port};

uint16_t drvpin[5] = {DRV1_Pin,DRV2_Pin,DRV3_Pin,DRV4_Pin,DRV5_Pin};

#define setpp(i) drvport[i-1]->OTYPER &= ~drvpin[i-1]

#define setod(i) drvport[i-1]->OTYPER |= drvpin[i-1]

#define drivehi(i) drvport[i-1]->ODR |= drvpin[i-1]

#define drivelo(i) drvport[i-1]->ODR &= ~drvpin[i-1]

编写一个刷新显示的程序,需要每1ms执行一次。每次选取一条线作为COM端。扫描点阵矩阵,如果单元1中与COM相同,并且vram的对应位是1,则将单元2对应的引脚置低。

其它引脚置高。最后设置COM引脚为PP,其它为OD。就能刷新显示数据了。

void DisplayDigtal(){       //1ms 刷新显示一次

    static uint8_t com = 1;

    uint8_t drv = 0xFF;    // 存储 驱动线需要输出的状态

    if(vram == 0){

        for(uint8_t i = 5;i>0;i--)

                drivelo(i);

        return;

    }

    for(uint8_t i = 0;i<16;i++){

        if(DotDecode[0]==com){

            if((vram & (1<<(15-i))) != 0)        // 对应位不为0

                drv &= ~(1<<DotDecode[1]);

        }

    }

    for(uint8_t i = 5;i>0;i--){

                setod(i);

        if((drv & (1<<i)) == 0)

            drivelo(i);

        else

            drivehi(i);

    }

        setpp(com);

    com = (com < 5)? com+1:1;

}

另外增加一个快速灭显示的函数,就是把所有引脚置为OD输出。

void TurnoffDigital(void){

    setod(1);

    setod(2);

    setod(3);

    setod(4);

    setod(5);  

}

使用时,调用RefreashVram函数,将需要显示的数据转化为vram中的点。就能显示出来。

下面是动态显示数据的实例。

作者: southcreek, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-408807.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

eeNick 2025-5-7 17:10

感谢分享,奖励30E币
相关推荐阅读
southcreek 2025-04-03 09:49
电路设计中的口线复用例子
实例1:设置GPIO为输入或输出完成读取状态和驱动LED功能。下面这个电路使用3个gpio 用于读取拔码开关的设置和驱动3个LED流水灯显示。拔码开关在开机时需要读取一次。使用过程中不需要使用。如果单...
southcreek 2025-02-20 13:35
供电开关电路不良引起的MCU程序跑飞及解决办法
这是一个3.3V 的供电开关,给WIFI模块供电。目的是能控制WIFI模块通电或断电。VCC_3V3 是电源,当WLENN为低时,Q1打开输出VCCW 给WIFI模块供电。实际使用时,当控制WLENN...
southcreek 2025-01-22 06:34
设置可执行程序图标
在本文的示例中,图标文件名称为“logo.ico”,该文件位于项目主目录下。2.2 设置标题栏图标通过下列函数设置标题栏图标:setWindowIcon(QIcon("://logo.ico"));1...
southcreek 2024-12-04 16:32
PWM输出隔离DAC设计
这个设计的目标是产生一个隔离的DAC输出。12V供电,产生0~5V的输出。达到10000约13.3位的分辨率。要求DAC输出在改变设置后1S内能稳定。需要能长时间保持稳定和低噪声。能达到要求的DAC只...
southcreek 2024-12-04 15:23
一个基于HAL库的串口控制框架
将串口接收配置为 DMA方式,DMA 使用 DMA_CIRCULAR 模式工作。串口接收的数据实际上构成循环队列。 定义一个结构Comm_typedef 结构体中包含指向接收到的第一字节位置chrc...
我要评论
1
0
关闭 站长推荐上一条 /3 下一条