七段数码管显示实验.docx
《七段数码管显示实验.docx》由会员分享,可在线阅读,更多相关《七段数码管显示实验.docx(15页珍藏版)》请在冰豆网上搜索。
七段数码管显示实验
单
片
机
实
验
报
告
实验九七段数码管显示实验
一、实验目的
1.学习七段数码管的工作原理;
2.学习数码管与8051单片机的接口方法;
3.掌握动态扫描显示技术。
二、实验原理
如图4.9-1所示,LED数码管由7个发光二极管组成,此外,还有一个圆点型发光二极管(在图中以dp表示),用于显示小数点。
通过七段发光二极管亮暗的不同组合,可以显示多种数字、字母以及其它符号。
LED数码管中的发光二极管共有两种连接方法:
1)共阴极接法:
把发光二极管的阴极连在一起构成公共阴极。
使用时公共阴极接地,这样阳极端输入高电平的段发光二极管就导通点亮,而输入低电平的则不点亮。
实验中使用的LED显示器为共阴极接法
2)共阳极接法:
把发光二极管的阳极连在一起构成公共阳极。
使用时公共阳极接+5V。
这样阴极端输入低电平的段发光二极管就导通点亮,而输入高电平的则不点亮。
为了显示数字或符号,要为LED显示器提供代码,因为这些代码是为显示字形的,因此称之为字形代码。
七段发光二极管,再加上一个小数点位,共计八段。
因此提供给LED显示器的字形代码正好一个字节。
若a、b、c、d、e、f、g、dp8个显示段依次对应一个字节的低位到高位,即D0、D1、D2、D3、D4、D5、D6、D7,则用共阴极LED数码管显示十六进制数时所需的字形代码如表4.9-1所示。
表4.9-1共阴极LED数码管字形代码
字型
共阴极字形代码
字型
共阴极字形代码
字型
共阴极字形代码
0
3FH
6
7DH
C
39H
1
06H
7
07H
d
5EH
2
5BH
8
7FH
E
79H
3
4FH
9
6FH
F
71H
4
66H
A
77H
灭
00H
5
6DH
b
7CH
*实际上试验中使用的是共阳极数码管,这里就不一一列出。
2、动态显示
按图4.9-2(b)连接线路,通过交替选中LED1和LED0循环显示两位十进制数。
七段数码管段码连接不变,位码驱动输入端S1、S0接8255AC口的PC1、PC0,通过C口的这两位交替输出1和0,以便交替选中LED1和LED0,从而实现两位十进制数的交替显示。
请编程实现在两个LED数码管上循环显示0099,程序流程图如图4.9-3(b)所示。
三、实验电路图
第一部分电路图:
第二部分电路图:
四、实验设备
微型计算机、单片机仿真器、实验仪、示波器(各一台);
实验连线(若干)。
五、实验内容
*由于汇编语言程序中已经做了相应的注释,C语言的编程原理与之相同处不再做重复注释,仅作个别注释,请见谅。
1.编程在8位数码管上面显示“12345678”8个数字,每经过1秒8个数字循环左移一位显示。
依次为:
1234578、23456781、34567812.......
汇编语言程序代码:
ORG0000H
START:
MOVR4,#00H
FLASH:
MOVR2,#01H
MOVR0,#30H
MOVDPTR,#TABFLA;把字形表首地址给外部寻址寄存器
LOPFLA:
MOVA,R2;输出位型
MOVP2,A
MOVA,@R0
MOVCA,@A+DPTR;在程序段中查表得到字形
MOVP1,A;输出字形
MOVR3,#0
DJNZR3,$;循环等待延时
MOVP1,#0FFH;关显示
MOVA,R2;位型左移一位
RLA
MOVR2,A
INCR0;下一个字形
CJNER0,#38H,GOON
MOVR0,#30H
GOON:
CJNEA,#01H,LOPFLA;若已经显示一遍则初始化
INCR4
CJNER4,#7FH,GOON1
MOVA,30H;显示表左移更新
MOV30H,31H
MOV31H,32H
MOV32H,33H
MOV33H,34H
MOV34H,35H
MOV35H,36H
MOV36H,37H
MOV37H,A
MOVR4,#00H
GOON1:
AJMPFLASH
TABFLA:
;字形表
DB0C0H,0F9H,0A4H,0B0H,99H
DB92H,82H,0F8H,80H,90H,88H
DB83H,0C6H,0A1H,86H,8EH
END
C语言程序代码:
#include
dataunsignedchardisadd_at_0x30;
constunsignedcharLED_TAB[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0x88,0x83,
0xC6,0xA1,0x86,0x8E};
dataunsignedcharj;
voiddelay()
{
unsignedchari=0xFF;
while(i--)
{
;
}
}
voidchange_s()
{
unsignedchar*k;
unsignedcharm;
k=&disadd;
m=*k;//显示表移位
*k=*(k+1);
*(k+1)=*(k+2);
*(k+2)=*(k+3);
*(k+3)=*(k+4);
*(k+4)=*(k+5);
*(k+5)=*(k+6);
*(k+6)=*(k+7);
*(k+7)=m;
j=0x00;//计数值初始化
}
main()
{
unsignedchari;
unsignedchardisbit;
unsignedchar*disnum,*n;
SP=0x40;
j=0x00;
n=&disadd;
*(n)=0x01;//显示设置初值为1~8
*(n+1)=0x02;
*(n+2)=0x03;
*(n+3)=0x04;
*(n+4)=0x05;
*(n+5)=0x06;
*(n+6)=0x07;
*(n+7)=0x08;
while
(1)
{
disbit=0x01;
disnum=&disadd;
for(i=0;i<8;i++)
{
P2=0x00;
P1=LED_TAB[*disnum];
P2=disbit;
delay();
disbit=disbit<<1;
disnum++;
}
j++;
if(j==0x3f)
{
change_s();//调用显示表移位子程序
}
}
}
2.用8255的PA口作为段码输出口,编写程序,利用定时器T0作为时间基准控制电子钟走时,电子钟的格式为:
XX—XX—XX
分钟—秒钟—百分秒
汇编语言程序代码:
COM_ADDXDATA0F003H
PA_ADDXDATA0F000H
PB_ADDXDATA0F001H
PC_ADDXDATA0F002H
ORG0000H
AJMPSTART
ORG000BH
AJMPT0INT
ORG0030H
START:
MOVSP,#60H;设置堆栈
MOVTMOD,#01H;设置定时器T0的控制字
MOVTH0,#0F0H;设置定时器计数初值
MOVTL0,#07FH
MOVR7,#00H;显示寄存器置初值
MOVR6,#00H
MOVR5,#00H
MOVR4,#00H
MOVR3,#00H
MOVR2,#00H
MOV32H,#16;设置显示分隔符
MOV35H,#16
SETBET0;允许中断(T0内部中断)
SETBEA
SETBTR0;开始计数
CONTINUE:
MOV37H,R7;进位判断,R7表示百分之一秒(之后的以此类推)
MOV36H,R6
CJNER6,#0AH,NOREACH
MOVR6,#00H
MOV36H,R6
INCR5
MOV34H,R5
CJNER5,#0AH,NOREACH
MOVR5,#00H
MOV34H,R5
INCR4
MOV33H,R4
CJNER4,#06H,NOREACH
MOVR4,#00H
MOV33H,R4
INCR3
MOV31H,R3
CJNER3,#0AH,NOREACH
MOVR3,#00H
MOV31H,R3
INCR2
MOV30H,R2
CJNER2,#06H,NOREACH
MOVR2,#00H
MOV30H,R2
NOREACH:
ACALLDISPLAY;调用显示子程序
AJMPCONTINUE
;中断子程序
T0INT:
INCR7;R7表示百分之一秒(之后的以此类推)
CJNER7,#0AH,NOREACH_S
MOVR7,#00H
INCR6
NOREACH_S:
MOVTH0,#0F0H;计数完一次后再次置计数初值
MOVTL0,#07FH
RETI
;数码管显示子程序
DISPLAY:
MOVR1,#01H;位型输出指针
MOVR0,#30H
MOVDPTR,#COM_ADD
MOVA,#80H
MOVX@DPTR,A
LOPFLA:
MOVDPTR,#PB_ADD
MOVA,R1
MOVX@DPTR,A
MOVDPTR,#TABFLA
MOVA,@R0
MOVCA,@A+DPTR;在程序段中查表得到字形
MOVDPTR,#PA_ADD
MOVX@DPTR,A
MOVA,#00H
WAIT:
DECA
CJNEA,#00H,WAIT;等待延时
MOVDPTR,#PA_ADD
MOVA,#0FFH
MOVX@DPTR,A;关显示
MOVA,R1;位型左移一位
RLA
MOVR1,A
INCR0;下一个字形
CJNEA,#01H,LOPFLA;若已经显示一遍则初始化
RET
TABFLA:
DB0C0H,0F9H,0A4H,0B0H,99H
DB92H,82H,0F8H,80H,90H,88H
DB83H,0C6H,0A1H,86H,8EH
DB0BFH
END
C语言程序代码:
#include
#defineTIMEINT0x01
#defineTIMEH0xf0
#defineTIMEL0x7f
xdataunsignedcharcon_address_at_0xf003;
xdataunsignedcharpa_at_0xf000;
xdataunsignedcharpb_at_0xf001;
xdataunsignedcharpc_at_0xf002;
dataunsignedchardisadd_at_0x30;
constunsignedcharLED_TAB[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0x88,0x83,
0xC6,0xA1,0x86,0x8E,0xBF};
dataunsignedcharr2,r3,r4,r5,r6,r7;//显示变量设置为全局变量
voiddelay()
{
unsignedchari=0xFF;
while(i--)
{
;
}
}
voidtimer0(void)interrupt1using1//中断子程序
{
r7++;
if(r7==0x0A)
{
r7=0x00;
r6++;
}
TH0=TIMEH;
TL0=TIMEL;
}
voiddisplay()//显示子程序
{
unsignedchari;
unsignedchardisbit;
unsignedchar*disnum;
disbit=0x01;
disnum=&disadd;
for(i=0;i<8;i++)
{
pb=0x00;
pa=LED_TAB[*disnum];
pb=disbit;
delay();
disbit=disbit<<1;
disnum++;
}
}
main()
{
unsignedchar*n;
SP=0x40;
con_address=0x80;
TMOD=TIMEINT;
TH0=TIMEH;
TL0=TIMEL;
n=&disadd;
r7=0x00;
r6=0x00;
r5=0x00;
r4=0x00;
r3=0x00;
r2=0x00;
*(n+2)=16;
*(n+5)=16;
ET0=1;
EA=1;
TR0=1;
while
(1)
{
*(n+7)=r7;//显示进位判断
*(n+6)=r6;
if(r6==0x0A)
{
r6=0x00;
*(n+6)=r6;
r5++;
*(n+4)=r5;
if(r5==0x0A)
{
r5=0x00;
*(n+4)=r5;
r4++;
*(n+3)=r4;
if(r4==0x06)
{
r4=0x00;
*(n+3)=r4;
r3++;
*(n+1)=r3;
if(r3==0x0A)
{
r3=0x00;
*(n+1)=r3;
r2++;
*n=r2;
if(r6==0x06)
{
r2=0x00;
*n=r2;
}
}
}
}
}
display();
}
}
六、实验小结
通过本次试验,我基本上掌握了数码管显示的程序流程,学会编写一些程序调用相应的相应的子程序,显示所需内容,了解了动态扫描显示的程序执行过程,结合定时器的设置和中断的返回,来实现最基本的百分秒显示,从而完成时钟显示,由此,结合前面所学的知识,巩固了数码管显示的知识,增强了我的程序调试能力,为下一步的学习打下了坚实基础。
以上程序都记过实验或是仿真器验证,现象正常,若有错误之处,请老师指正,谢谢。