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
Timer T0 interrupt program flowchart
Time series plus one second subroutine
BCD Splitting Subroutine
Show Subdiagram
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
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
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.
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
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
- What is the difference between low inertia and high inertia of servo motors?
- Google discontinues Android Things, its IoT operating system
- Reverse voltage protection for battery chargers
- ASUS laptop, the second hard drive is gone? !
- BMS Software Engineer Recruitment
- Low power mode of msp430f149
- GaN Reference Designs
- How to get started with embedded development?
- [Perf-V Review] Transplanting the Hummingbird E203 open source SOC to the FPGA board
- Design USB3.1 high-speed SD Card reader based on Genesys GL3224
- If you want to make the three-pole tube work in the amplification area, what is the idea? You need to calculate the static working point ib ic VCE three...