|
|
簡簡單單點(diǎn)個6條腿的8段LED數(shù)碼管
開發(fā)板上常見的7段數(shù)碼管都是共陰或者共陽結(jié)構(gòu)的,
分為SEG和COM段,驅(qū)動代碼也比較好寫,行列刷新嘛,
但是很多廉價的電子產(chǎn)品比如充電寶、電池倉上面用的,
數(shù)碼管就比較簡單了,只有很少的引腳,
看燈珠的結(jié)構(gòu)也是比較無序的,相對來說比較難搞,
由于項目需要嘛,不得不搞一下,于是某一個寶買了幾個樣品,
試著驅(qū)動一下。
數(shù)碼管的燈珠結(jié)構(gòu)如下,看起來比較亂,實(shí)際上也是真的亂。
試了一下點(diǎn)亮所有段碼,亮度還行,可以進(jìn)行下一步驅(qū)動了。
PS:點(diǎn)亮所有段碼的方式很簡單,
每次使1個引腳拉低,其余拉高即可,然后循環(huán)掃描。
普通3位的數(shù)碼管刷三次,這種需要刷6次,總刷新率不變的情況下,刷新中斷頻率需要翻倍。
1.png (262.8 KB, 下載次數(shù): 0)
下載附件
2026-3-12 23:21 上傳
查理復(fù)用(Charlieplex)是一種在驅(qū)動大量LED時有效地節(jié)約IO口的方法,理論上可點(diǎn)亮 腳數(shù)*(腳數(shù)-1)個LED
驅(qū)動這種數(shù)碼管的技術(shù)稱作查理復(fù)用技術(shù)(Charlieplexing)
charlieplexing利用單片機(jī)端口的三態(tài)。
一般規(guī)則是,只有兩個端口可以同時輸出,而其他所有端口都可以通過將它們定義為輸入來處于高阻抗?fàn)顟B(tài)。
就是用這個查理復(fù)用技術(shù)(Charlieplexing)。
5個IO口最多可以控制20個LED
6個IO口最多可以控制30個LED
下面介紹一下實(shí)現(xiàn)方法,
單片機(jī)為STC8G1K17,其它STC單片機(jī)也一樣用的
定義管腳
sbit PIN1 = P3^0; //數(shù)碼管
sbit PIN2 = P3^1; //數(shù)碼管
sbit PIN3 = P3^2; //數(shù)碼管
sbit PIN4 = P3^3; //數(shù)碼管
sbit PIN5 = P5^5; //數(shù)碼管
sbit PIN6 = P5^4; //數(shù)碼管
3個7段數(shù)碼管,2個小數(shù)點(diǎn),2個溫度符號,一共是25個段,定義32位段位碼,每個段占一位
//各個LED燈珠代表的位
#define A1 0x00000001
#define B1 0x00000002
#define C1 0x00000004
#define D1 0x00000008
#define E1 0x00000010
#define F1 0x00000020
#define G1 0x00000040
#define A2 0x00000080
#define B2 0x00000100
#define C2 0x00000200
#define D2 0x00000400
#define E2 0x00000800
#define F2 0x00001000
#define G2 0x00002000
#define A3 0x00004000
#define B3 0x00008000
#define C3 0x00010000
#define D3 0x00020000
#define E3 0x00040000
#define F3 0x00080000
#define G3 0x00100000
#define DP1 0x00200000
#define DP2 0x00400000
#define K1 0x00800000
#define K2 0x01000000
定義三位數(shù)碼管的顯示表 其實(shí)就是顯示字符需要點(diǎn)對應(yīng)段位碼,比如顯示1,就點(diǎn)亮B1 C1,一行一個狀態(tài)。
//第一個7段碼從0~9對應(yīng)的編碼
code u32 digit1[11] =
{
A1|B1|C1|D1|E1|F1, //0
B1|C1, //1
A1|B1|D1|E1|G1, //2
A1|B1|C1|D1|G1, //3
B1|C1|F1|G1, //4
A1|C1|D1|F1|G1, //5
A1|C1|D1|E1|F1|G1, //6
A1|B1|C1, //7
A1|B1|C1|D1|E1|F1|G1, //8
A1|B1|C1|D1|F1|G1, //9
0, //黑 消隱
};
//第二個7段碼從0~9對應(yīng)的編碼
code u32 digit2[11] =
{
A2|B2|C2|D2|E2|F2, //0
B2|C2, //1
A2|B2|D2|E2|G2, //2
A2|B2|C2|D2|G2, //3
B2|C2|F2|G2, //4
A2|C2|D2|F2|G2, //5
A2|C2|D2|E2|F2|G2, //6
A2|B2|C2, //7
A2|B2|C2|D2|E2|F2|G2, //8
A2|B2|C2|D2|F2|G2, //9
0, //黑 消隱
};
//第三個7段碼從0~9對應(yīng)的編碼
code u32 digit3[11] =
{
A3|B3|C3|D3|E3|F3, //0
B3|C3, //1
A3|B3|D3|E3|G3, //2
A3|B3|C3|D3|G3, //3
B3|C3|F3|G3, //4
A3|C3|D3|F3|G3, //5
A3|C3|D3|E3|F3|G3, //6
A3|B3|C3, //7
A3|B3|C3|D3|E3|F3|G3, //8
A3|B3|C3|D3|F3|G3, //9
0, //黑 消隱
};
點(diǎn)燈IO控制代碼,所有IO全部設(shè)置為開漏輸出,利用使能內(nèi)部4K上拉輸出高電平,關(guān)閉上拉為高阻,輸出0為低電平,三種IO狀態(tài)
//6個IO全部設(shè)為輸入,關(guān)閉上拉
void ALL_IN (void)
{
P3M0 = 0x00; P3M1 = 0x0f; P3PU = 0x00;
P5M0 = 0x00; P5M1 = 0x30; P5PU = 0x00;
}
void PIN1_OUT_L(void)
{
P3M0 |= 0x01;
P3M1 &= ~0x01;
PIN1 = 0;
}
void PIN2_OUT_L(void)
{
P3M0 |= 0x02;
P3M1 &= ~0x02;
PIN2 = 0;
}
void PIN3_OUT_L(void)
{
P3M0 |= 0x04;
P3M1 &= ~0x04;
PIN3 = 0;
}
void PIN4_OUT_L(void)
{
P3M0 |= 0x08;
P3M1 &= ~0x08;
PIN4 = 0;
}
void PIN5_OUT_L(void)
{
P5M0 |= 0x20;
P5M1 &= ~0x20;
PIN5 = 0;
}
void PIN6_OUT_L(void)
{
P5M0 |= 0x10;
P5M1 &= ~0x10;
PIN6 = 0;
}
void PIN1_OUT_H(void)
{
P3PU |= 0x01;
}
void PIN2_OUT_H(void)
{
P3PU |= 0x02;
}
void PIN3_OUT_H(void)
{
P3PU |= 0x04;
}
void PIN4_OUT_H(void)
{
P3PU |= 0x08;
}
void PIN5_OUT_H(void)
{
P5PU |= 0x20;
}
void PIN6_OUT_H(void)
{
P5PU |= 0x10;
}
顯示函數(shù),參數(shù)num為3為10進(jìn)制整型,比如賦值123,就顯示123,dp1,dp2,k1,k2是兩位小數(shù)點(diǎn)和兩個溫度符號
void display(u16 num,bit dp_1,bit dp_2,bit KK1,bit KK2)
{
u8 num1,num2,num3;
num1 = num / 100; //拆分出百位
num2 = (num % 100) / 10; //拆分出十位
num3 = num % 10; //拆分出個位
display_num = digit1[num1] | digit2[num2] | digit3[num3];
if(dp_1) display_num |= DP1; //暫未寫消隱功能 可根據(jù)小數(shù)點(diǎn)位置和小數(shù)點(diǎn)前數(shù)字為零處理消隱
if(dp_2) display_num |= DP1;
if(KK1) display_num |= K1;
if(KK2) display_num |= K2;
}
下面是刷數(shù)碼管的過程,使用定時器0的 1ms中斷自動刷屏,不設(shè)置任何等待過程,對單片機(jī)的指令開銷占用極小,而且刷屏流暢不閃爍。
//刷數(shù)碼管定時器 1000Hz 三個數(shù)碼管平均333Hz
void Timer0_Isr(void) interrupt 1
{
static u8 sta;
ALL_IN(); //關(guān)閉數(shù)碼管
switch (sta)
{
case 1:
PIN1_OUT_L();
if(display_num & A3) PIN6_OUT_H(); //1 A3 G3 K1 K2
if(display_num & G3) PIN5_OUT_H();
if(display_num & K1) PIN4_OUT_H();
if(display_num & K2) PIN3_OUT_H();
sta++;
break;
case 2:
PIN2_OUT_L();
if(display_num & A1) PIN3_OUT_H(); //2 A1 B1 D1 E1 DP1
if(display_num & B1) PIN4_OUT_H();
if(display_num & D1) PIN6_OUT_H();
if(display_num & E1) PIN5_OUT_H();
if(display_num & DP1) PIN1_OUT_H();
sta++;
break;
case 3:
PIN3_OUT_L();
if(display_num & B2) PIN5_OUT_H(); //3 B2 D2 B3 F1 DP2
if(display_num & D2) PIN4_OUT_H();
if(display_num & B3) PIN6_OUT_H();
if(display_num & F1) PIN2_OUT_H();
if(display_num & DP2) PIN1_OUT_H();
sta++;
break;
case 4:
PIN4_OUT_L();
if(display_num & C2) PIN5_OUT_H(); //4 C2 E3 G1 F2
if(display_num & E3) PIN6_OUT_H();
if(display_num & G1) PIN2_OUT_H();
if(display_num & F2) PIN3_OUT_H();
sta++;
break;
case 5:
PIN5_OUT_L();
if(display_num & C1) PIN2_OUT_H(); //5 C1 A2 C3 G2
if(display_num & A2) PIN4_OUT_H();
if(display_num & C3) PIN6_OUT_H();
if(display_num & G2) PIN3_OUT_H();
sta++;
break;
case 6:
PIN6_OUT_L();
if(display_num & E2) PIN3_OUT_H(); //6 E2 D3 F3
if(display_num & D3) PIN4_OUT_H();
if(display_num & F3) PIN5_OUT_H();
sta = 1;
break;
default:
sta = 1;
break;
}
}
|
|