本帖最后由 WL0123 于 2026-3-30 22:07 编辑
极简的单排5脚188数码管的驱动方法试探
在一些低档消费电子产品中常见一种单排5脚188和单排6脚1888数码管。由于这种数码管内部结构异于常见的数码管。商家提供的内部LED与引脚关系图看上去也感觉杂乱无章。仔细研究一番其实就是一种矩阵连接关系,以单排5脚188为例,将原图重新排列一下就可以明显看出来就是一种共阴关系。一次最多可以点亮4个笔段。如果单片机引脚直接连接数码管有过流损坏单片机端口的风险,如果数码管每个脚接限流电阻,由于需要点亮的笔段不确定,随亮点多少不同亮度会不均匀,为此利用新型单片机端口的高阻模式和内置上拉电阻,按需要点亮的笔段使能上拉电阻提供驱动电流。作为当前用作共阴的端口设准双向模式低电平,不论需要点亮的笔段多少,各笔段亮度一致。5脚188数码管共16个笔段,需要分4次才能完成全部笔段扫描。由此制作一个表格,将8位标准段码拆解为5位驱动码。实践证明:数码管亮度能够满足大多数应用场景,并且无鬼影。还有其他更简洁的驱动方式,欢迎坛友探讨。
- //5脚188数码管驱动程序示例
- //使用STC8H1K08单片机
- #include <STC8H.H>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar code table[]={ //数码管段码0~f
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- uint count; //计数
- uchar num; //计数
- uchar w1,w2,w3; //数码管位
- bit flag; //中断标志
- void Timer0_Init(); //初始化定时器0
- void display(); //显示函数
- //主函数
- void main()
- {//端口模式初始化
- P1M0 = 0x00;P1M1 = 0x00;//准双向
- P3M0 = 0x00;P3M1 = 0x00;//准双向
- P5M0 = 0x00;P5M1 = 0x00;//准双向
- P_SW2 |= 0x80; //打开扩展存储器
- Timer0_Init(); //初始化定时器0
- while(1)
- {
- if(flag)
- {
- flag=0; //周期5ms
- display(); //显示函数
- if(++count>=100) //0.5s
- {
- count=0;
- if(++num>188)num=0;
- if(num>=100)w1=table[1];
- else w1=0x00;
- w2=table[num/10%10];
- w3=table[num%10];
- }
- }
- }
- }
- void Timer0_Isr(void) interrupt 1
- {
- flag=1;
- }
- void Timer0_Init(void) //5毫秒@11.0592MHz
- {
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD &= 0xF0; //设置定时器模式
- TL0 = 0x00; //设置定时初始值
- TH0 = 0x28; //设置定时初始值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- ET0 = 1; //使能定时器0中断
- EA = 1; //使能总中断
- }
- //数码管显示函数
- void display()
- {
- static uchar i=0;
- uchar a[4];
- switch(i)
- {/******************5位***********4位**********3位**********2位**********1位***********/
- case 0: a[0]=(w3>>2&0x10)|(w3>>2&0x08)|(w3>>1&0x04)|(w3<<0&0x02)|(0 /*COM1*/); break;
- case 1: a[1]=(w2>>0&0x10)|(w2<<0&0x08)|(w2<<1&0x04)|(0 /*COM2*/)|(w3>>0&0x01); break;
- case 2: a[2]=(w2>>1&0x10)|(w2<<1&0x08)|(0 /*COM3*/)|(w2<<1&0x02)|(w3>>2&0x01); break;
- case 3: a[3]=(w2>>2&0x10)|(0 /*COM4*/)|(w1<<1&0x04)|(w1>>1&0x02)|(w3>>4&0x01); break;
- }
- P1M1=~(0x01<<i)&0x1f; //P1.0~1.3轮流高阻转准双向
- P1PU=a[i]; //按位使能上拉电阻提供高电平驱动电流,代替端口寄存器高电平
- P1=a[i]; //按COM位提供低电平共地驱动电流,其它位为高阻模式,高低电平无关
- i=++i%4; //循环计数
- }
复制代码
|