- 打卡等级:偶尔看看II
- 打卡总天数:25
- 最近打卡:2024-09-24 08:48:14
中级会员
- 积分
- 273
|
发表于 2024-9-3 10:30:43
|
显示全部楼层
本帖最后由 webfly 于 2024-9-20 11:38 编辑
第十集:数码管的动态显示
1、数码管动态刷新的原理
静态显示方式接口编程容易,但是占用口线较多。若用I/O口线接口,要占用四个八位I/O口。如果显示器的数目增多,则需要增加I/O口的数目。因此在显示位数较多的情况下,一般都采用动态显示方式。若要各个数码管能够同时显示出与本位相应的显示字符,就必须采用动态扫描显示方式。即在某一时刻,只让某一位的位选线处于选通状态,而其他位的位选线处于关闭状态,同时,段码线上输出相应位要有显示的字符的段码。这样,在同一时刻,四位LED中只有被选通的那一位显示出字符,而其他三位则是熄灭的。同样,在下一时刻,只让其下一位的位选线处于选通状态,而其他各位的位选线处于关闭状态,在段码线上输出将要显示字符的段码,此时,只有在选通位显示出相应的字符,其他各位则是熄灭的。如此循环下去,就可使各位显示出将要显示的字符。 虽然这些字符是在不同时刻出现的,而在同一时刻,只有一位显示,其他各位熄灭,但由于LED数码管的余辉和人眼的“视觉暂留”作用,只要每位显示间隔足够短,则可以造成“多位同时亮”的假象,达到同时显示的效果。
2、控制原理
3、8位数码管同时点亮
#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#define KEY1 P32 //定义一个按键 引脚选择P32
#define KEY2 P33 //定义一个按键 引脚选择P33
#define BEEP P54 //定义一个按键 引脚选择P54
#define SEG_Delay 1 //延时多少ms
#define MAIN_Fosc 24000000UL //定义主时钟
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
u8 SEG_Tab[20] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //0-9段码,0-9带小数点
u8 COM_Tab[8] = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe }; //0-7的位码数组
u8 Show_Tab[8] = {3,0,0,0,0,10,0,0};
u32 TimCount = 0; //计数单位1ms
bit RUN_State = 0; //开始运行/结束运行
u8 num = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void SEG_Fre( void )
{
//位码选择第一位,段码选择0
P7 = COM_Tab[num]; //位码的选择
P6 = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码 赋给 P6 NUM =0 -> Show_Tab[num]] = 1 -> p6 = oxF9
delay_ms(SEG_Delay);
num++;
if( num >7 )
num = 0;
}
void main() //程序开始运行的入口
{
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
EA = 1; //CPU开放中断,打开总中断。
while(1) //死循环
{
if( DeviceState != DEVSTATE_CONFIGURED ) //
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
//------------------------------------------------P32按下一次,灯往右边边移动一个单位 -----------------------------------------------
Show_Tab[0] = 1; //选择 1
Show_Tab[1] = 10; //选择 0.
Show_Tab[2] = 0; //选择 0
Show_Tab[3] = 0; //选择 0
if( RUN_State==1 )
{
TimCount++;
Show_Tab[4] = TimCount/10000%10;
Show_Tab[5] = TimCount/1000%10+10;
Show_Tab[6] = TimCount/100%10;
Show_Tab[7] = TimCount/10%10; //取10位
}
SEG_Fre();
if( KEY1 ==0 )
{
delay_ms(10);
if( KEY1 ==0 )
{
BEEP = 0;
delay_ms(10);
BEEP = 1;
while( KEY1 ==0 )
{
SEG_Fre();
}
if( RUN_State==0 )
TimCount = 0;
RUN_State = !RUN_State;
}
}
}
}
/*
11111110 0XFE
11111101 0XFD
11111011 0XFB
11110111 0XF7
11101111 0XEF
11011111 0XDF
10111111 0XBF
01111111 0X7F
*/
void sys_init() //函数定义
{
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01)); //等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
|
|