Tutorial Microcontroller 8051
 
 
 
 
 
     

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
Best Link

 

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