找回密码
 立即注册
查看: 2257|回复: 19

简简单单点个6条腿的8段LED数码管

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-08 01:06:54
已绑定手机

35

主题

2111

回帖

2259

积分

荣誉版主

积分
2259
发表于 2024-4-2 15:05:35 | 显示全部楼层 |阅读模式
开发板上常见的7段数码管都是共阴或者共阳结构的,
分为SEG和COM段,驱动代码也比较好写,行列刷新嘛,
但是很多廉价的电子产品比如充电宝、电池仓上面用的,
数码管就比较简单了,只有很少的引脚,
看灯珠的结构也是比较无序的,相对来说比较难搞,
由于项目需要嘛,不得不搞一下,于是某宝买了几个样品,
试着驱动一下。

数码管的灯珠结构如下,看起来比较乱,实际上也是真的乱。
试了一下点亮所有段码,亮度还行,可以进行下一步驱动了。
PS:点亮所有段码的方式很简单,
每次使1个引脚拉低,其余拉高即可,然后循环扫描。


QQ截图20240130211834.png
微信图片_20240402144254.jpg


1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
睁开眼睛做场梦~~~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-08 01:06:54
已绑定手机

35

主题

2111

回帖

2259

积分

荣誉版主

积分
2259
发表于 2024-4-2 15:06:19 | 显示全部楼层
驱动好的效果如下,貌似还不错

睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-08 01:06:54
已绑定手机

35

主题

2111

回帖

2259

积分

荣誉版主

积分
2259
发表于 2024-4-2 15:19:02 | 显示全部楼层
下面介绍一下实现方法,
单片机为STC8G1K17,其它STC单片机也一样用的
定义管脚
  1. sbit PIN1 = P3^0;      //数码管
  2. sbit PIN2 = P3^1;      //数码管
  3. sbit PIN3 = P3^2;      //数码管
  4. sbit PIN4 = P3^3;      //数码管
  5. sbit PIN5 = P5^5;      //数码管
  6. sbit PIN6 = P5^4;      //数码管
复制代码

3个7段数码管,2个小数点,2个温度符号,一共是25个段,定义32位段位码,每个段占一位
  1. //各个LED灯珠代表的位
  2. #define A1 0x00000001
  3. #define B1 0x00000002
  4. #define C1 0x00000004
  5. #define D1 0x00000008
  6. #define E1 0x00000010
  7. #define F1 0x00000020
  8. #define G1 0x00000040
  9. #define A2 0x00000080
  10. #define B2 0x00000100
  11. #define C2 0x00000200
  12. #define D2 0x00000400
  13. #define E2 0x00000800
  14. #define F2 0x00001000
  15. #define G2 0x00002000
  16. #define A3 0x00004000
  17. #define B3 0x00008000
  18. #define C3 0x00010000
  19. #define D3 0x00020000
  20. #define E3 0x00040000
  21. #define F3 0x00080000
  22. #define G3 0x00100000
  23. #define DP1 0x00200000
  24. #define DP2 0x00400000
  25. #define K1 0x00800000
  26. #define K2 0x01000000
复制代码
定义三位数码管的显示表 其实就是显示字符需要点对应段位码,比如显示1,就点亮B1 C1,一行一个状态。
  1. //第一个7段码从0~9对应的编码
  2. code u32 digit1[11] =
  3. {
  4.         A1|B1|C1|D1|E1|F1,         //0
  5.         B1|C1,                                //1
  6.         A1|B1|D1|E1|G1,                //2
  7.         A1|B1|C1|D1|G1,                //3
  8.         B1|C1|F1|G1,                //4
  9.         A1|C1|D1|F1|G1,                //5
  10.         A1|C1|D1|E1|F1|G1,        //6
  11.         A1|B1|C1,                        //7
  12.         A1|B1|C1|D1|E1|F1|G1,//8
  13.         A1|B1|C1|D1|F1|G1,        //9
  14.         0,                        //黑 消隐
  15. };
  16. //第二个7段码从0~9对应的编码
  17. code u32 digit2[11] =
  18. {
  19.         A2|B2|C2|D2|E2|F2,         //0
  20.         B2|C2,                                //1
  21.         A2|B2|D2|E2|G2,                //2
  22.         A2|B2|C2|D2|G2,                //3
  23.         B2|C2|F2|G2,                //4
  24.         A2|C2|D2|F2|G2,                //5
  25.         A2|C2|D2|E2|F2|G2,        //6
  26.         A2|B2|C2,                        //7
  27.         A2|B2|C2|D2|E2|F2|G2,//8
  28.         A2|B2|C2|D2|F2|G2,        //9
  29.         0,                  //黑 消隐
  30. };
  31. //第三个7段码从0~9对应的编码
  32. code u32 digit3[11] =
  33. {
  34.         A3|B3|C3|D3|E3|F3,         //0
  35.         B3|C3,                                //1
  36.         A3|B3|D3|E3|G3,                //2
  37.         A3|B3|C3|D3|G3,                //3
  38.         B3|C3|F3|G3,                //4
  39.         A3|C3|D3|F3|G3,                //5
  40.         A3|C3|D3|E3|F3|G3,        //6
  41.         A3|B3|C3,                        //7
  42.         A3|B3|C3|D3|E3|F3|G3, //8
  43.         A3|B3|C3|D3|F3|G3,        //9
  44.         0,                  //黑 消隐
  45. };
复制代码

点灯IO控制代码,所有IO全部设置为开漏输出,利用使能内部4K上拉输出高电平,关闭上拉为高阻,输出0为低电平,三种IO状态
  1. //6个IO全部设为输入,关闭上拉
  2. void ALL_IN (void)
  3. {        
  4.     P3M0 = 0x00; P3M1 = 0x0f; P3PU = 0x00;
  5.     P5M0 = 0x00; P5M1 = 0x30; P5PU = 0x00;
  6. }
  7. void PIN1_OUT_L(void)
  8. {
  9.     P3M0 |= 0x01;
  10.         P3M1 &= ~0x01;
  11.         PIN1 = 0;
  12. }
  13. void PIN2_OUT_L(void)
  14. {
  15.     P3M0 |= 0x02;
  16.         P3M1 &= ~0x02;
  17.         PIN2 = 0;
  18. }
  19. void PIN3_OUT_L(void)
  20. {
  21.     P3M0 |= 0x04;
  22.         P3M1 &= ~0x04;
  23.         PIN3 = 0;
  24. }
  25. void PIN4_OUT_L(void)
  26. {
  27.     P3M0 |= 0x08;
  28.         P3M1 &= ~0x08;
  29.         PIN4 = 0;
  30. }
  31. void PIN5_OUT_L(void)
  32. {
  33.     P5M0 |= 0x20;
  34.         P5M1 &= ~0x20;
  35.         PIN5 = 0;
  36. }
  37. void PIN6_OUT_L(void)
  38. {
  39.     P5M0 |= 0x10;
  40.         P5M1 &= ~0x10;
  41.         PIN6 = 0;
  42. }
  43. void PIN1_OUT_H(void)
  44. {
  45.     P3PU |= 0x01;
  46. }
  47. void PIN2_OUT_H(void)
  48. {
  49.     P3PU |= 0x02;
  50. }
  51. void PIN3_OUT_H(void)
  52. {
  53.     P3PU |= 0x04;
  54. }
  55. void PIN4_OUT_H(void)
  56. {
  57.     P3PU |= 0x08;
  58. }
  59. void PIN5_OUT_H(void)
  60. {
  61.     P5PU |= 0x20;
  62. }
  63. void PIN6_OUT_H(void)
  64. {
  65.     P5PU |= 0x10;
  66. }
复制代码
显示函数,参数num为3为10进制整型,比如赋值123,就显示123,dp1,dp2,k1,k2是两位小数点和两个温度符号
  1. void display(u16 num,bit dp_1,bit dp_2,bit KK1,bit KK2)
  2. {
  3.         u8 num1,num2,num3;
  4.         num1 = num / 100;               //拆分出百位
  5.         num2 = (num % 100) / 10;          //拆分出十位
  6.         num3 = num % 10;                //拆分出个位               
  7.         display_num = digit1[num1] | digit2[num2] | digit3[num3];   
  8.         if(dp_1)  display_num |= DP1;   //暂未写消隐功能  可根据小数点位置和小数点前数字为零处理消隐
  9.         if(dp_2)  display_num |= DP1;
  10.         if(KK1)  display_num |= K1;
  11.         if(KK2)  display_num |= K2;
  12. }
复制代码
下面是刷数码管的过程,使用定时器0的 1ms中断自动刷屏,不设置任何等待过程,对单片机的指令开销占用极小,而且刷屏流畅不闪烁。
  1. //刷数码管定时器 1000Hz  三个数码管平均333Hz
  2. void Timer0_Isr(void) interrupt 1
  3. {
  4.         static u8 sta;
  5.         ALL_IN();     //关闭数码管        
  6.         switch (sta)
  7.         {
  8.                 case 1:
  9.                         PIN1_OUT_L();
  10.                         if(display_num & A3) PIN6_OUT_H();   //1                A3        G3        K1        K2
  11.                         if(display_num & G3) PIN5_OUT_H();
  12.                         if(display_num & K1) PIN4_OUT_H();
  13.                         if(display_num & K2) PIN3_OUT_H();               
  14.                         sta++;
  15.                         break;
  16.                 case 2:
  17.                         PIN2_OUT_L();
  18.                         if(display_num & A1) PIN3_OUT_H();   //2                A1        B1        D1        E1        DP1
  19.                         if(display_num & B1) PIN4_OUT_H();
  20.                         if(display_num & D1) PIN6_OUT_H();
  21.                         if(display_num & E1) PIN5_OUT_H();
  22.                         if(display_num & DP1) PIN1_OUT_H();               
  23.                         sta++;
  24.                         break;
  25.                 case 3:               
  26.                         PIN3_OUT_L();
  27.                         if(display_num & B2) PIN5_OUT_H();   //3                B2        D2        B3        F1        DP2
  28.                         if(display_num & D2) PIN4_OUT_H();
  29.                         if(display_num & B3) PIN6_OUT_H();
  30.                         if(display_num & F1) PIN2_OUT_H();
  31.                         if(display_num & DP2) PIN1_OUT_H();                        
  32.                         sta++;
  33.                         break;
  34.                 case 4:        
  35.                         PIN4_OUT_L();
  36.                         if(display_num & C2) PIN5_OUT_H();   //4                C2        E3        G1        F2
  37.                         if(display_num & E3) PIN6_OUT_H();
  38.                         if(display_num & G1) PIN2_OUT_H();
  39.                         if(display_num & F2) PIN3_OUT_H();               
  40.                         sta++;
  41.                         break;
  42.                 case 5:
  43.                         PIN5_OUT_L();
  44.                         if(display_num & C1) PIN2_OUT_H();   //5                C1        A2        C3        G2
  45.                         if(display_num & A2) PIN4_OUT_H();
  46.                         if(display_num & C3) PIN6_OUT_H();
  47.                         if(display_num & G2) PIN3_OUT_H();
  48.                         sta++;
  49.                         break;
  50.                 case 6:               
  51.                         PIN6_OUT_L();
  52.                         if(display_num & E2) PIN3_OUT_H();   //6                E2        D3        F3
  53.                         if(display_num & D3) PIN4_OUT_H();
  54.                         if(display_num & F3) PIN5_OUT_H();               
  55.                         sta = 1;
  56.                         break;
  57.                 default:
  58.                         sta = 1;
  59.                         break;
  60.         }
  61. }
复制代码

睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:408
  • 最近打卡:2025-05-07 09:34:59

0

主题

170

回帖

1029

积分

金牌会员

积分
1029
发表于 2024-4-2 21:58:03 | 显示全部楼层
这种数码管复用的方式和传统的共阳、共阳不一样,代码扫描的时候复杂很多,但万变不离其宗。
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-08 01:06:54
已绑定手机

35

主题

2111

回帖

2259

积分

荣誉版主

积分
2259
发表于 2024-4-2 22:52:38 | 显示全部楼层
yja*** 发表于 2024-4-2 21:58
这种数码管复用的方式和传统的共阳、共阳不一样,代码扫描的时候复杂很多,但万变不离其宗。 ...

有多少个引脚,就相当于多少个COM,而且是共阴共阳混合复用的,驱动机理的确很简单,但是要组织成好用的接口还是需要很多繁冗的工作。看上面的代码就很多行,普通数码管的话,要简单的多。
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-07 09:24:46
已绑定手机

13

主题

1271

回帖

3023

积分

论坛元老

积分
3023
发表于 2024-4-2 23:32:07 | 显示全部楼层
通过代码节省了硬件
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:401
  • 最近打卡:2025-05-08 05:28:23

16

主题

702

回帖

998

积分

高级会员

积分
998
发表于 2024-4-3 07:45:45 | 显示全部楼层
这种方式比较节省IO口,但是代码量就稍微大一点了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-08 01:06:54
已绑定手机

35

主题

2111

回帖

2259

积分

荣誉版主

积分
2259
发表于 2024-4-3 10:08:15 | 显示全部楼层
小*** 发表于 2024-4-3 07:45
这种方式比较节省IO口,但是代码量就稍微大一点了

普通3位的数码管刷三次,这种需要刷6次,总刷新率不变的情况下,刷新中断频率需要翻倍。

点评

普通3位的数码管刷三次,这种需要刷6次---这种是有多少段码就需要刷新多少次,且刷新过程要改变IO的工作模式。其实效率蛮低的,仅适用于简单项目  发表于 2024-4-17 16:04
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:508
  • 最近打卡:2025-05-07 07:34:14
已绑定手机

1

主题

836

回帖

1521

积分

金牌会员

积分
1521
发表于 2024-4-3 15:29:14 | 显示全部楼层
学习
靡不有初,鲜克有终
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:528
  • 最近打卡:2025-05-08 00:28:04

10

主题

1163

回帖

5203

积分

论坛元老

积分
5203
发表于 2024-4-3 15:37:49 | 显示全部楼层
查理复用(Charlieplex)是一种在驱动大量LED时有效地节约IO口的方法,理论上可点亮 脚数*(脚数-1)个LED
驱动这种数码管的技术称作查理复用技术(Charlieplexing)
charlieplexing利用单片机端口的三态。
一般规则是,只有两个端口可以同时输出,而其他所有端口都可以通过将它们定义为输入来处于高阻抗状态。

就是用这个查理复用技术(Charlieplexing)。

5个IO口最多可以控制20个LED
6个IO口最多可以控制30个LED
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-8 06:29 , Processed in 0.496720 second(s), 124 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表