Writing a clock program using a timer based on the MCS-51 microcontroller (assembly)

Publisher:乡村乐园Latest update time:2022-09-07 Source: csdnKeywords:MCS-51 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1. Think carefully about the good idea

Writing a clock program using a timer is a headache. Put aside other fancy functions and start with the most basic time display. The rest can be dealt with later.


What we generally hope is that the clock can keep timing, call the display to show the current time when needed, and do other things at the same time, so of course we can't use delay to write it, otherwise this clock will be useless except for displaying time.


We hope to have an interrupt every time the timing reaches one second, and in the interruption, add one second to the time series in the storage (the time series is stored in the form of one byte for each hour, minute, and second). The maximum timing time of the 51 single-chip microcomputer timer 0 mode 1 is 216=65536μs, which is about 65ms. But we can have an interrupt every 50ms, and the time series will add one second when the interruption reaches the 20th time; or we can have an interrupt every 20ms, and the time series will add one second when the interruption reaches the 50th time. Generally speaking, making the single timing time as long as possible can reduce the error, but I still want to use 20ms as an example QwQ

Regarding time series, when adding one second, it must be able to satisfy the functions of incrementing to minutes after 60 seconds, incrementing to seconds after 60 minutes, and returning to zero after 24 hours.

The display part adopts a dynamic display method, that is, when the display subroutine is called, each bit from left to right takes turns to display 0.5ms of time, and the cycle continues. To the human eye, the visual effect is a constantly bright time display.


Since the display uses a 6-bit eight-segment digital tube, the time sequence (3-byte compressed BCD code) must be split into 6-bit 0XH and stored in the display buffer before display.


Let's sort out the ideas. First, set the timer to generate an interrupt every 20ms. When the interrupt reaches the 50th time, call the subroutine to add one second to the stored time series. In the main program, we only need to perform the cycle operation of splitting BCD → display (you can add functions directly in the main program later).


2. Fast forward to drawing the program flowchart

Main program block diagram

image.png

Timer T0 interrupt program flowchart
image.png
Time series plus one second subroutine
image.png

image.png

image.png

BCD Splitting Subroutine

image.png

Show Subdiagram

image.png

image.png

3. Decent source code

Some notes

The MCU clock crystal oscillator corresponding to this code is 12MHz

The 6-digit 8-segment digital tube of the simulator has a segment code port address of 8004H and a bit code port address of 8002H

20H 21H 22H units store the BCD values ​​of [hour, minute, second] respectively

30H~36H total 6 units as display buffer

Since the execution of instructions takes a certain amount of machine cycles, the clock may have an error of microseconds per second. You can use an oscilloscope to debug and correct it later and modify the code.

Currently, only the time display function is available, and other functions will be updated later.

source code

ORG 0000H

SJMP MAIN

ORG 000BH

LJMP SER0

ORG 0030H

MAIN:

MOV SP,#70H ;Set stack SP

CLR EA ; Disable interrupt

MOV 30H,#23H ; Set the initial time value

MOV 31H,#59H

MOV 32H,#55H

MOV TMOD,#01H ; Use timer 0, software control, timing mode, mode 1

MOV TH0,0B1H ; initial timing value: 2^16-20ms/1us=45536=B1E0H

MOV TL0,0E0H

MOV R6,#50 ; Set the count to 50 as a global variable for interrupt count

SETB EA ; Enable interrupt

SETB ET0 ; Enable T0 interrupt

SETB TR0 ; Start timer 0

SHOW:

LCALL LOOSE ; Call subroutine to split BCD code and store it in display buffer

LCALL DISP ;Call the display subroutine to display

LJMP SHOW


SER0: ;Interrupt subroutine

CLR EA ; Disable interrupt

MOV TH0,#0B1H ; Re-fill the initial value of the timing

MOV TL0,#0E0H

DJNZ R6,EXIT ; Continue to execute the following instructions when the count reaches 50 times, otherwise an interrupt will occur

MOV R6,#50 ;Reset the count

PUSH ACC ; protect working register

PUSH PSW

CLR RS1 ;Select register bank 01

SETB RS0

LCALL NUMINC ; Call the subroutine to add one second to the time value

POP PSW

POP ACC

EXIT:

RARELY


LOOSE: ; Split subroutine, compress BCD code->0XH

MOV R5,#03H ; 3 bytes in total, need to loop 3 times

MOV R0,#30H ; Display buffer first address

MOV R1,#20H ;Time series storage first address

LOOP1:

MOV A,@R0

ANL A,#0F0H ; take the high position

SWAP A

MOV @R1,A

INC R1

MOV A,@R0 ; store high bit

ANL A,#0FH ; take the low bit

MOV @R1, A ; store low bit

INC R0

INC R1

DJNZ R5,LOOP1


DISP: ;Display subroutine

MOV R2, #20H ; initial value of bit code

MOV R3, #06H ; 6 bits in total

MOV R0, #20H ; Display buffer first address

SIX:

MOV R7, #250 ; Delay self-loop times

MOV DPTR,#8002H ; bit code port address

MOV A,#00H

MOVX @DPTR,A ; Turn off display

MOV A,@R0

MOV DPTR,#DATA0

MOVC A,@A+DPTR ; Look up the table to get the segment code value

MOV DPTR,#8004H ; segment code port first address

MOVX @DATR,A ;segment code value is sent to segment code port

MOV DPTR,#8002H

MOV A,R2

MOVX @DPTR A ; send bit code, segment code display

DJNZ R7, $ ; loop R7 times in place to achieve a delay effect

INC R0

RR A

MOV R2,A

DJNZ R3,SIX

RIGHT


NUMINC: ;Time series plus one second subroutine

MOV R1,#32H ;Time sequence end address (seconds)

MOV A,@R1

ADD A,#01H ; add 1

DA A ; Convert to BCD code

MOV @R1, A ; save

CJNE @R1, #60H, TORET; If it is less than 60 seconds, return directly, otherwise execute the following program

MOV @R1, #00H ; seconds clear zero

DEC R1 ; perform minute operation

MOV A,@R1

ADD A,#01H

And A

MOV @R1,A

CJNE @R1, #60H, TORET; If it is less than 60 minutes, return directly, otherwise execute the following program

MOV @R1, #00H ; minutes reset

DEC R1 ;Perform hour operation

MOV A,@R1

ADD A,#01H

And A

MOV @R1,A

CJNE @R1, #24H, TORET; If it is not 24 hours, return directly, otherwise execute the following program

MOV @R1, #00H ; hours reset

LAW:

RIGHT

DATA0: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;0 1 2 3 4 5 6 7 8 9

DB 77H,7CH,39H,5EH,79H,71H,00H ; ABCDEF off

END


4. About the dynamic display of digital tube

Common cathode digital tube character segment code

Eight-segment digital tube appearance

Segment Code
Segment Code

Digital tube dynamic display principle

The principle of dynamic display is that the common end of each digital tube is controlled by an I/O output to achieve time-sharing selection; and after the segments of each digital tube are connected in parallel, they are connected to the output end of a latch. When the CPU outputs the code of the character to be displayed through the data bus and is latched by the latch, only the bit selected by the I/O port output is displayed, and the others are not displayed. In order to make each bit display different characters, a scanning method must be adopted, that is, in a unit of time, the CPU outputs different values ​​through the I/O port, selects different bits, and displays them one by one in turn (only one bit is displayed at a certain time); as long as the time interval between each bit is short enough, due to the temporary retention phenomenon of human vision, it looks like each bit is displaying its own character. In order to stably display characters, the CPU must constantly refresh each digital tube. Therefore, although this display method reduces hardware costs, it takes up CPU time and has a lower brightness.


Simulator digital display circuit

Simulator digital tube experimental circuit

The figure above shows the display circuit of the simulation system. The 8-bit segment code and 6-bit bit code are output by two 74LS374 chips.

After the bit code is driven by MC1413 or ULN2003 inverted, the corresponding display bit is selected. U1's output Q1~Q8 is used for the segment code output port (the data to be displayed is sent to this port); the lower 6 bits of U2's output Q1~Q8 are the bit code output port (that is, the output port to select which bit to display); when the digital tube needs to display a certain character, the segment code of the character is sent to U1 through the data bus, and is sent to the a~g and dp of the digital tube through the 74LS374 latch; then, the bit code of which digital tube needs to be displayed is also sent to U2 through the data bus, and the 6 digital tubes are also controlled by the 74LS374 latch. The bit codes from left to right are 20H, 10H, 08H, 04H, 02H, and 01H.

Keywords:MCS-51 Reference address:Writing a clock program using a timer based on the MCS-51 microcontroller (assembly)

Previous article:Design of N-byte hexadecimal division based on 51 single-chip microcomputer - taking 6 bytes divided by 3 bytes as an example
Next article:51 single chip microcomputer output square wave problem

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号