|
|
Frequency Counter
8051 Microcontroller
A very useful tool for the budding
electronics engineer, this digital frequency counter / frequency meter
from MyTutorialCafe.com will give you the most bang for the buck. Based
on the 89s51 microcontroller.
A good use of the frequency counter
is to calibrate other equipment. For example a signal generator that
doesn't have its own digital display. The meter will show the exact
frequency being produced by the signal generator.
( Download File : frequency.zip
)

;====================================================
;FREQUENCY COUNTER BASE ON MICROCONTROLLER 89S51
;
;1.This Program is to count frequency from T0, by using mode 1 Counter 16 bit, then ; ; counter will overflow after 65.535d or FFFFh pulse
;2.Counter resets every 1 second that generated by timer 1, configured as timer 16 bit trough
; TF1 interrupt
;3.Every 1 second data will show on LCD Character and data saved on RAM address
; 30h trough 6fh for 30 data
;4.Subrutine SearchMax, used to find the biggest data betwen 30 data that already saved
;
; by: Triwiyanto, S.Si.,MT
; www.mytutorialcafe.com
;======================================================
;
dispclr equ 00000001b
funcset equ 00111000b
entrmod equ 00000110b
dispon equ 00001100b
ones equ 71h
tens equ 72h
hundreds equ 73h
thousands equ 74h
tenthousands equ 75h
Count10 equ 76h
DataCounter_MaxL equ 77h
DataCounter_MaxH equ 78h
DataCounter_nextL equ 79h
DataCounter_nextH equ 7ah
DataRAMCounterL equ 7bh
DataRAMCounterH equ 7ch
DataFlowRateL equ 7dh
DataFlowRateH equ 7eh
NewDataL equ 7fh
NewDataH equ 70h
;
RS bit P3.0
EN bit P3.1
PortLCD equ P0
button bit P2.3
;Ram 30h s/d 4fh
;Ram 50h s/d 6fh
;
;
org 0h
sjmp start
;
org 0bh ; address interrupt for timer0
ljmp Timer_Interupsi0 ; long jump to timer interrupt 0 TF0
;
start: call ResetRAM
call Init_LCD
AgainD:call lcd_demo
jb button,AgainD
jnb button,$
;
setb P2.0; mode no filter TCS230 clr P2.1 ; mode no filter TCS230 clr P2.2 ; output enable TCS230 call init_lcd
call init_interupsi_Timer0
;
call LCD_Flow
Forever:
call DisplayFlowRate
jb button, Forever
jnb button,$
call lcd_Search
call ldelay
call init_lcd
call LCD_maxFLow
Finish:
call DisplayFlowRateMax
call stopcounter
jb button,Finish
jnb button,$
call resetcounter
sjmp start
;
DisplayFlowRate:
mov DataFlowRateL,NewDataL
mov DataFlowRateH,NewDataH
;
call Hex16toBCD
;
mov R3,#086h
call write_inst
mov R3,tenthousands
call write_data
;
mov R3,#087h
call write_inst
mov R3,thousands
call write_data
;
mov R3,#088h
call write_inst
mov R3,hundreds
call write_data
;
mov R3,#089h
call write_inst
mov R3,tens
call write_data
;
mov R3,#08ah
call write_inst
mov R3,ones
call write_data
ret
;
DisplayFlowRateMax:
call SearchingMax
;
mov DataFlowRateL,DataCounter_MaxL
mov DataFlowRateH,DataCounter_MaxH
;
call Hex16toBCD
;
mov R3,#0c6h
call write_inst
mov R3,tenthousands
call write_data
;
mov R3,#0c7h
call write_inst
mov R3,thousands
call write_data
;
mov R3,#0c8h
call write_inst
mov R3,hundreds
call write_data
;
mov R3,#0c9h
call write_inst
mov R3,tens
call write_data
;
mov R3,#0cah
call write_inst
mov R3,ones
call write_data
ret
;
;==========================================================
;Subroutine Hex16toBCD
;===========================================================
;To convert hex 16 bit to 5 digit decimal
;input Data 8 High byte = R1
;input Data 8 Low byte = R2
;
;Output tenthousands = R7
;Output thousands = R6
;Output hundreds = R5
;Output tens = R4
;Output ones = R3
;
;Contoh: 1A2C h ----> 06799 d
;=======================================================
Hex16toBCD:
ANL PSW,#11101111b ; Aktivasi bank 1
MOV R1,DataFlowRateH; MSByte
MOV R2,DataFlowRateL; LSByte
MOV R3,#00D
MOV R4,#00D
MOV R5,#00D
MOV R6,#00D
MOV R7,#00D
MOV B,#10D
MOV A,R2
DIV AB
MOV R3,B ;
MOV B,#10 ; R7,R6,R5,R4,R3
DIV AB
MOV R4,B
MOV R5,A
CJNE R1,#0H,HIGH_BYTE ; CHECK FOR HIGH BYTE
SJMP ENDD
HIGH_BYTE:
MOV A,#6
ADD A,R3
MOV B,#10
DIV AB
MOV R3,B
ADD A,#5
ADD A,R4
MOV B,#10
DIV AB
MOV R4,B
ADD A,#2
ADD A,R5
MOV B,#10
DIV AB
MOV R5,B
CJNE R6,#00D,ADD_IT
SJMP CONTINUE
ADD_IT:
ADD A,R6
CONTINUE:
MOV R6,A
DJNZ R1,HIGH_BYTE
MOV B, #10D
MOV A,R6
DIV AB
MOV R6,B
MOV R7,A
ENDD:
Mov A,R3
Add A,#30h
MOV ones,A
;
Mov A,R4
Add A,#30h
Mov tens,A
;
Mov A,R5
Add A,#30h
Mov hundreds,A
;
Mov A,R6
Add A,#30h
Mov thousands,A
;
Mov A,R7
Add A,#30h
Mov tenthousands,A
ANL PSW,#11100111b ;Aktivasi Bank 0
ret
;============================================================
;Subrutine Timer_Interupsi0
;===================================================
;This subruoutine is to give an interruption and will overflow
;every 0.05 second or 50000 u second.
;and data that loadee is 65.536-50.000=15536 d = ( 3CB0h )
;B0 h loaded to TL1 and data 3C loaded to TH1
;
;Each this subroutine read, pencacah20 will decrement till Pencacah20=0
;this will happen every 20 X 50000 uS = 20 X 0,05s = 1 s,and then
;subrutine updatedata-stopcounter-savedatacounter
;dan resetcounter will call.
;==========================================================
Timer_Interupsi0:
mov tl0,#0B0h
mov th0,#03ch
djnz Count10,EndInterupsi
mov Count10,#20
call UpdateData
call StopCounter
call SaveDataCounter
call ResetCounter
EndInterupsi:
reti
;
;=====================================================
;Subrutine Init_interupsi_timer0
;=====================================================
;This subroutine is used to initiate RAM low byte and RAM high byte
;Initiate mode timer: timer 0 is functioned as timer 16 bit mode 1
;timer 1 is functioned as counter 16 bit mode 1
;Initiate register counter TL0 dan TH0: with data 3CB0h so counter will over
;flow every 0,05 second
;Initiate register counter TL1 dan TH1: with data 0000h so counter
;start rock and roll in start condition 0000
;Initate Timer0 Interrupt
;=====================================================
Init_interupsi_Timer0:
mov DataRamCounterL,#30h
mov DataRAMCounterH,#50h
mov Count10,#20 ;Initiate for counter down 10 x 0.05 = 0.5 second
mov tl0,#0B0h
mov th0,#03ch
mov tl1,#00h
mov th1,#00h
Mov TMOD,#01010001b ;timer0 = as timer 16 bit, timer1 = as counter16 bit
setb ET0 ; Enable timer 0 interruption
Setb EA ; Master Enable All Interuppt
setb TR0 ; start rock and roll timer 0
setb TR1 ; start rock and roll timer 1
ret
;
UpdateData:
mov NewDataL,TL1
mov NewDataH,TH1
ret
;
StopCounter:
clr TR0
clr TR1
ret
;
;=======================================================
;Subrutine Savedatacounter
;=======================================================
;This subruoutine is to save data to register counter 16 bit TL1 and TH1
;Data register TL1 is saved in RAM with address 30h s/d 4fh
;Data register TH1 is saved in RAM with address 50h s/d 6fh
;this subroutine will be called every timer 0 over flow each 20x 0.05 second = 1second
;after data is saved than address RAM will increment
; ;Index Transfer Data : mov @R0,Data1
; mov Data2,@R0
; Example:
; org 0h
; mov R0,#30h
;start:mov DataADC,P2 ;gets data from ADC
; mov @R0,DataADC ; saves data ADC in addresss 30h
; inc R0 ; increment, R0:= R0 + 1, to save the next data
; call delay ; next address is 31h
; sjmp start
;======================================================
SaveDataCounter:
mov R0,DataRamCounterL
mov @R0,TL1
mov R1,DataRAMCounterH
mov @R1,TH1
inc DataRAMCounterL
inc DataRAMCounterH
mov A,DataRAMCounterL
cjne A,#50h,QuitSDC
mov DataRamCounterL,#30h; Reset to base Address 30h
mov DataRamCounterH,#50h; Reset to base Address 50h
QuitSDC:
ret
;
ResetCounter:
mov TL1,#0
mov TH1,#0
Setb TR0
Setb TR1
ret
; ResetRAM:
mov R1,#64
mov R0,#30h
NextRam:mov @R0,#0
inc R0
djnz R1,NextRam
ret
;
delay: mov R6,#25
del1: mov R5,#255
djnz R5,$
djnz R6,del1
ret
;
ldelay: mov R7,#30
ldel1: call delay
djnz R7,ldel1
ret
;==========================================================
; Subrutine SearchingMax ( Oleh: Triwiyanto )
;==========================================================
;This subroutine is to search data 16 bit betwen 30 data ;with metode, to compare data betwen now and next data ;RAM have capacity ony 1 byte so low byte will be saved to 30h .. 40h
;and high byte will be saved on 50h..61h
;by using the algorith from high programmming language then :
;===========================================================
;DataMax:=DataNext[0]
;for i:=1 to 30 do
; begin
; if DataNext[i] > DataMax then DataMax := DataNext[i]
; end
;=======================================================
;How to detect if a data is bigger then others, is ; by using instruction SUBB A,Data and JNC Label
; for example A=19, Data=20 then C = 1
; A=21, Data=20 then C = 0
;=======================================================
SearchingMax:
mov R7,#30 ;number address ram is 2 x 30 address
mov R0,#30h
mov R1,#50h
mov DataCounter_MaxL,@R0
mov DataCounter_MaxH,@R1
NextData:
inc R0
inc R1
mov DataCounter_NextL,@R0
mov DataCounter_NextH,@R1
;
mov A,DataCounter_NextL
clr C
subb A,DataCounter_MaxL
mov A,DataCounter_NextH
subb A,DataCounter_MaxH
;
jnc SaveDataCounterMax
djnz R7,NextData
Sjmp QuitS
SaveDataCounterMax:
mov DataCounter_MaxL,DataCounter_NextL
mov DataCounter_MaxH,DataCounter_NextH
djnz R7,NextData
QuitS: ret
;
init_lcd:
mov R3,#dispclr
acall write_inst
mov R3,#funcset
acall write_inst
mov R3,#dispon
acall write_inst
mov R3,#entrmod
acall write_inst
ret
;
Write_inst:
Clr RS ; mode write instruction
Mov PortLCD,R3 ; D7 s/d D0 = P0 = R1
Setb EN ; EN = 1 = Enable data
Acall delay ; calldelay time
Clr EN ; EN = 0
ret
;
Write_data:
Setb RS ; mode write instruction
Mov PortLCD,R3 ; D7 s/d D0 = P0 = R1
Setb EN ; EN = 1
Acall delay ; call delay time
Clr EN ; EN = 0 ret
;
LCD_Demo:
mov dptr,#tulisDemo; DPTR = [ tulisan1 ]
mov r7,#16 ; R3=16,Number character to display
mov r3,#080h ; R1=80h,character position row=1,col=1
acall write_inst ;
Demo: clr a ; A = 0
movc a,@a+dptr ; A = [A+ DPTR]
mov r3,A ; R1 = A
inc dptr ; DPTR = DPTR +1
acall write_data
djnz r7,Demo ;R3=R3-1,jump to tulis1 if R3 = 0
ret
;
LCD_Flow:
mov dptr,#tulisFlow; DPTR = [ tulisan1 ]
mov r7,#16 ; R3= 16, Number character to display
mov r3,#080h ;R1= 80h,character position row=1, col=1
acall write_inst
Flow: clr a ; A = 0
movc a,@a+dptr ; A = [A+ DPTR]
mov r3,A ; R1 = A
inc dptr ; DPTR = DPTR +1
acall write_data
djnz r7,Flow ; R3 = R3-1,jump to tulis1 if R3=0
ret
;
LCD_Search:
mov dptr,#tulisSearch; DPTR = [ tulisan1 ]
mov r7,#16 ; R3=16,Number character to display
mov r3,#080h ;R1=80h,character position row=1,col=1
acall write_inst ;
Search:clr a ; A = 0
movc a,@a+dptr ; A = [A+ DPTR]
mov r3,A ; R1 = A
inc dptr ; DPTR = DPTR +1
acall write_data
djnz r7,Search ; R3 = R3-1,jump to tulis1 if R3=0
ret
;
LCD_MaxFlow:
mov dptr,#tulisFlow; DPTR = [ tulisan1 ]
mov r7,#16 ;R3=16,Number character to display
mov r3,#0c0h;R1=80h,character position row=1, col=1
acall write_inst
MaxFlow: clr a ; A = 0
movc a,@a+dptr ; A = [A+ DPTR]
mov r3,A ; R1 = A
inc dptr ; DPTR = DPTR +1
acall write_data
djnz r7,MaxFlow ;R3=R3-1,jump to tulis1 if R3=0
ret
;
TulisDemo:
DB 'Spirometer 89s51'
TulisFlow:
DB 'FLowR: ml/s'
TulisSearch:
DB 'Searching...Max '
;
end
BACK
|
|
Lesson 1:
T
o o l
1.1. Programmer
1.2. Edsim
51
1.3. MIDE-51
1.4. ATMEL
ISP
Lesson 2:
Input Output
2.1.LED
2.2.Swicht
2.3.7
Segmen
2.4.LCD
Character
2.5.ADC
2.6.DAC
2.7.Motor
Stepper
2.8.Keypad
Lesson 3:
Timer Counter
3.1.Basic
3.2.Mode
0
3.3.Mode
1
3.4.Mode
2
3.5.Mode
3
Lesson 4:
Serial Comm.
4.1.Basic
4.2.LED
4.3.Rotate
LED
4.2 ADC
4.3.LCD
Lesson 5:
Interuption
5.1.Basic
5.2.Timer
5.2.External
|