标题:
用单片机控制MP3/SD/FM的LED显示屏的方法
[打印本页]
作者:
hushe
时间:
2015-12-22 19:22
标题:
用单片机控制MP3/SD/FM的LED显示屏的方法
经过诸多尝试,终于把这个LED数码管的显示方式搞清楚了。该数码管的面板和管脚结构表示如下:
该数码管共12个管脚,Pin1-7为数码管的A-G段,Pin8-11对应于中间四个数字字符,从左到右分别编为D1-D4,Pin12对应于边上的其它符号。
从左上角排列,分别与Pin1-Pin7对应的Play, Pause, USB, SD, TDP(时间显示的两个点),FM(包括后面:8.8中间的点,以及最后的MP3)。
从字符选择D1-D5端提高高电平,而SEGA-SEGG则为低电平,从而点亮对应的字符。对应关系如上图所示。
对应于0-9,A-F的字模编码如下:
#define LED_ON 1
#define LED_OFF 0
unsigned char cp;
unsigned char dispPtr;
static unsigned char
code
CharCode[] = {
//共阳极 共阴极 0 G F E D C B A 字符值
0x40
,
//0x3F, // 0 0 1 1 1 1 1 1 0x3F:0
0x79
,
//0x06, // 0 0 0 0 0 1 1 0 0x06:1
0x24
,
//0x5B, // 0 1 0 1 1 0 1 1 0x5B:2
0x30
,
//0x4F, // 0 1 0 0 1 1 1 1 0x4F:3
0x19
,
//0x66, // 0 1 1 0 0 1 1 0 0x66:4
0x12
,
//0x6D, // 0 1 1 0 1 1 0 1 0x6D:5
0x02
,
//0x7D, // 0 1 1 1 1 1 0 1 0x7D:6
0x78
,
//0x07, // 0 0 0 0 0 1 1 1 0x07:7
0x00
,
//0x7F, // 0 1 1 1 1 1 1 1 0x7F:8
0x10
,
//0x6F, // 0 1 1 0 1 1 1 1 0x6F:9
0x08
,
//0x77, // 0 1 1 1 0 1 1 1 0x77:A
0x03
,
//0x7C, // 0 1 1 1 1 1 0 0 0x7C:b
0x27
,
//0x58, // 0 1 0 1 1 0 0 0 0x58:c
0x21
,
//0x5E, // 0 1 0 1 1 1 1 0 0x5E:d
0x06
,
//0x79, // 0 1 1 1 1 0 0 1 0x79:E
0x0E
,
//0x71, // 0 1 1 1 0 0 0 1 0x71:F
//0x01, //bPlay;
//0x02, //bPause;
//0x04, //bUSB;
//0x08, //bSD;
//0x10, //bTDP;
//0x20, //bFM;
//0x40, //bMP3;
//0x00 //bBlank;
};
利用定时器中断 Timer0来进行显示。其中Disp程序是将对应的字形码输出到数码管所接的端口的。
这里定义了一个结构,用来表示LED要显示的内容(其实不是必要的)。
struct
DispBuf {
int
bPLAY:
1;
int
bPAUSE:
1
;
int
bUSB:
1
;
int
bSD:
1
;
int
bTDP:
1
;
int
bFM:
1
;
int
bMP3:
1
;
unsigned char
DBuf[
4
];
};
struct
DispBuf theBuf;
void
Disp(
unsigned char
c);
void
Timer0_isr(
void
) interrupt
1
{
cp++;
//以下进行各数码管分时扫描。
if (cp ==
3
) {
//5ms * 4 = 20ms LED_REFRESH_FREQ 拖过调整显示延迟常数,
//可以改变显示时 LED的闪烁状态,越小速度越快,闪烁越低,但是耗电可能会增加。
cp =
0
;
dispPtr++;
if (dispPtr ==
1
) {
D5=LED_OFF;
Disp(CharCode[theBuf.DBuf[
0
]]);
D1=LED_ON;
}
if (dispPtr ==
2
) {
D1=LED_OFF;
Disp(CharCode[theBuf.DBuf[
1
]]);
D2=LED_ON;
}
if (dispPtr ==
3
) {
D2=LED_OFF;
Disp(CharCode[theBuf.DBuf[
2
]]);
D3=LED_ON;
}
if (dispPtr ==
4
) {
D3=LED_OFF;
Disp(CharCode[theBuf.DBuf[
3
]]);
D4=LED_ON;
}
if (dispPtr ==
5
) {
D4=LED_OFF;
Disp(
0xFF
);
//对于各种符号的显示做特殊处理。
D5=LED_ON;
dispPtr=
0
;
}
}
}
void
Disp(
unsigned char
c)
{
unsigned char
t;
t= c;
if
(c == 0xFF) {
//附加的各种符号的判定和显示,需要合并。
if
(theBuf.bPLAY ==
0
) t |=
0x01
;
else
t &=
0xFE
;
if
(theBuf.bPAUSE ==
0
) t |=
0x02
;
else
t &=
0xFD
;
if
(theBuf.bUSB ==
0
) t |=
0x04
;
else
t &=
0xFB
;
if
(theBuf.bSD ==
0
) t |=
0x08
;
else
t &=
0xF7
;
if
(theBuf.bTDP ==
0
) t |=
0x10
;
else
t &=
0xEF
;
if
(theBuf.bFM ==
0
) t |=
0x20
;
else
t &=
0xDF
;
if
(theBuf.bMP3 ==
0
) t |=
0x40
;
else
t &=
0xBF
;
}
P2 &=
0xE0
;
//清除低5位:SEGA-SEGE连接至P2^0 - P2^4
P2 |= (t &
0x1F
);
P4 &=
0x9F
;
//清除 P4.5, P4.6; SEGF,SEGG连接至 P4^5和P4^6.
P4 |= (t &
0x60
);
}
实用的显示整数的子程序。最大显示的四位数0-0xFFFF。
void
DispHInt(
unsigned int
nNum)
{
unsigned int
t;
//将整数拆分为16进制数,分别送到对应的字符缓冲区中。
t=nNum/
0x1000
;
theBuf.DBuf[
0
]=t;
t=(nNum%
0x1000
)/
0x100
;
theBuf.DBuf[
1
]=t;
t=(nNum%
0x100
)/
0x10
;
theBuf.DBuf[
2
]=t;
t=nNum%
0x10
;
theBuf.DBuf[
3
]=t;
}
//演示例程。需要添加到main函数中使用。
void
ScanLED()
{
unsigned int
i;
theBuf.bFM=
1
;
//显示FM标志
theBuf.bPLAY =
0
;
theBuf.bPAUSE =
0
;
theBuf.bSD =
0
;
theBuf.bUSB =
0
;
theBuf.bTDP =
0
;
theBuf.bMP3 =
0
;
for (i=
0
;i<
0xFFFF
;i++)
{
DispHInt(i);
delay(
10
);
//延时程序,未列出。
}
}
以上程序在 STC15W4K32S4 LQ44的样机上调试通过。运行效果如下:
作者:
aazhjaa
时间:
2021-8-9 20:21
很好的例子,收藏学习。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1