| ??? 01/12/06 17:32 Read: times |
#107175 - Tachometer code with problems |
Hi,
I'm busy making a tachometer for model engines that uses a hall effect sensor with one 'pulse' per revolution. I started out making a system that measured the time for each revolution, however, I have decided to simplify it by counting the number of revolutions in one second instead. I have been trying to avoid asking anyone for help, but unfortunately, I cannot see what I am doing wrong and hope that someone can possibly help me. I am using an AT89S8252. The code uses timer 1 to time 1 second and timer 0 to count the number of revolutions. Only the lower byte of timer 0 is used, as that will give a large enough RPM range. At the moment when I turn my circuit on, it displays 'RPM: 00000_'. I'm not sure why the underscore is there. When I cause a 1-0 transition on P3.4, nothing happens. I have simulated the code on Pinnacle 52 without any of the LCD code included and it seems to be doing what I want, so I have a feeling it has something to do with writing the RPM to the LCD. The '2 BYTE HEX TO 5 DIGITS BCD' section of code came straight from the code library, so there shouldn't be a problem with that. Most of the LCD subroutines came from Craig Steiner's book, so they should also be OK. Finally, before I give the code, I have tried to comment wherever possible, so I hope the code makes sense.
;Code assumes an AT89S8252 with 12MHz crystal
Initial: LJMP Start
ORG 0034h
Start: MOV TMOD, #15h ;Setup timer 0 and timer 1
SETB EA ;Enable interrupts
SETB ET1 ;Enable timer 1 interrupt
EN EQU P3.5
RW EQU P3.6
RS EQU P3.7
DATA EQU P2
TCOUNT EQU 40h ;This is an address in IRAM
ALARM EQU 00h ;This is an address of BIT memory
INIT_LCD: MOV A, #38h ;Setting up LCD
LCALL LCD_COMMAND ;Setting up LCD
MOV A, #0Eh ;Setting up LCD
LCALL LCD_COMMAND ;Setting up LCD
MOV A, #06h ;Setting up LCD
LCALL LCD_COMMAND ;Setting up LCD
LCALL CLEAR_LCD ;Clear LCD
MOV A, #'R' ;Write 'R' to LCD
LCALL LCD_WRITE
MOV A, #'P' ;Write 'P' to LCD
LCALL LCD_WRITE
MOV A, #'M' ;Write 'M' to LCD
LCALL LCD_WRITE
MOV A, #':' ;Write ':' to LCD
LCALL LCD_WRITE
Mainloop:
MOV TL0, #00h ;Set timer 0 to #00h initially
MOV TH1,#03Ch ;Initialize TH1 to overflow every .05 seconds
MOV TL1,#0B0h ;Initialize TL1 to overflow every .05 seconds
MOV TCOUNT,#20 ;Set TCOUNT to 20 to wait for 1 second
SETB TR1 ;Turn timer 1 on
JNB ALARM,$ ;Cycle until ALARM is set (1 second later)
LCALL RPM_CALC
CLR TR1 ;Stop timer 1
CLR ALARM ;Clear ALARM bit
; Writing RPM to the LCD
MOV A, #85h ;Move cursor on LCD
LCALL LCD_COMMAND
MOV A, 74h ;Move highest byte of decimal RPM to accumulator
ADD A, #30h ;Add #30h to convert to correct ASCII character
LCALL LCD_WRITE ;Write to LCD
MOV A, 75h ;Move 2nd highest byte of decimal RPM to accumulator
ADD A, #30h ;Add #30h to convert to correct ASCII character
LCALL LCD_WRITE ;Write to LCD
MOV A, 76h ;Move 3rd highest byte of decimal RPM to accumulator
ADD A, #30h ;Add #30h to convert to correct ASCII character
LCALL LCD_WRITE ;Write to LCD
MOV A, 77h ;Move 4th highest byte of decimal RPM to accumulator
ADD A, #30h ;Add #30h to convert to correct ASCII character
LCALL LCD_WRITE ;Write to LCD
MOV A, 78h ;Move 5th highest byte of decimal RPM to accumulator
ADD A, #30h ;Add #30h to convert to correct ASCII character
LCALL LCD_WRITE ;Write to LCD
LJMP Mainloop ;Repeat the loop
;************
;*Interrupts*
;************
ORG 001Bh ;Timer 1 interrupt
MOV TL1,#0B0h ;Set TL1 to 0B0h
MOV TH1,#03Ch ;Set TH1 to 3Ch
DJNZ TCOUNT,T1_EXIT ;Decrement TCOUNT, if not zero exit interrupt
SETB ALARM ;Set ALARM to indicate the preset time has passed
T1_EXIT:
RETI ;Return from the interrupt
;*************
;*Subroutines*
;*************
ORG 0FAh
RPM_CALC:
MOV A, #03Ch ;Set accumulator to 60 decimal
MOV B, TL0 ;Store the low byte of timer 0 in the B register
MUL AB ;Multiply A and B to determine RPM
;**************************************************
;* START OF 2 BYTE HEX TO 5 DIGITS BCD *
;**************************************************
MOV R1, A ;Store low byte of RPM in R1
MOV R2, B ;Store high byte of RPM in R2
MOV R5,#0
MOV R6,#0
MOV R7,#0
MOV A,R1
MOV B,#10
DIV AB
MOV R3,B ; Lower byte, in R1, is transformed into 2 decade digits,
MOV R4,A ; it's OK that the higher one can be greater than 9
MOV A,R2 ; Higher byte is in R2
JZ SPRING ; Spring over if 0
MOV B,#10
DIV AB
MOV R5,B ; Same as for lower byte
MOV R6,A
; Value in R5 is 256 times higher than value standing in R3, R4. Mply R5 with 6,
; add to R3, mply R5 with 5, add to R4, mply R5 with 2 and replace itself in R5
MOV R0,#05 ; Point to R5
ACALL TRANSF ; Transform R5 to 3 lower positions
INC R0 ; Repeat from R6, now all registers are 1 higher
ACALL TRANSF ; Transform R6 to 3 higher positions
SPRING: MOV R0,#03 ; Point to lowest digit
; Adjust to decimal, everything higher than 9 should be, as 1 tenth, added to higher.
; Starting from the lowest digit, divide with 10, keep the rest, and add the 1/10th to
; first higher place (eg. 145, leave 5 and add 14 to the next higher)
ACALL DECADJ
LJMP END_HEX
TRANSF: MOV A,@R0
MOV B,#6
MUL AB
DEC R0
DEC R0
ADD A,@R0
MOV @R0,A
INC R0
INC R0
MOV A,@R0
MOV B,#5
MUL AB
DEC R0
ADD A,@R0
MOV @R0,A
INC R0
MOV A,@R0
RL A ; Mply with 2
MOV @R0,A
RET
DECADJ: MOV A,@R0
DECLOP: MOV B,#10
DIV AB
MOV @R0,B
INC R0
ADD A,@R0
MOV @R0,A
CJNE R0,#7,DECLOP
RET
END_HEX: MOV 74h, R7
MOV 75h, R6
MOV 76h, R5
MOV 77h, R4
MOV 78h, R3
;**************************************************
;* END OF 2 BYTE HEX TO 5 DIGITS BCD *
;**************************************************
RET
LCD_COMMAND: CLR RS
CLR RW
MOV DATA, A
SETB EN
NOP
NOP
NOP
NOP
CLR EN
LCALL WAIT_LCD
RET
WAIT_LCD: MOV R1, #27h ;Store #39 decimal in R1
TOP: MOV R0, #00h ;Store #00h in R0
WAIT_LCD1: CLR RS
SETB RW
MOV DATA, #0FFh
SETB EN
MOV A, DATA
LJMP TEST
CONT: JB ACC.7, WAIT_LCD1
LJMP MOV
TEST: DJNZ R0, CONT ;If R0 not zero then go to CONT
DJNZ R1, TOP ;If R1 not zero then go to TOP
MOV: CLR EN
CLR RW
RET
;WAIT_LCD will only repeat 9984 times then continue
CLEAR_LCD: MOV A, #01h
LCALL LCD_COMMAND
RET
LCD_WRITE: SETB RS
CLR RW
MOV DATA, A
SETB EN
NOP
NOP
NOP
NOP
CLR EN
LCALL WAIT_LCD
RET
END
I hope what I have said is clear and understandable. Thanks Warren |



