首页 > 编程语言 >基于ATMega16的数码管时钟显示实例(汇编)

基于ATMega16的数码管时钟显示实例(汇编)

时间:2024-01-18 17:55:06浏览次数:24  
标签:TMP PC RETI Rd 数码管 寄存器 ATMega16 进位 时钟

本例在ATMega16上,利用汇编程序通过8个七段数码实现具有时分秒的实时时钟显示,主要讨论定时器T2中异步时钟的使用方法及时钟信号的产生。

本例中的8位数码管采用两个4位的组合而成,段码端通过限流电阻及跳线帽接在PB端口,位选端通过PNP三极管扩流后接在PA端口,电路如下图所示。

完整的汇编代码如下。

.INCLUDE "M16DEF.INC"
.DEF    TMP = R16                ;定义R16寄存器的别名(注意小于16号的寄存器不能进行LDI操作)
.DEF    CNT = R17
.DEF    SHIFT = R18
.DSEG                            ;以下数据放置在Data区域,即RAM中
.ORG    $0060                    ;从$60地址开始存放,即RAM的起始地址
.EQU    SECOND = $60             ;定义一个存放秒的RAM空间别名
.EQU    MINUTE = $61             ;定义一个存放分的RAM空间别名
.EQU    HOUR = $62               ;定义一个存放时的RAM空间别名
.CSEG                            ;以下数据放置在Code区域,即Flash中
.ORG    $0000
    JMP        RESET             ;复位的向量入口,地址为$00
    NOP                          ;空指令
    RETI                         ;中断返回
    NOP
    RETI
    NOP
    RETI
    NOP
    RJMP        TIME2_OVF         ;定时器2的溢出中断向量入口,地址为$10
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RJMP        TIME0_OVF          ;定时器0的溢出中断向量入口,地址为$12
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
    NOP
    RETI
.ORG    $002A                    ;前面最后一个中断向量入口地址是$28,双字后刚好是$2A
RESET:
    LDI     TMP, HIGH(RAMEND)    ;获取RAM空间的最大地址高字节(ATMega16为$04)
    OUT     SPH, TMP             ;高字节送SP高位
    LDI     TMP, LOW(RAMEND)     ;获取RAM空间的最大地址低字节(ATMega16为$5F)
    OUT     SPL, TMP             ;低字节送SP低位
    SER     TMP                  ;把R16全部置1
    OUT     DDRA, TMP            ;把端口A设置为输出方向
    OUT     DDRB, TMP            ;把端口B设置为输出方向
    LDI     SHIFT, $FE           ;从端口A的第0位开始扫描
    LDI     ZL, LOW(LED7 * 2)    ;获取字形码所在的首地址低字节
    LDI     ZH, HIGH(LED7 * 2)   ;获取字形码所在的首地址高字节,乘2的目的是让整个字地址左移1位,空出最低位来作为高/低字节选择
    CLR     TMP
    STS     SECOND, TMP          ;清0秒的值        
    LDI     TMP, $59
    STS     MINUTE, TMP
    LDI     TMP, $23
    STS     HOUR, TMP
;Timer0溢出中断配置
    LDI     TMP, $06
    OUT     TCNT0, TMP            ;以上为设置定时器0的初始值
    IN      TMP, TCCR0
    ORI     TMP, $03
    OUT     TCCR0, TMP            ;设置为64分频,根据上面的初始值,8MHz晶振对应2ms
    IN      TMP, TIMSK
    ORI     TMP, $01
    OUT     TIMSK, TMP            ;允许定时器0的溢出中断
;Timer2溢出中断配置(异步方式)
    LDI     TMP, $05
    OUT     TCCR2, TMP            ;设置为128分频
    CLR     TMP
    OUT     TCNT2, TMP            ;计数值置0
    LDI     TMP, $08
    OUT     ASSR, TMP             ;设置定时器2为异步时钟模式
WT:
    IN      TMP, ASSR    
    CPI     TMP, $08
    BRNE    WT                    ;等待ASSR寄存器的低三位为0
    IN      TMP, TIFR
    ORI     TMP, $40
    OUT     TIFR, TMP             ;强制清除定时器2的中断标志位            
    IN      TMP, TIMSK
    ORI     TMP, $40
    OUT     TIMSK, TMP            ;允许定时器2的溢出中断
    SEI                           ;开启总中断
    SEC                           ;进位位置1
LOOP:
    RJMP    LOOP
;定时器2溢出中断服务程序(时钟)
TIME2_OVF:                        
    LDS     TMP, SECOND            ;获取当前秒的值
    INC     TMP                    ;秒加1
    CPI     TMP, $5A               ;秒是否到60
    BREQ    M                      ;秒到60则跳到M行执行
    CPI     TMP, 10                ;秒未60时,如果个位大于10(0x0A),则进行BCD调整
    BRHS    SOK                    ;若半进位位H为1,则跳到SOK行执行
    SUBI    TMP, $FA               ;减去$FA,进行BCD调整
SOK:
    STS     SECOND, TMP            ;回写秒的值
    RETI                           ;中断返回
M:                                 ;分部分
    CLR      TMP        
    STS      SECOND, TMP           ;秒清0
    LDS      TMP, MINUTE           ;获取当前分的值
    INC      TMP                   ;分加1
    CPI      TMP, $5A              ;分是否到60
    BREQ     H                     ;分到60则跳到H行执行
    CPI      TMP, 10               ;分未60时,如果个位大于10(0x0A),则进行BCD调整
    BRHS     MOK                   ;若半进位位H为1,则跳到MOK行执行
    SUBI     TMP, $FA              ;减去$FA,进行BCD调整
MOK:
    STS      MINUTE, TMP           ;回写分的值
    RETI                           ;中断返回
H:                                 ;时部分
    CLR      TMP
    STS      MINUTE, TMP           ;分清0
    LDS      TMP, HOUR             ;获取当前时的值
    INC      TMP                   ;时加1
    CPI      TMP, $24              ;时是否到24
    BREQ     R                     ;时到24则跳到R行执行
    CPI      TMP, 10               ;时未24时,如果个位大于10(0x0A),则进行BCD调整
    BRHS     HOK                   ;若半进位位H为1,则跳到HOK行执行
    SUBI     TMP, $FA              ;减去$FA,进行BCD调整
HOK:
    STS      HOUR, TMP             ;回写时的值
    RETI                           ;中断返回
R:
    CLR      TMP
    STS      HOUR, TMP             ;时清0
    RETI                           ;中断返回
;定时器Timer0溢出中断服务程序
TIME0_OVF:
    LDI      TMP, $06
    OUT      TCNT0, TMP            ;重载定时器初始值
    SBRS     SHIFT, 7              ;扫描的第7位为1则继续看第6位
    RJMP     MG                    ;扫描的第7位为0则跳到MG(秒的个位)去执行
    SBRS     SHIFT, 6              ;扫描的第6位为1则继续看第5位
    RJMP     MS                    ;扫描的第6位为0则跳到MS(秒的十位)去执行
    SBRS     SHIFT, 5              ;扫描的第5位为1则继续看第4位
    RJMP     FGF                   ;扫描的第5位为0则跳到FGF(分隔符)去执行
    SBRS     SHIFT, 4              ;扫描的第4位为1则继续看第3位
    RJMP     FG                    ;扫描的第4位为0则跳到FG(分的个位)去执行
    SBRS     SHIFT, 3              ;扫描的第3位为1则继续看第2位
    RJMP     FS                    ;扫描的第3位为0则跳到FS(分的十位)去执行
    SBRS     SHIFT, 2              ;扫描的第2位为1则继续看第1位
    RJMP     FGF                   ;扫描的第2位为0则跳到FGF(分隔符)去执行
    SBRS     SHIFT, 1              ;扫描的第1位为1则继续看第0位
    RJMP     SG                    ;扫描的第1位为0则跳到SG(时的个位)去执行
    SBRS     SHIFT, 0              ;扫描的第0位为1则跳一行执行
    RJMP     SS                    ;扫描的第0位为0则跳到SS(时的十位)去执行
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    RETI                           ;中断返回
SS:
    LDI      ZL, LOW(LED7 * 2)     ;获取字形码所在的首地址低字节,字形码的数量不超过255,所以可以不用再次获取地址高字节,因为没改动过
    LDS      CNT, HOUR             ;获取时的当前值
    ANDI     CNT, $F0              ;屏蔽低4位
    SWAP     CNT                   ;高低4位交换
    ADD      ZL, CNT               ;低字节加上要显示的时十位值
    LPM                            ;查表后的内容送入R0中
    OUT      PORTB, R0             ;把R0的内容送显
    OUT      PORTA, SHIFT          ;打开显示的第7位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     BRIDGE                ;如查进位位C的值为0,则跳到NEXT执行(此处超出了跳转范围,故借用RJMP来实现),否则顺序执行
    RETI                           ;如果还没扫描到头,则中断返回
BRIDGE:                            ;桥接跳转    
    RJMP     NEXT
SG:
    LDI      ZL, LOW(LED7 * 2)     ;获取字形码所在的首地址低字节,字形码的数量不超过255,所以可以不用再次获取地址高字节,因为没改动过
    LDS      CNT, HOUR             ;获取时的当前值
    ANDI     CNT, $0F              ;屏蔽高4位
    ADD      ZL, CNT               ;低字节加上要显示的时十位值
    LPM                            ;查表后的内容送入R0中
    OUT      PORTB, R0             ;把R0的内容送显
    OUT      PORTA, SHIFT          ;打开显示的第6位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     NEXT                  ;如查进位位C的值为0,则跳到NEXT执行,否则顺序执行
    RETI                           ;如果还没扫描到头,则中断返回
FS:
    LDI      ZL, LOW(LED7 * 2)     ;获取字形码所在的首地址低字节,字形码的数量不超过255,所以可以不用再次获取地址高字节,因为没改动过
    LDS      CNT, MINUTE           ;获取时的当前值
    ANDI     CNT, $F0              ;屏蔽低4位
    SWAP     CNT                   ;高低4位交换
    ADD      ZL, CNT               ;低字节加上要显示的时十位值
    LPM                            ;查表后的内容送入R0中
    OUT      PORTB, R0             ;把R0的内容送显
    OUT      PORTA, SHIFT          ;打开显示的第4位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     NEXT                  ;如查进位位C的值为0,则跳到NEXT执行,否则顺序执行
    RETI                           ;如果还没扫描到头,则中断返回
FG:
    LDI      ZL, LOW(LED7 * 2)     ;获取字形码所在的首地址低字节,字形码的数量不超过255,所以可以不用再次获取地址高字节,因为没改动过
    LDS      CNT, MINUTE           ;获取时的当前值
    ANDI     CNT, $0F              ;屏蔽高4位
    ADD      ZL, CNT               ;低字节加上要显示的时十位值
    LPM                            ;查表后的内容送入R0中
    OUT      PORTB, R0             ;把R0的内容送显
    OUT      PORTA, SHIFT          ;打开显示的第3位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     NEXT                  ;如查进位位C的值为0,则跳到NEXT执行,否则顺序执行
    RETI                           ;如果还没扫描到头,则中断返回
MS:
    LDI      ZL, LOW(LED7 * 2)     ;获取字形码所在的首地址低字节,字形码的数量不超过255,所以可以不用再次获取地址高字节,因为没改动过
    LDS      CNT, SECOND           ;获取时的当前值
    ANDI     CNT, $F0              ;屏蔽低4位
    SWAP     CNT                   ;高低4位交换
    ADD      ZL, CNT               ;低字节加上要显示的时十位值
    LPM                            ;查表后的内容送入R0中
    OUT      PORTB, R0             ;把R0的内容送显
    OUT      PORTA, SHIFT          ;打开显示的第1位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     NEXT                  ;如查进位位C的值为0,则跳到NEXT执行,否则顺序执行
    RETI                           ;如果还没扫描到头,则中断返回
MG:
    LDI      ZL, LOW(LED7 * 2)     ;获取字形码所在的首地址低字节,字形码的数量不超过255,所以可以不用再次获取地址高字节,因为没改动过
    LDS      CNT, SECOND           ;获取时的当前值
    ANDI     CNT, $0F              ;屏蔽高4位
    ADD      ZL, CNT               ;低字节加上要显示的时十位值
    LPM                            ;查表后的内容送入R0中
    OUT      PORTB, R0             ;把R0的内容送显
    OUT      PORTA, SHIFT          ;打开显示的第0位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     NEXT                  ;如查进位位C的值为0,则跳到NEXT执行,否则顺序执行
    RETI                           ;如果还没扫描到头,则中断返回            
FGF:
    LDI      TMP, $FD
    OUT      PORTB, TMP            ;把字符-送显
    OUT      PORTA, SHIFT          ;打开显示的第6位和第1位
    SEC                            ;进位位C置1,由于下面用到带进位位的左移
    ROL      SHIFT                 ;带进位位左移
    BRCC     NEXT                  ;如查进位位C的值为0,则跳到NEXT执行,否则顺序执行
    RETI
NEXT:                              ;扫描到头
    LDI      SHIFT, $FE            ;从端口A的第0位开始扫描
    RETI                           ;中断返回
.CSEG                              ;以下数据放置在Code区域,即Flash中
LED7:                              ;字形码数据,以字节方式顺序存放
    .DB $03,$9F,$25,$0D,$99,$49,$41,$1F
    .DB $01,$09,$11,$C1,$63,$85,$61,$71

本例使用到了AVR中I/O空间的13个寄存器,即SPH、SPL、DDRA、DDRB、PORTA、PORTB、TCNT0、TCNT2、TCCR0、TCCR2、ASSR、TIFR和TIMSK。其中SPH、SPL、DDRA、DDRB、PORTA、PORTB等6个寄存器的介绍可参考“基于ATMega16的流水灯实例”一文,TIMSK寄存器可参考“基于ATMega16的数码管动态扫描显示实例”一文。另外,本例还使用了RAM空间的3个字节,分别作为时、分、秒的存储单元。

先来看TCNT0寄存器和TCNT2寄存器,它们分别是定时器T0和T2的计数寄存器,其结构完全一样,这里就只给出TCNT0的具体结构,如下表所示。

定时器T0和T2的计数位宽均为8位,初始值为0,最大计数值为255。要改变它们的初始计数值,直接写寄存器即可。 

再来看TCCR0寄存器,它是定时器T0的控制寄存器,初始值为全0,具体如下表所示。

T0的工作模式由第3、6两位(WGM01 、WGM00)来决定,这里需要它们都为0,即让T0工作在普通定时模式。低3位(CS00~CS02)用来确定时钟的分频情况,它与定时器T1中的CS10~CS12完全一样,具体可参考“基于ATMega16的数码管动态扫描显示实例”一文中的相关部分,这里就不在重复了。

接下来看TCCR2寄存器,它是定时器T2的控制寄存器,初始值为全0,具体如下表所示。

T2的工作模式由第3、6两位(WGM21 、WGM20)来决定,这里需要它们都为0,即让T2工作在普通定时模式。低3位(CS20~CS22)用来确定时钟的分频情况,这里与T0、T1中的不完全一样,具体如下表所示。

在本例中,由于T2采用异步晶振的方式,晶振频率为32768Hz,所以上面3位设置为101,即选择128分频,分频后的频率为256Hz。这样在T2计数256次之后,就可以产生精确的秒信号。

下面来看ASSR寄存器,它是异步状态寄存器,为定时器T2所特有,初始值为全0,具体如下表所示。

第3位为异步设定位,写0时为系统时钟模式,写1时为异步时钟模式。在异步模式下,由于与系统时钟有差异,所以在操作TCCR2、OCR2、TCNT2等寄存器时,需要等待。第0~2位分别代表相应寄存器的更新忙标志位,只有等待值变为0时,才能对相应的寄存器进行操作。

最后看TIFR寄存器,它是中断标志寄存器,为T0、T1和T2所共有,初始值为全0,具体如下表所示。

其中的第0、2、6三位分别用来标志T0、T1、T2的溢出中断,即当定时器有溢出中断发生时,相应的位会被硬件置1 ,中断响应后会自动清零,写1将强制清零该位。

本例中一共使用到了27种指令,其中的JMP、RJMP、LDI、OUT、SER、SEC、ROL、BRNE等8条指令可参考“基于ATMega16的流水灯实例”一文。 NOP、RETI、CLR、SEI、INC、ADD、LPM、BRCC等8条指令可参考基于ATMega16的数码管动态扫描显示实例“”,其余11条指令解释如下。

1)寄存器数据直接送SRAM
  STS  k,Rr  0 ≤ r ≤ 31,0 ≤ k ≤ 65535
说明:将寄存器中的内容直接存储到数据存储空间中。对于带有SRAM的芯片,数据空间由寄存器堆,I/O 存储器和内部SRAM 存储器组成。对存储器数据的访问被限定在当前数据段的64K 字节的空间。该指令不一定支持所有的AVR芯片。
操作:(k) ← Rr  PC ← PC + 2   32位机器码:1001 001d dddd 0000 kkkk kkkk kkkk kkkk
2)I/O空间数据送寄存器
  IN   Rd, A    0 ≤ d ≤ 31,0 ≤ A ≤ 63
说明:将I/O空间的数据传送到寄存器Rd中。
操作:Rd ← I/O(A)    PC ← PC + 1   16位机器码:1011 0AAd dddd AAAA
3)“或”立即数
  ORI   Rd, K    16 ≤ d ≤ 31,0 ≤ K ≤ 255
说明:将寄存器Rd的值与常量进行“或”操作,结果送入寄存器Rd中。
操作:Rd ← Rd Ⅴ K    PC ← PC + 1   16位机器码:0110 KKKK dddd KKKK
4)与立即数比较
  CPI   Rd, K    16 ≤ d ≤ 31,0 ≤ K ≤ 255
说明:完成寄存器Rd和常数的比较操作,寄存器的内容不改变,该指令后能使用所有条件跳转指令。
操作:Rd — K    PC ← PC + 1   16位机器码:0011 KKKK dddd KKKK
5)SRAM数据直接送寄存器
  LDS  Rd,k  0 ≤ d ≤ 31,0 ≤ k ≤ 65535
说明:从数据区中指定的位置装入一个字节的数据到寄存器。对于带有SRAM的芯片,数据空间由寄存器堆,I/O 存储器和内部SRAM 存储器组成。对存储器数据的访问被限定在当前数据段的64K 字节的空间。该指令不一定支持所有的AVR芯片。
操作:Rr ← (k)  PC ← PC + 2   32位机器码:1001 000d dddd 0000 kkkk kkkk kkkk kkkk
6)相等跳转
  BREQ  k  -64 ≤ k ≤ 63
说明:条件相对跳转,测试零标志位Z,如果Z位被置位,则相对PC值跳转k个字。如果在执行CP、CPI、SUB 或SUBI 指令后,立即执行该指令,且当寄存器Rd中数与寄存器 Rr中数相等时,将发生跳转。可跳转k个字,k 为7位带符号数,最多可向前跳63个字,向后跳64个字。这条指令相当于指令“BRBS 1,k”。
操作:If Rd = Rr (Z = 1) then PC ← PC + k + 1, else PC ← PC + 1  16位机器码:1111 00kk kkkk k001
7)半进位标志为1跳转
  BRHS  k  -64 ≤ k ≤ 63
说明:条件相对跳转,测试半进位标志H,如果H位被置位,则相对PC值跳转k个字。k 为7位带符号数,最多可向前跳63个字,向后跳64个字。该指令相当于指令“BRBS 5,k”。
操作:If H = 1 then PC ← PC + k + 1, else PC ← PC + 1  16位机器码:1111 00kk kkkk k101
8)减立即数
  SUBI   Rd, K    16 ≤ d ≤ 31,0 ≤ K ≤ 255
说明:寄存器Rd的内容和常数相减,结果送目的寄存器Rd。该指令工作于寄存器R16~R31之间,非常适合X、Y 和Z指针的操作。
操作:Rd ← Rd - K    PC ← PC + 1   16位机器码:0101 KKKK dddd KKKK
9)寄存器位为1跳行
  SBRS  Rr,b  0 ≤ r ≤ 31,0 ≤ b ≤ 7
说明:测试寄存器的某一位,如果这一位为1则跳过下一条指令。
操作:If Rr(b) = 1 then PC ← PC + 2 (or 3) else PC ← PC + 1  16位机器码:1111 111r rrrr 0bbb
10)“与”立即数
  ANDI   Rd, K    16 ≤ d ≤ 31,0 ≤ K ≤ 255
说明:寄存器Rd的内容和常数逻辑与,结果送目的寄存器Rd。
操作:Rd ← Rd · K    PC ← PC + 1   16位机器码:0111 KKKK dddd KKKK
11)寄存器半字节交换
  SWAP   Rd    0 ≤ d ≤ 31
说明:将一个寄存器中的高四位与低四位进行交换。
操作:Rd(7:4) ← Rd(3:0),Rd(3:0) ← Rd(7:4)    PC ← PC + 1   16位机器码:1001 010d dddd 0010

此外,程序中还用到了另外一些伪指令(.INCLUDE、.DEF、.ORG可参考“基于ATMega16的流水灯实例”一文,.CSEG、.DB可参考“基于ATMega16的数码管动态扫描显示实例”一文),具体解释如下。 

1)声明数据段(SRAM)
语法:.DSEG
说明:DSEG伪指令声明数据段的起始。一个汇编程序文件可以包含几个数据段,这些数据段在汇编过程中被连接成一个数据段。在数据段中,通常仅由BYTE伪指令(和标号)组成。每个数据段内部都有自己的字节定位计数器。可使用ORG伪指令定义该字节定位计数器的初始值,作为数据段在SRAM中的起始位置。DSEG伪指令不带参数。
2)定义标识符常量
语法:.EQU 标号 = 表达式
EQU伪指令将表达式的值赋给一个标识符,该标识符为一个常量标识符,可以用于后面的指令表达式中,在汇编时凡遇到该标识符都以其等值表达式替代。在编写程序中,只要修改此表达式,就修改了程序中多处涉及该表达式的地方,减少了程序的修改量。但该标识符的值不能改变或重新定义。

下面对程序中的相关部分进行一下说明。
1)ATMega16可以让定时器T2工作在异步模式下,即工作在低频晶振模式下。一般在引脚PC6和PC7之间接一个32768Hz的时钟晶振,让T2在异步模式下使用。在T2中选择时钟的128分频,然后让计数器计满256次后产生溢出中断,则此时T2的中断时间刚好就是1秒。这样做的好处在于,避免在使用较高频率系统晶振的情况下,通过8位定时器难以精确地实现较长时间的定时。
2)定时器T2工作在异步模式时,对其寄存器的操作由于处于不同的时钟频率之下,所以需要等待。即在操作完TCCR2、OCR2、TCNT2等寄存器之后,需要等待他们完成。或者说在操作他们之前需要判忙,不忙才能进行操作。另外,为了保险,在配置完成T2之后,还需要强制清一下T2的中断标志位再使用。
3)有了秒时钟之后,再产生出分和时,并在SRAM中开辟三个字节空间,分别用于存放实时的时、分、秒。申请的空间最好位于SRAM的最低地址处(因为最高地址被用作了堆栈空间)。在ATMega16中,数据空间一共包含了三类空间,地址从低到高依次是通用寄存器空间、I/O寄存器空间和内部SRAM空间。而SRAM空间是从地址$0060开始到地址$045F结束,所以本例中申请的时、分、秒空间被指定在地址$62~$60处。
4)定时器T2产生出的时、分、秒等计时信号的值,需要作BCD调整,以适应时钟的计时规则。由于时、分、秒最大都只有两位数,且十位的最大值只到5,所以只需要对个位进行调整即可。调整原理是这样,判定个数位在加1后是否大于10(十六进制$A),若不大于则取实际的值,若大于则减去一个十六进制数$FA,这样所得结果就调整过来了。比如,假设当前秒的值为十六进制的$09,则在加1后为十六进制的$0A,而非想要的$10。这时进行$0A-$FA的操作,其结果的最后两位就是$10(前面的若干个F表示负数,不用管它)。然后再把$10回存到秒的存储单元(SRAM中地址为$60处)中,以后取出来再加1,就又回到个位数不超过10的操作了,如此循环。所谓的BCD调整,其实就是让十六进制数“看起来”像十进制数一样的操作。虽然本质上还是十六进制,但“看上去”就像是十进制一样。
5)在分和秒的边界(最大值)判定上,由于是在加1之后BCD调整之前,所以对比的值就是真实的十六进制数,即在判断是否大于60时,并不是与$60比较,而是与$5A比较(因为BCD调整前,$59+1=$5A,调整后才为$60)。但时的边界判定就不存在此问题了(因为$23+1=$24)。
6)本例的动态扫描原理与“基于ATMega16的数码管动态扫描显示实例”一文中的一样,只不过把所使用的定时器换成了T0。这里要强调的是,如何把时间的个位和十位拆分开来显示。在本例中,当取低4位(个位数)时,直接把高4位屏蔽。取高4位(十位数)时,先把高低4位交换,再屏蔽高4位。

标签:TMP,PC,RETI,Rd,数码管,寄存器,ATMega16,进位,时钟
From: https://www.cnblogs.com/fxzq/p/17965868

相关文章

  • 网络授时服务器 时钟同步服务器 gps时钟授时系统
    随着计算机网络规模的不断扩大,各种关键业务越来越多,口令保护、加密、电子认证等安全措施也日益显得重要,许多重要的安全措施都与时间有关。比如电子认证服务就要求加密证书的用户密码须严格与时间标记对应,该证书只在特定的时间窗口内有效,因此在该时间窗内,客户机的时间必须与服务器......
  • 采用模块化方法设计的LMK1C1104DQFR、LMK1C1106PWR、LMK1C1108PWR(LVCMOS)时钟缓冲器系
    LMK1C110x1.8V、2.5V和3.3VLVCMOS时钟缓冲器系列1、概述LMK1C110x是的一款模块化、高性能、低偏斜、通用时钟缓冲器系列器件。整个系列采用模块化方法设计。提供三个不同的扇出选项:1:2、1:3、1:4。该系列所有器件均互相引脚兼容,并向后兼容CDCLVC110x系列,便于操作。该系列所......
  • 北斗GPS卫星时钟服务器(NTP服务器)架构方法步骤
    北斗GPS卫星时钟服务器(NTP服务器)架构方法步骤北斗GPS卫星时钟服务器(NTP服务器)架构方法步骤京准电子科技官微——ahjzsz一、施工简介:应贵司要求,我司提供卫星时钟系统(NTP时钟同步服务器),为解决全网络计算机系统时间同步问题; 二、施工须知:1.使用本装置之前,请您仔细阅读用户手册......
  • 北斗网络时钟服务器介绍、网络校时服务器,北斗网络授时服务器,时钟服务器
    随着科学技术的发展工业信息化高速迈进许多设备对于高精度时间系统应用日益广泛,高稳定时钟系统显得尤为重要,在某些系统设备从而需要网络校时服务器进行校正,网络时间服务器可接收北斗卫星标准时间为基准同步时间。网络校时服务器是针对自动化系统中的计算机、控制装置等进行校时的高......
  • 电子时钟同步系统在西安市精神卫生中心的应用、时钟同步系统,电子时钟系统,时钟同步子
    近期,西安市精神卫生中心使用我公司自主生产的电子时钟同步系统,时钟同步系统为该院提供准确的、统一的时间基准。SYN2151型时钟服务器西安市精神卫生中心是一所集临床医疗、教学、科研、康复和社区防治为一体的三级甲等精神病专科医院,是陕西中医药大学、西安医学院硕士培养点和教学......
  • [转帖]ntp导致的时钟回拨
    https://zhuanlan.zhihu.com/p/587313130 我们的服务器时间校准一般是通过ntp进程去校准的。但由于校准这个动作,会导致时钟跳跃变化的现象。而这种情况里面,往往回拨最能引起我们的困扰,回拨如下所示:  会引起什么问题准点调度任务的误判假设有一个任务每天0点时......
  • 【C++/Qt】QLCDNumber-电子时钟实战
    头文件:#ifndefDIGITALCLOCK_H#defineDIGITALCLOCK_H#include<QLCDNumber>classdigitalClock:publicQLCDNumber{Q_OBJECTpublic:digitalClock(QWidget*parent=0);protected:voidmousePressEvent(QMouseEvent*event);//鼠标点击事件void......
  • 基于STC89C52RC的温湿度显示与按键可调的时钟显示
    大学时候的课程设计项目,本人只负责软件设计。课题摘要摘要温湿度参数的检测已经成为人们日常生产生活中的一个重要的参数指标。温度和湿度是两个最基本的环境参数,人们生活与温湿度息息相关。在工农业生产、环保、科研、化工业、制药业等地方,都经常需要对环境温度和湿度进行测量。......
  • 89C51单片机实现五个步进电机和显示实时时钟和日历功能的代码
    为了实现五个步进电机和显示实时时钟和日历功能,我们需要使用89C51单片机、步进电机驱动模块、数码管显示模块和实时时钟模块。以下是一个简单的代码示例:#include<reg52.h>#include<intrins.h>//定义步进电机驱动模块的引脚sbitIN1=P1^0;sbitIN2=P1^1;sbitIN3=P1^......
  • 22 读写I2C接口的RTC时钟芯片
    软件版本:VIVADO2021.1操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!1概述    本节课继续利用I2C总线控制器实现对RTC时钟芯片,DS1337的读写访问,进一步验证我们设计的i2c控制......