×
单片机 > 单片机程序设计 > 详情

数码显示(用到74ls273)

发布时间:2020-06-19 发布时间:
|

以下程序选择的晶振都是6MHz的,实现的功能是秒和分的实时显示在数码管上,用到了6个数码管   ==>>   xx--xx  (左分右秒,中间是小横线)


流程图:

c程序:


//程序选择的晶振是6MHz

#include  

#include  

#include  

#include  


#define PORT XBYTE[0x0CFA0]   //定义片选地址,但是还是不知道怎么来的???

 

unsigned char    code bySegTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F, 0x6F,0x40};//共阴数码管的段选信号 

unsigned char    data byTimerTable[6]={0,0,10,10,0,0}; //要显示的时间放置在byTimerTable,其中byTimerTable[2]和 byTimerTable[3] 内容固定,是符号 “- ”

unsigned char    data byMinute = 0;  //定义分变量,赋初值 

unsigned char    data bySecond = 0;  //定义秒变量,赋初值

 

void InitTimer1(void); 

void Display(void); 

void Delay1ms(void); 

 

void main(void) 

    InitTimer1();  //定时/计数器 1 初始化

           

    for(;;) 

    { 

          Display(); 

    } 

 

void InitTimer1(void) 

        TMOD = 0x10;     //T1 工作于方式 

        TH1 = (65536 - 50000)/256; //置时间常数,延时 0.1 秒    

        TL1 = (65536 - 50000)%256;  //置时间常数,延时0.1 秒   

        ET1 = 1;  //允许 T1 中断   

        EA = 1;   //允许总中断  

        TR1 = 1;  //开启 T1   

 

void Display(void) 

    unsigned char data i; 

    unsigned char data byLedSelect= 0XFE;      //数码管位选置初值,准备选中第 1 个数码管 

 

    byTimerTable[4] = bySecond / 10;   //获取秒的十位数  

    byTimerTable[5] = bySecond % 10;   //获取秒的个位数  


    byTimerTable[0] = byMinute/ 10;         //获取分钟的十位数 

    byTimerTable[1] = byMinute% 10;     //获取分钟的个位数 

         

    for(i=0;i<6;i++) 

    { 

        PORT = bySegTable[byTimerTable[i]];  //送段选 

        P1 = byLedSelect;    //送位选 

        Delay1ms(); 

        PORT = 0x00;  //关闭段选 

        P1 = 0xFF;   //关闭位选

        byLedSelect = _crol_(byLedSelect, 1);  //位选左移一位(循环左移),注意和 byLedSelect byLedSelect << 1;(补零左移,还是?)的区别。

    } 

 

 

void Delay1ms(void) 

        unsigned char a,b; 

        for(b=71;b>0;b--) 

                for(a=2;a>0;a--); 

 

void Timer1Interrupt(void)  interrupt 3      //T1中断服务程序

    static unsigned char data byCounter = 0;   //  设置byCounter为静态局部变量 

     

    TL1 = bySecond % 10;  //重置时间常数 

    TH1 = bySecond / 10;  //重置时间常数 

     

    byCounter++;      //计数器加1 

    if(byCounter ==10) 

    { 

        byCounter = 0; 

        bySecond++;     

        if(bySecond == 60) 

        { 

            bySecond = 0;    

            byMinute++;       

            if(byMinute== 60) 

            { 

                byMinute = 0;  


            } 

        } 

    }   

 


汇编程序:(还没在实验上跑过,程序能能不实现功能不清楚,先发上来先,后若发现问题必更新,若热心人看到有错,麻烦请你提出,在此感激不尽,嘻嘻,汇编真是不好搞懂,傻傻的对着它,头都晕了)



;已在2012年5月29日7:29:44修改  

   PORT EQU 0CFA0H

    BUF EQU 23H       ;存放初值

    SBF EQU 22H       ;存放秒值

    MBF EQU 21H       ; 存放分值

    CSEG AT 4000H

    LJMP START 

    CSEG AT 401BH

    LJMP CLOCK

    CSEG AT 4100H

START:

    MOV R0, #40H    ;40H-45H是显示缓冲区

    MOV A, #00H     ;依次存放高位

    MOV @R0, A      ;0A,0A(横线) 以及秒

    INC R0          ;高位,秒低位

    MOV @R0, A


    INC R0

    MOV A, #0AH

    MOV @R0, A

    INC R0

    MOV @R0, A


    INC R0

    MOV A, #00H

    MOV @R0, A

    INC R0

    MOV @R0, A 


    MOV TMOD, #10H      ;定时器1初始化为方式1 

    MOV TH1, #3CH       ;计数50000次,即延时了50*2ms

    MOV TL1, #0B0H      ;置时间常数,延时0.1秒 

    MOV BUF, #00H       ;置0 

    MOV SBF, #00H

    MOV MBF, #00H

    SETB ET1

    SETB EA

    SETB TR1

DS1:

    MOV R0, #40H       ;置显示缓冲区首址

    MOV R2, #0AH      ;位选,置扫描初值,点亮最左边的LED6,与下面的CPL A相关

DS2:

    MOV DPTR, #PORT    ;

    MOV A, @R0         ;得到的段显码输出到段数据口(即是更新的数据给A) 

    ACALL TABLE

    MOVX @DPTR, A      ;即是更新的数据在数码管显示

    MOV A, R2

    CPL A              ;什么意思,要加个各个位取反干嘛??

    MOV P1, A          ;位选吧,选通那个数码管,但是上面的CPL A到底有何用处,与这条语句有何联系呢???【请看MOV R2, #0A】

    MOV R3, #0FFH      ;延时一小段时间 

DEL:

    NOP

    DJNZ R3, DEL

    INC R0           ;显示缓冲字节加一 

    CLR C            ;RRC与C是有联系的

    MOV A, R2

    RRC A           ;显码右移一位,要留意于RR的区别, 

    MOV R2, A       ;最末一位是否显示完毕?,如无则继续往下显示  

    JNZ DS2

    MOV R0, #45H   ;不清楚45H填对了木有,应该对吧,

    MOV A, SBF

    ACALL GET

    DEC R0

    DEC R0

    MOV A, MBF

    ACALL GET

    SJMP DS1

TABLE:

    INC A            ;PC指向的程序要执行的下一条语句,又一位RET占用了一个字节,若A开始是0的画,执行这条语句后,再执行MOVC A, @A+PC就指向了下面【DB 。。。】的首地址

    MOVC A, @A+PC    ;有很大的疑问,就是不懂,怎么就能直接求出PC的地址呢?而不是在keil调试中发现

    RET

    DB 3FH, 06H, 5BH, 4FH, 66H, 6DH

    DB 7DH, 07H, 7FH, 6FH, 40H

GET:

    MOV R1, A      ;把从分或秒字节中取来的值的高 

    ANL A, #0F0H   ;位屏蔽掉,并送入缓冲区???取高位不太清楚0F0H填的对不对

    MOV @R0, A

    DEC R0

    MOV A, R1      ;把从分或秒字节中取来的值的低 

    SWAP A         ;位屏蔽掉,并送入缓冲区 

    ANL A,#0F0H    ;???取低位不太清楚0F0H填的对不对

    MOV @R0, A

    DEC R0           ;R0指针下移一位

    RET

CLOCK:

    MOV TL1, #0B0H       ;置时间常数 

    MOV TH1, #3CH        ;计数50000次,即延时了50*2ms

    PUSH PSW

    PUSH ACC

    INC BUF               ;计数加一

    CJNE A, #0AH, QUIT    ;计到10否?没有则转到QUIT退出中断,注意与下面进行DA转换的区别,这里表示的十六进制数

    MOV BUF, #00H

    MOV A, SBF

    INC A                ;秒值加一,经十进制调整后放入 

    DA A                 ;十进制调整指令,功能是在进行BCD码加法运算时,用来对BCD码的加法运算结果进行自动修正

    MOV SBF, A

    CJNE A, #60H, QUIT   ;计到60否?没有则转到QUIT退出中断 3CH转为十进制为60,注意这里的数表示的是BCD码,与上面的DA息息相关

    MOV SBF, #00H        ;是,秒字节清零

    MOV A, MBF

    INC A                ;分值加一,经十进制调整后放入 

    DA A                 ;分字节

    MOV MBF, A

    CJNE A, #60H, QUIT   ;分值为60否?不是则退出中断,注意这里的数表示的BCD码,与上面的DA相关

    MOV MBF, #00H        ;是,清零 

QUIT:

    POP ACC

    POP PSW

    RETI

END


注意这里的数表示的是BCD码,与上面的DA息息相关


关键字:数码显示  74ls273 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机CO2检测显示程序解析