;*************************************************************** ;Simple frequency counter for Infinion 80c515 ;designed for 12 MHz Xtals ;this code can be addapted to all x52 cores which support ;a 16 bit timer in autoreload mode and a 16 bit counter ;max frequency @ 12 MHz is 500 kHz (6 Digits resolution) ;GateTime is 1 s ;*************************************************************** ;*************************************************************** ;V0.1 Notes ;*************************************************************** ;This example works for 80c535 only ;frequency must be connected at T0 Pin ;there is a error which comes from irq processing time ;this error will increase at higher frequencies ;Simulation shows 50001 Hz at 50000 Hz ;this error can be corrected by the outputfunction ;This is because the last reload should be a few clocks ;shorter to compensate the exec Time ;*************************************************************** ;V0.2 notes ;*************************************************************** ;using a reload value of -49999 instead of -500000 ;shows much better results, this was a bug in V0.1 :-) ;Simulation now shows 499.999 kHz at 500.000 kHz ;added a simple Outputfunktion which actually ;fills a buffer with frequency as HexAscii ;*************************************************************** ;toDo List ;*************************************************************** ;support for generic x52 ;support for decimal output ;support for LCD or RS232 output ;support for different crystals ;support for 10 s GateTime $NOMOD51 ; disable predefined 8051 registers $DEBUG ; $INCLUDE(reg515.inc) ; ;this is for memory Placement Prog equ 0000h ;Starting address for the program BitVar equ 0 ;where the Bitsegment starts DataVar equ 024h ;were the Data Segment starts ;some Constants T0_MASK equ 0F0h T1_MASK equ 00Fh ;Symbol definitions used in "main" to control the LCD display. ;not used at all LCD_CLR equ 01AH ;clear LCD command LCD_LF equ 0AH ;LCD line feed (next line) LCD_CR equ 0DH ;LCD carriage return ;some port definitions to make the code more readable RAM_A16 Bit P5.0 EEP_ENA Bit P5.2 bMode Bit P5.3 ;Check this PortPin to read Mode of op ;Place for data vars ;************************************************************** DSEG at DataVar ;start at DataSeg GateTime: DS 1 ;the GateOVCounter OverFlow: DS 1 ; frequency: DS 4 ;actually a UINT32 Value bufindex: DS 1 ; outbuffer: DS 16 T0Vect: DS 2 ;for saving the actual Irq Vect T2Vect: DS 2 ; STACK: DS 1 ;stack starts here ;************************************************************** BSEG at BitVar ;place first bit here bReady: dBit 1 ;1: ready for output ;Code starts here ;***************************************************************** CSEG at Prog ;opens the code segment ORG Prog + 0 LJMP Init ;should be placed here CSEG at PROG +0Bh ;Timer 0 overflow interrupt PUSH T0Vect ;Attention this is very tricky PUSH T0Vect+1 RET ;ret starts the IRQ CSEG at PROG+02Bh ;Timer 2 overflow interrupt PUSH T2Vect ;both Functions need 6 clocks PUSH T2Vect+1 ;to start the IRQ RET CSEG at PROG +100h Init: CLR EAL ; SETB RAM_A16 ;Make bit A16 of 128K Ram "high". ; CLR EEP_ENA ;Disable EEPROM. ; CLR P5.1 MOV SP,#STACK-1 ;init the stack V0.1 STACK-1 ;since we have a stack now Rest should be placed in Sub routines Main: ; CALL INIT_LCD ;make all neccesarry LCD Inits ; JB bMode,Main1 ;0 Frequ Mode 1 Period Mode CALL InitIrqVectorsFreq ;Init Freq Irq Vectors CALL InitT0Freq ;T0 to Timer Frequency Mode Call InitT2Freq ;T2 to Counter Mode SJMP Main2 Main1: ; CALL InitIrqVectorsPeriod ; CALL InitT0Period ; CALL InitT2Period Main2: CLR bReady SETB TR0 ;both Timers are runing SETB T2I0 SETB EAL MainLoop: JNB bReady,$ ;wait for Result CALL HandleFreqOutput JMP MainLoop ;DispalyHandler when executing Frequency HandleFreqOutput: CLR A MOV TL0,A MOV TH0,A ;clear the counter MOV Overflow,A MOV GateTime,#20 MOV TL2, # Low (-49999) ;V0.2 new ReloadValue -49999 MOV TH2, # High(-49999) SETB T2I0 SETB TR0 ;restart both Timers CLR bReady ;now you have 1 s to format the output as you want ;you will need some 32 Bit Division Functions ;here a short example for doing hex out to a buffer MOV bufindex,#OutBuffer CALL BufHexOut RET ;***************************************************************************** ;subroutines InitT0Freq: MOV A, TMOD ;initialize Timer 0 to Counter mode ANL A, # T0_MASK ;change only T0 ORL A, # 5 ;Mode 1 16 Bit Counter MOV TMOD,A CLR A MOV TL0, A MOV TH0, A ;Timer0 to zero SETB ET0 ;allow T0 Irq RET InitT2Freq: MOV GateTime,# 20 MOV T2CON,#00010000b ;0001 0000 MOV CRCL, # Low (-49999) ;0xAF; // 50 ms Reload 3CAF = -50000 MOV CRCH, # High(-49999) ;0x3C; MOV TL2, # Low (-49999) ;V0.2 new ReloadValue -49999 MOV TH2, # High(-49999) SETB ET2 ;Interupt Timer 2 enable ; MOV IP, # 20h ;T2 (GateTime) high priority this should be checked RET ;for 80c535 ;******************************************************************************* ;IRQ Functions for frequency measurement only InitIrqVectorsFreq: MOV T0Vect+0,# Low (T0FreqIrq) ;T0 for Frequ Counter Mode MOV T0Vect+1,# High(T0FreqIrq) MOV T2Vect+0,# Low (T2FreqIrq) ;T2 for Frequ Counter Mode MOV T2Vect+1,# High(T2FreqIrq) RET T0FreqIrq: INC OverFlow ;count the overflows RETI T2FreqIrq: PUSH PSW PUSH ACC DEC GateTime MOV A,GateTime JNZ T2FreqIrq1 CLR TR0 ;stop counter CLR T2I0 ;stop timer we have the freq SETB bReady ;indicate valid freq value MOV frequency+0, #0 ;MSB always zero MOV Frequency+1, Overflow ;MSB-1 overflow MOV frequency+2, TH0 ;MSB-2 MOV frequency+3, TL0 ;LSB T2FreqIrq1: CLR TF2 ;clear always the IRQ Flag POP ACC POP PSW RETI ;example for doing nothing at IRQs NoVectors: MOV T0Vect+0,# Low (DoNothingIrq) ; MOV T0Vect+1,# High(DoNothingIrq) MOV T2Vect+0,# Low (DoNothingIrq) ; MOV T2Vect+1,# High(DoNothingIrq) RET DoNothingIrq: RETI ;V0.2 ;some example Output Functions ;sends 'f=0xxxxxh Hz' to OutBuffer BufHexOut: MOV A,#'f' CALL BufWriteChar MOV A,#'=' CALL BufWriteChar MOV A,frequency+1 ;LSB+2 CALL BufWrite2Digits MOV A,frequency+2 ;Lsb +1 CALL BufWrite2Digits MOV A,frequency+3 ;LSB CALL BufWrite2Digits MOV A,#'h' CALL BufWriteChar MOV A,#' ' CALL BufWriteChar MOV A,#'H' CALL BufWriteChar MOV A,#'z' CALL BufWriteChar MOV A,#0 ;end of buffer CALL BufWriteChar RET ;sends ACC as 2 Hex Digits to Buffer BufWrite2Digits: PUSH ACC SWAP A CALL Bin2Hex CALL BufWriteChar POP ACC CALL Bin2Hex ; CALL BufWriteChar ; RET ;Buffer Output Function BufWriteChar: ; PUSH AR0 MOV R0,bufindex MOV @R0,A INC R0 MOV bufindex,R0 ; POP AR0 RET ;Return Ascii Equivalent of ACC 0..3 Bin2Hex: ; PUSH DPH ; PUSH DPL MOV DPTR, # AsciiTab ANL A,# 0Fh MOVC A,@A+DPTR ; POP DPL ; POP DPH RET AsciiTab: DB '0' DB '1' DB '2' DB '3' DB '4' DB '5' DB '6' DB '7' DB '8' DB '9' DB 'A' DB 'B' DB 'C' DB 'D' DB 'E' DB 'F' END