
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:
MOV P2,#0FEH
MOV A,#00H
MOV DPTR,#TAB
LOOP:
MOVC A,@A+DPTR
MOV P0,A
LCALL DELAY
INC A
CJNE A,#0AH,LOOP
MOV A,P2
RL A
MOV P2,A
JB ACC.6,SS1
MOV P2,#0FEH
SS1:
CLR A
SJMP LOOP
DELAY:
MOV R1,#2
L1: MOV R2,#200
L2: MOV R3,#200
L3: DJNZ R3,L1
DJNZ R2,L2
DJNZ R1,L3
RET SJMP $
ORG 0080H
TAB:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
END
#include <reg51.h>#include <intrins.h>
void delay(unsigned int i) //函数声名
char DelayCNT//定义变量
//此表为 LED 的字模, 共阴数码管 0-9 -
unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40} //段码控制
//此表为8个数码管位选控制, 共阴数码管 1-8个 -
unsigned char code dispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F} //位选控制 查表的方法控制
/************主函数**********************/
main()
{
unsigned int i,LedNumVal=1 //变量定义
unsigned int LedOut[10] //变量定义
DelayCNT=0
while(1)
{
if(++DelayCNT>=20) //控制数字变化速度
{
DelayCNT=0 //20个扫描周期清零一次
++LedNumVal //每隔20个扫描周期加一次
}
LedOut[0]=Disp_Tab[LedNumVal%10000/1000]
LedOut[1]=Disp_Tab[LedNumVal%1000/100]|0x80
LedOut[2]=Disp_Tab[LedNumVal%100/10]
LedOut[3]=Disp_Tab[LedNumVal%10]
LedOut[4]=Disp_Tab[LedNumVal%10000/1000] //千位
LedOut[5]=Disp_Tab[LedNumVal%1000/100]|0x80 //百位带小数点
LedOut[6]=Disp_Tab[LedNumVal%100/10] //十位
LedOut[7]=Disp_Tab[LedNumVal%10]//个位
for( i=0i<9i++)
{
P0 = LedOut[i]
P1 = dispbit[i] //使用查表法进行位选
/* switch(i) //使用switch 语句控制位选
{
case 0:P1 = 0x7F break
case 1:P1 = 0xbF break
case 2:P1 = 0xdF break
case 3:P1 = 0xeF break
case 4:P1 = 0xf7 break
case 5:P1 = 0xfb break
case 6:P1 = 0xfd break
case 7:P1 = 0xfe break
} */
delay(150) //扫描间隔时间 太长会数码管会有闪烁感
}
}
}
void delay(unsigned int i)
{
char j
for(ii >0i--)
for(j = 200j >0j--)
}
这个程序的基本流程是:1.把content中的数字对应的断码找出,并依次存放到LEDBuf中
2.依次送LEDBuf中的断码到LED上,LED显示对应字符
OUTBIT equ 08002h 将位码送至此地址,位码表示显示哪一位LED管
OUTSEG equ 08004h 将断码送至此地址,断码表示在指定的LED管上显示什么字符
data segment
Content db 1,2,3,0dh,0eh,0fh 要显示的数字
LEDBuf db 6 dup(?) 要显示的数字对应的断码
LEDMAP给出的是断码表,表示16进制数到断码的映射。总共16个,分别表示0-f。
比如第一个3fh就是0的断码,断码送到LED中,LED会自动显示0。
LEDMAP:
db 3fh,06h,5bh,4fh,66h,6dh,7dh,,07h
db 7fh,6fh,77h,7ch,39h,5eh, 79h,71h
data ends
code segment
assume cs:code, ds:data
Delay的目的就是为了让LED灯上的内容停留,以便看清
Delay proc
push cx
mov cx,100h
loop $ 这里的循环目的是暂停一段时间,让LED上的数字停留,以便人看清
pop cx
ret
Delay endp
DisplayLED做的事:把LEDbuf中内容全部显示到LED灯上。LEDbuf中6个断码,对应6个LED灯。
DisplayLED proc near
mov bx, offset LEDBuf
mov cx, 6 总共显示6个断码
mov ah, 00100000b 位码,00100000b中1的位置指示了要显示的数位,当前是1在左起第六个,也就是显示6号LED灯
后面有shr指令会将这个00100000b右移,这样变成00010000,显示5号LED,以此类推。
DLoop: mov dx, OUTBIT
mov al, 0
out dx,al 将0送端位码端口,表示当前不选中任何LED,即关闭LED
mov al, [bx] 将LEDbuf中的一个断码,送入al
mov dx, OUTSEG
out dx,al 送断码,表示要在LED中显示这个字符
mov dx, OUTBIT
mov al, ah
out dx, al 送位码,表示要显示哪一个LED灯
call Delay 上面送完断码,位码后,在相应的LED上就显示相应的字符,Delay可以让这个字符停留一段时间,视觉滞留。
shr ah, 1 位码右移,显示下一个LED
inc bx bx加1,那么[bx]就指向LEDbuf中的下一个断码
loop Dloop 这个Dloop循环把LEDbuf中的六个断码依次全部送到对应LED上显示
ret
DisplayLED endp
Start:程序的入口,从这里开始运行程序
Start proc near
mov ax, data
mov ds, ax
mov cx,6 显示六个字符
mov ah,0 ah是content中的偏移量,从0->5,分别找出content中各个字节内容
mov si,offset ledbuf
redo: mov bx,offset content
mov al,ah 后面的xlat指令要使用al
xlat xlat的作用al<-[bx+al],也就是将bx这个地址(content)起的第al个字节内容送到al中
mov bx,offset ledmap
xlat 将此时al中的数字对应的断码找出,并放到al中。(数字a对应的断码就是ledmap起第a个字节的数据)
mov [si],al 将找到的断码放到LEDbuf中
inc si LEDbuf地址加1,存放下一个断码
inc ah 找content中下一个数字的断码
loop redo 整个redo循环做的事:把content中数字对应的断码放到LEDbuf中,循环最后结果是LEDbuf变成:06h,5bh,4fh,5eh,79h,71h
show: call displayled
jmp show 在LED上一直显示这6个字符
start endp
code ends
end start
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)