Today we are going to make a very simple 8051 Assembly code for a frequency counter example. We are going to make the example very simple and to the point just the way we normally do in our previous examples. Today’s focus is to demonstrate the very simple frequency counting algorithm implementation in 8051 assembly language. With this algorithm we are going to take a simple delay of 1 second using the 8051 timers. Meanwhile we initiate the external interrupt to count the pulses on External Interrupt pin of the 8051 microcontrollers. The External interrupt will count the number of pulses until the internal timer complete it’s one second delay. After the delay is complete the number of counts on external interrupt is our actual frequency.
For the sake of the simplicity, we are going to display the result on the serial terminal. We do not want to make the code goes extra big as the code is in Assembly language. We will output the frequency on the serial terminal. We are going to use the timer @2400 baud rate at the 12Mhz crystal. The simulation is done on the proteus 8 and the microcontroller used in the proteus is AT89c2051 to keep things simple.
What is a Frequency Counter?
A frequency counter is an electronic instrument that measures the frequency of an input signal. The frequency is defined as the number of occurrences of a repeating event per unit of time. In the context of this code, the frequency counter counts the number of pulses or cycles of a signal within a specified time frame (1 second in this case) to determine its frequency.
Frequency Counter Algorithm
The 8051 frequency counter algorithm initializes the microcontroller’s timers and serial communication, then enters a loop where it repeatedly clears the counter, enables interrupts, waits for a specified time (one second), disables interrupts, and transmits the counted pulses. The external interrupt service routine (ISR) increments the counter digits upon each pulse and handles the overflow by advancing to the next digit. The half-second delay subroutine creates precise timing using Timer 0, while the transmission subroutine converts the counter digits to ASCII and sends them serially. This process effectively measures the frequency of input pulses by counting them over a fixed time interval and sending the result for display or further processing.
Calculation of Limits
Given the above setup:
- Maximum Count: The maximum count before overflow is
9999
. - Time Frame: The code counts pulses in a 1-second interval.
Therefore, the frequency measurement limit is:
- Maximum Measurable Frequency: 9999 pulses per second (or 9999 Hz).
- Minimum Measurable Frequency: 1 pulse per second (or 1 Hz).
In practical terms, the actual measurement limits may be slightly lower due to the overhead of executing instructions and handling interrupts. The effective frequency range for accurate measurement will be somewhat less than the theoretical maximum of 9999 Hz.
8051 Assembly code for frequency counter
Let’s dive into the actual code and try to understand the working of the code step by step. Here is the initial macro definitions of the code.
LEDS EQU P0
DIGIT1 EQU 30H
DIGIT2 EQU 31H
DIGIT3 EQU 32H
DIGIT4 EQU 33H
ORG 0
LJMP MAIN
ORG 3H ;EX0 VECTOR
LJMP EX0_ISR
LEDS
is defined as P0
, the port we will use for LEDs. DIGIT1
, DIGIT2
, DIGIT3
, and DIGIT4
are memory locations (30H, 31H, 32H, 33H) where we will store the digits of the counter.ORG 0
and LJMP MAIN
set the starting point of our program.ORG 3H
and LJMP EX0_ISR
define the interrupt vector for external interrupt 0 (EX0).
MAIN:
;====== SERIAL INIT =============================
MOV TMOD,#22H ;TIMER 1 , MODE 2
MOV TH1,#-13 ;2400 BAUD RATE @ 12MHZ
MOV TH0,#-200 ;PRELOAD VALUE
SETB TR0
MOV SCON,#52H ;8-BIT , 1 STOP , REN ENABLED
SETB TR1 ;START TIMER 1
SETB IT0 ;EDGE TRIGGER
MOV IE,#10000001B ;ENABLE EX0
CLR IE.7
;========== ======================================
Code language: PHP (php)
TMOD
is set to22H
to configure Timer 1 in modeTH1
is set to-13
to get a baud rate of 2400 at a 12MHz clock.TH0
is preloaded with-200
for timing purposes.TR0
andTR1
are set to start Timer 0 and TimerSCON
is set to52H
to configure serial communication.IT0
is set to enable edge-triggered interrupts.IE
is set to10000001B
to enable external interrupt 0 (EX0).
AGAIN:
ACALL CLEAR_COUNTER
SETB IE.7
ACALL HALF_SEC
ACALL HALF_SEC
CLR IE.7
ACALL TRANS_DATA
SJMP AGAIN
Code language: CSS (css)
The AGAIN
loop clears the counter, enables interrupts, waits for half a second twice (total 1 second), disables interrupts, and transmits the counter data. CLEAR_COUNTER
subroutine sets the counter digits to zero. HALF_SEC
subroutine waits for half a second. TRANS_DATA
subroutine transmits the counter digits serially.
EX0_ISR:
INC DIGIT1
MOV A,#10
CJNE A,DIGIT1,EX0_EXIT
MOV DIGIT1,#0
INC DIGIT2
CJNE A,DIGIT2,EX0_EXIT
MOV DIGIT2,#0
INC DIGIT3
CJNE A,DIGIT3,EX0_EXIT
MOV DIGIT3,#0
INC DIGIT4
CJNE A,DIGIT4,EX0_EXIT
MOV DIGIT4,#0
EX0_EXIT:
RETI
Code language: CSS (css)
The EX0_ISR
is the interrupt service routine for external interrupt 0. It increments DIGIT1
and checks if it reaches 10. If DIGIT1
reaches 10, it resets DIGIT1
to 0 and increments DIGIT2
. The process repeats for DIGIT3
and DIGIT4
.
HALF_SEC:
MOV R6,#25
L02: MOV R7,#100
L01: JNB TF0,$
CLR TF0
DJNZ R7,L01
DJNZ R6,L02
RET
Code language: PHP (php)
The HALF_SEC
subroutine uses Timer 0 to create a delay of half a second.
TRANS_DATA:
MOV A,DIGIT4
ADD A,#48
ACALL TX
MOV A,DIGIT3
ADD A,#48
ACALL TX
MOV A,DIGIT2
ADD A,#48
ACALL TX
MOV A,DIGIT1
ADD A,#48
ACALL TX
MOV A,#10
ACALL TX
MOV A,#13
ACALL TX
RET
Code language: CSS (css)
The TRANS_DATA
subroutine converts the counter digits to ASCII and transmits them serially.
TX:
JNB TI,$
CLR TI
MOV SBUF,A
RET
The TX
subroutine waits for the transmit interrupt flag (TI) to clear and then loads the accumulator (A) into the serial buffer (SBUF) for transmission.
Conclusion
This 8051 assembly code example demonstrates a simple frequency counter. It counts the number of pulses within a second and transmits the result serially. Understanding each part of the code helps in grasping the functionality of the 8051 microcontroller and assembly programming.
I hope you find this explanation helpful. Keep experimenting and learning. Happy coding!
One reply on “8051 Assembly Frequency Counter Example”
I would really like to expand on this code. But when I went to compile it I realised there is a chunk missing. The CLEAR_COUNTER sub-routine. Could you correct the code and repost so that I can go ahead with it?
Thank you