| ??? 11/15/02 14:18 Read: times |
#32570 - RE: help - question on digital frequen |
Steve, below is the code. Some of the code is redundant at the moment but when I get over this stumbling block I will be using the remainder of the code for data logging to a pc using visual basic. You will see the timer interrupt code at about line 65 or so that I am using.
Thanks again to you and all that have continued to offer help and support. I really appreciate it. Seamus. $MOD52 ;DIGITAL FREQUENCY CONNECTED TO P2.0 ; ;*************************************** ;* CONSTANT DEFINITIONS * ;*************************************** ;Stack size (initial value of SP register) StackAddr EQU 0E0H ;stack address (equals size) ;HD44780 (LCD Controler) Definitions ClrScr EQU 01H ;clear screen SetDDRam EQU 80H ;set ddram address LCDLineLength EQU 20 ;lcd's line length LCDRowsNum EQU 4 ;lcd's max.row number ;TMRCYCL EQU 12 ;TMR_SEC EQU CRYSTAL/TMRCYCL ; = 921600 ;TWNTYTH EQU TMR_SEC * #.05 ; = 46080 ;RSET_TM EQU 65536-TWNTYTH ; = 19456 RSET_TM EQU 19456 LED EQU P3.4 LCDDATA EQU P0 MINUTES EQU 07DH SECONDS EQU 07Eh TICKS EQU 07Fh ;End of internal RAM DSEG AT 30H LCD_1: DS 20 ;lcd display buffer lcdenable BIT P3.7 ;enable signal for lcd display lcdread BIT P3.6 ;read signal for lcd lcdreg BIT P3.5 ;RS when H switch to command register, when L to data register lcdbusy BIT P0.7 ;data line 7 od lcd, for busy state testing CSEG ;*************************************** ;* INTERRUPT VECTORS * ;*************************************** ORG 0H AJMP InitProc ;reset ORG 3H AJMP IrqExt0 ;int0 ORG 0BH AJMP IrqTmr0 ;timer 0 ORG 13H AJMP IrqExt1 ;int1 ORG 1BH AJMP IrqTmr1 ;timer 1 ORG 23H AJMP IrqSPI ;spi ORG 30H IrqExt0: RETI ;external int0 ;*************************************** ;* TIMER 0 INTERRUPT * ;*************************************** IrqTmr0: PUSH ACC CLR TR0 ;Turn off timer0 as we reset the value MOV TH0,#HIGH RSET_TM ;Set the high byte of the reset value MOV TL0,#LOW RSET_TM ;Set the low byte of the reset value SETB TR0 ;Restart timer0 DJNZ TICKS,EXIT_TMR0 ;Decrement TICKS MOV TICKS,#20 ;Reset TICKS CALL ClearLCD ;;REAL TIME CLOCK CODE CALL RTC ;;FOR TESTING PURPOSES CPL LED ;;SETS UP SOME VARIABLES FOR LCD POSITION MOV R1,#0 ;row no.0 MOV R2,#0 ;column no.0 ;;INCASE WE HAVE NO SIGNAL MOV A,R6 JNZ SIGNAL ;HAS R6 A VALUE? MOV A,R7 JNZ SIGNAL ;IS R7 NOT ZERO MOV DPTR,#NoSignal0 CALL WriteCString JMP EXIT_TMR0 ;EXITS SIGNAL: ;;16-BIT SUBTRACT! -- THIS NEEDS TO BE MADE INTO A FUNCTION ;;HIGH IN->R6,R7 -- LOW IN->R4,R5 -- ANS->R2,R3 ; SETB RS1 ; MOV A,#194 ;Move the low-byte into the accumulator ; CLR C ;Always clear carry before first subtraction ; SUBB A,07h ;Subtract the second low-byte from the accumulator ; MOV R3,A ;Move the answer to the low-byte of the result ; MOV A,#1 ;Move the high-byte into the accumulator ; SUBB A,06h ;Subtract the second high-byte from the accumulator ; MOV R2,A ;Move the answer to the low-byte of the result ; MOV 07H, R3 ; MOV 06H, R2 ; CLR RS1 ;;CONVERT HEX TO ASCII CALL Hex3DecConv ;result in r5,6,7 CALL Dec2AsciiConv ;result in lcd_1 (ram memory buffer) MOV R0,#LCD_1 ;r0 contains address of ram buffer ;;MOVE ADDRESS OF LCD_1 5 SPACES TO THE RIGHT ; MOV A,R0 ; ADD A,#5 ; MOV R0,A ;;MANUALLY DISPLAY TEMPERATURE ON LCD! ;;R1->ROW -- R2->COL -- R3 -- ASC ; MOV R3,#43 ; CALL PutCharOnLCD MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD INC R0 MOV A,@R0 MOV R3,A INC R2 CALL PutCharOnLCD ; INC R0 ; ; MOV A,@R0 ; MOV R3,A ; INC R2 ; CALL PutCharOnLCD ; MOV R3,#46 ; INC R2 ; CALL PutCharOnLCD ; INC R0 ; MOV A,@R0 ; MOV R3,A ; INC R2 ; cALL PutCharOnLCD ;' INC R2 ;' MOV DPTR,#Degrees ;' CALL WriteCString ; MOV R3,#0 ; INC R2 ; CALL PutCharOnLCD ; MOV R3,#'C' ; INC R2 ; CALL PutCharOnLCD ;;INCASE OF NO SIGNAL, THIS WILL RESET VALUES MOV R5,#0 MOV R6,#0 MOV R7,#0 EXIT_TMR0: POP ACC RETI ;Returns! ;*************************************** ;* OTHER INTERRUPTS * ;*************************************** ;external int1 IrqExt1: RETI ;timer 1 interrupt IrqTmr1: RETI ;spi interrupt IrqSPI: RETI ;*************************************** ;* MAIN PROGRAM CODE * ;*************************************** InitProc: MOV SP,#StackAddr ;stack pointer setting CALL InitLCD ;lcd init - 8 bit interface ; CALL DefChars ;;TIMER STUFF! MOV TH0,#HIGH RSET_TM ;Initialize timer high-byte MOV TL0,#LOW RSET_TM ;Initialize timer low-byte MOV TMOD,#21h ;Sets up Timer0 for normal use, timer1 for baud MOV TCON,#01h MOV TH1,#0FDh ;sets for 9600 baud MOV SCON,#50h ;sets sm1 only SETB TR1 ;Off goes Timer1 SETB TR0 ;Off goes Timer0 ;;INTERRUPT STUFF! MOV TICKS,#60 ;Ticks from 60 down for three Seconds SETB EA ;Initialize interrupts SETB ET0 ;Initialize Timer 1 interrupt MOV 0Fh,#0 ;R7 BANK 1 - I FORGET WHY I DID THIS. MOV R5,#0 MOV R6,#0 MOV R7,#0 MOV SECONDS,#0 MOV MINUTES,#0 ;;SOME COPYLEFT INFORMATION MOV R1,#0 ;row no.0 MOV R2,#0 ;column no.0 MOV DPTR,#CopyLeft0 CALL WriteCString MOV R1,#1 ;row no.1 MOV R2,#0 ;column no.0 MOV DPTR,#CopyLeft1 CALL WriteCString CLR P2.0 DETECT: JNB P2.0,$ MOV TH2,#0 MOV TL2,#0 SETB TR2 JB P2.0,$ CLR TR2 MOV R6,TH2 MOV R7,TL2 MOV R5,#0 SJMP DETECT ;*************************************** ;* REAL TIME CLOCK CODE * ;*************************************** RTC: INC SECONDS MOV A,SECONDS ;Move the seconds variable into the accumulator CJNE A,#60,EXIT_RTC MOV SECONDS,#0 INC MINUTES EXIT_RTC: SETB RS1 ;as not to disturb other registers ; MOV R4,0 ;reset them just in case ; MOV R5,0 ; MOV R6,0 MOV R7,SECONDS CALL Hex3DecConv CALL Dec2AsciiConv ;result in lcd_1 (ram memory buffer) ;;MOVE ADDRESS OF LCD_1 6 SPACES TO THE RIGHT MOV R0,#LCD_1 ;r0 contains address of ram buffer MOV A,R0 ADD A,#6 MOV R0,A ;;SET UP LCD POSITION AND WRITE SECONDS, ':', AND MINUTES MOV R1,#1 MOV R2,#14 CALL WriteAString MOV R2,#13 MOV R3,#58 CALL PutCharOnLCD ; MOV R4,0 ; MOV R5,0 ; MOV R6,0 MOV R7,MINUTES CALL Hex3DecConv CALL Dec2AsciiConv ;result in lcd_1 (ram memory buffer) MOV R0,#LCD_1 ;r0 contains address of ram buffer MOV A,R0 ADD A,#6 MOV R0,A MOV R1,#1 MOV R2,#11 CALL WriteAString CLR RS1 RET ;*************************************** ;* LIBRARY FUNCTIONS/CODE * ;*************************************** ;Out data to status control register (of LCD) ;status control register is using to input control codes for lcd controller OutStatRegLCD: CLR lcdreg ;choose status register CLR lcdread ;& write mode NOP SETB lcdenable MOV P0,A ;move acc.content to P2 CLR lcdenable ;data latched by enable signal PUSH ACC CALL CheckBusyFlag POP ACC RET ;Display char at cursor position ;this routine outputs char contained in acc. to video ram of lcd OutLCD: SETB lcdreg ;choose data register CLR lcdread ;& write mode NOP SETB lcdenable MOV P0,A ;move acc.content to P2 CLR lcdenable ;data latched by enable signal PUSH ACC CALL CheckBusyFlag POP ACC RET ;Delay instead of busy line checking ;if you want, you can check the value of P0.7 (d7 of lcd) ;logic H on this line is for BUSY state of lcd controller CheckBusyFlag: SETB lcdenable CLR lcdreg SETB lcdread MOV LCDDATA,#0FFh MOV A,LCDDATA JB ACC.7,CheckBusyFlag CLR lcdenable CLR lcdread RET ;Initializing of lcd (8 bitów) InitLCD: CLR lcdreg CLR lcdread CLR lcdenable SETB lcdenable ;enable H, then L MOV P0,#30H CLR lcdenable SETB lcdenable ;enable H, then L MOV P0,#30H CLR lcdenable SETB lcdenable ;enable H, then L MOV P0,#30H CLR lcdenable MOV A,#3CH CALL OutStatRegLCD MOV A,#08H CALL OutStatRegLCD MOV A,#01H CALL OutStatRegLCD MOV A,#06H CALL OutStatRegLCD MOV A,#0CH ;lcd "on display" CALL OutStatRegLCD RET ;DefChars: CLR A ;start address of CGRAM ; ORL A,#40H ;cgram definition mode (b6=1) ; CALL OutStatRegLCD ; MOV DPTR,#Char ;start address of definition to dptr ;DefChars1: CLR A ; MOVC A,@A+DPTR ;byte from def.table to acc. ; CJNE A,#0,DefCharsSkip1 ;is it the end of table? ; JMP DefCharsSkip2 ;DefCharsSkip1: CALL OutLCD ;send a byte ; INC DPTR ;next position ; JMP DefChars1 ;DefCharsSkip2: MOV A,#80H ;display mode ; CALL OutStatRegLCD ; RET ;;CLEAR LCD SCREEN ClearLCD: MOV A,#ClrScr ;"clear screen" code CALL OutStatRegLCD RET ;display char on lcd ;R1 <- row number (0 - n) ;R2 <- column number (0 - n) ;R3 <- ascii char code (code of character from rom char.generator of lcd) PutCharOnLCD: PUSH ACC CLR TI MOV SBUF,R3 JNB TI,$ MOV A,R1 ;save r1 MOV 10h,A CJNE R1,#1,PutCharOn1 ;is row=1? MOV A,#64 ;yes,ddram start position=64 JMP PutCharOffset PutCharOn1: CJNE R1,#2,PutCharOn2 ;is row=2? MOV A,#20 ;yes,ddram start pos.=20 JMP PutCharOffset PutCharOn2: CJNE R1,#3,PutCharOn3 ;is row=3? MOV A,#84 ;yes,ddram start pos.=84 AJMP PutCharOffset PutCharOn3: CLR A ;if row=0 then ddram start pos.=0 PutCharOffset: ADD A,R2 ;offset for x coordin. ORL A,#SetDDRam ;set ddram CALL OutStatRegLCD PutCharOffSkip: MOV A,R3 CALL OutLCD ;Out char on screen MOV A,10h ;R1 recall MOV R1,A POP ACC RET ;r1= row number ;r2=column number ;dptr=string address WriteCString: CLR A MOVC A,@A+DPTR ;chacter code from rom to acc. CJNE A,#0,WriteCSkip1 ;is it the end of string RET WriteCSkip1: MOV R3,A CALL PutCharOnLCD ;put char on lcd INC R2 ;next column CJNE R2,#LCDLineLength,CStringSkip2 ;is it max column? MOV R2,#0 ;yes,clear column number INC R1 ;next row CJNE A,#LCDRowsNum,CStringSkip2 ;is max row number? MOV R1,#0 ;yes-clear row number MOV R2,#0 ;&column,start from home pos. CStringSkip2: INC DPTR ;next chacter AJMP WriteCString ;write a string from ram memory ;R0=address of string in ram memory ;R1=row number ;R2=column number WriteAString: MOV A,@R0 ;first char from ram position to acc. CJNE A,#0,WriteASkip1 ;is it the end code? RET WriteASkip1: MOV R3,A MOV A,R0 ;ro save PUSH ACC CALL PutCharOnLCD ;display char. POP ACC ;r0 restore MOV R0,A INC R2 ;next column CJNE R2,#LCDLineLength,AStringSkip2 ;is it max number of column? MOV R2,#0 ;yes,clear column number INC R1 ;and go to the next row CJNE A,#LCDRowsNum,AStringSkip2 ;is it the max number of row? MOV R1,#0 ;yes,clear row number and MOV R2,#0 ;go to the first row AStringSkip2: INC R0 ;increment pointer address JMP WriteAString ;3 bytes of hex number to decimal convertion routine ;number in r5,r6,r7 (r5-msb,..,r7-lsb), result in r4,r5,r6,r7 ;the routine counts, how many times you can subtract the 1000000 from numer, then 100000,10000,1000,100,10,1 ;each counter equals position of decimal number f.e.: ; 1E74 hex - you can subtract 1000 seven (7) times, 100 seven (7) times, 10 nine (9) times and the rest ;is six (6), so your result of conversion is 7796 (equals 1E74) Hex3DecConv: CLR C MOV R4,#0 ;milion counter clear Hex3DecLoop1: MOV A,R7 ;how many time we can subtract 10000000 without carry (989680H) SUBB A,#80H MOV R7,A MOV A,R6 SUBB A,#96H MOV R6,A MOV A,R5 SUBB A,#98H MOV R5,A JC Hex3DecSkip1 INC R4 JMP Hex3DecLoop1 Hex3DecSkip1: MOV A,R4 PUSH ACC ;push counter onto stack MOV A,R7 ADD A,#80H MOV R7,A MOV A,R6 ADDC A,#96H MOV R6,A MOV A,R5 ADDC A,#98H MOV R5,A CLR C MOV R4,#0 Hex3DecLoop2: MOV A,R7 ;how many times we can subtract 1000000 (F4240H) without carry SUBB A,#40H MOV R7,A MOV A,R6 SUBB A,#42H MOV R6,A MOV A,R5 SUBB A,#0FH MOV R5,A JC Hex3DecSkip2 INC R4 JMP Hex3DecLoop2 Hex3DecSkip2: MOV A,R4 PUSH ACC ;push counter onto stack MOV A,R7 ADD A,#40H MOV R7,A MOV A,R6 ADDC A,#42H MOV R6,A MOV A,R5 ADDC A,#0FH MOV R5,A CLR C MOV R4,#0 Hex3DecLoop3: MOV A,R7 ;100000 (186A0H)? SUBB A,#0A0H MOV R7,A MOV A,R6 SUBB A,#86H MOV R6,A MOV A,R5 SUBB A,#01H MOV R5,A JC Hex3DecSkip3 INC R4 JMP Hex3DecLoop3 Hex3DecSkip3: MOV A,R4 PUSH ACC ;onto stack MOV A,R7 ADD A,#0A0H MOV R7,A MOV A,R6 ADDC A,#86H MOV R6,A MOV A,R5 ADDC A,#01H MOV R5,A Hex2DecConv: MOV R4,#0 CLR C Hex2DecLoop1: MOV A,R7 ;10000 (2710h)? SUBB A,#010H MOV R7,A MOV A,R6 SUBB A,#27H MOV R6,A MOV A,R5 SUBB A,#0 MOV R5,A JC Hex2DecSkip1 INC R4 JMP Hex2DecLoop1 Hex2DecSkip1: MOV A,R4 ;onto stack PUSH ACC MOV A,R7 ADD A,#010H MOV R7,A MOV A,R6 ADDC A,#27H MOV R6,A CLR C MOV R4,#0 Hex2DecLoop2: MOV A,R7 ;1000 (3E8h)? SUBB A,#0E8H MOV R7,A MOV A,R6 SUBB A,#03H MOV R6,A JC Hex2DecSkip2 INC R4 JMP Hex2DecLoop2 Hex2DecSkip2: MOV A,R4 ;onto satck PUSH ACC MOV A,R7 ADD A,#0E8H MOV R7,A MOV A,R6 ADDC A,#03H MOV R6,A CLR C MOV R4,#0 Hex2DecLoop3: MOV A,R7 ;100 (64h)? SUBB A,#064H MOV R7,A MOV A,R6 SUBB A,#0H MOV R6,A JC Hex2DecSkip3 INC R4 JMP Hex2DecLoop3 Hex2DecSkip3: MOV A,R4 ;onto stack PUSH ACC MOV A,R7 ADD A,#064H MOV R7,A MOV A,R6 ADDC A,#0H MOV R6,A CLR C MOV R4,#0 Hex2DecLoop4: MOV A,R7 ;10 (0Ah)? SUBB A,#0AH MOV R7,A JC Hex2DecSkip4 INC R4 JMP Hex2DecLoop4 Hex2DecSkip4: MOV A,R4 ;onto stack PUSH ACC ADD A,#0AH ;1 MOV A,R7 ;tens & ones in w R7 ADD A,#0AH MOV R7,A POP ACC SWAP A ADD A,R7 MOV R7,A POP ACC ;thousands & hundreds in R6 MOV R6,A POP ACC SWAP A ADD A,R6 MOV R6,A POP ACC ;tens thousands & hundreds thousands in R5 MOV R5,A POP ACC SWAP A ADD A,R5 MOV R5,A POP ACC ;milins & tens milions in R4 MOV R4,A POP ACC SWAP A ADD A,R4 MOV R4,A RET ;Decimal to ascii conversion ;decimal in r4(msb),r5,r6,r7(lsb),result in ram buffer LCD_1(0..7) ;note:numbers are in correct order after hex2dec conversion routine ;routine takes each of decimal number (4 bits of 8 bit register) and adds it to 0 ascii code character ;f.e. 15 => '0'+1 -> '1' , '0'+5 -> '5' Dec2AsciiConv: MOV A,#LCD_1 MOV R0,A ;pointer to lcd_1 MOV A,R4 ANL A,#0F0H SWAP A ADD A,#'0' MOV @R0,A INC R0 MOV A,R4 ANL A,#0FH ADD A,#'0' MOV @R0,A INC R0 MOV A,R5 ANL A,#0F0H SWAP A ADD A,#'0' MOV @R0,A INC R0 MOV A,R5 ANL A,#0FH ADD A,#'0' MOV @R0,A INC R0 MOV A,R6 ANL A,#0F0H SWAP A ADD A,#'0' MOV @R0,A INC R0 MOV A,R6 ANL A,#0FH ADD A,#'0' MOV @R0,A INC R0 MOV A,R7 ANL A,#0F0H SWAP A ADD A,#'0' MOV @R0,A INC R0 MOV A,R7 ANL A,#0FH ADD A,#'0' MOV @R0,A INC R0 ;put the end of string code MOV A,#0 MOV @R0,A RET ;==================================================================== ; subroutine UDIV16 ; 16-Bit / 16-Bit to 16-Bit Quotient & Remainder Unsigned Divide ; ; input: r1, r0 = Dividend X ; r3, r2 = Divisor Y ; ; output: r1, r0 = quotient Q of division Q = X / Y ; r3, r2 = remainder ; ; alters: acc, B, dpl, dph, r4, r5, r6, r7, flags ;==================================================================== UDIV16: mov r7, #0 ; clear partial remainder mov r6, #0 mov B, #16 ; set loop count div_loop: clr C ; clear carry flag mov a, r0 ; shift the highest bit of rlc a ; the dividend into... mov r0, a mov a, r1 rlc a mov r1, a mov a, r6 ; ... the lowest bit of the rlc a ; partial remainder mov r6, a mov a, r7 rlc a mov r7, a mov a, r6 ; trial subtract divisor clr C ; from partial remainder subb a, r2 mov dpl, a mov a, r7 subb a, r3 mov dph, a cpl C ; complement external borrow jnc div_1 ; update partial remainder if ; borrow mov r7, dph ; update partial remainder mov r6, dpl div_1: mov a, r4 ; shift result bit into partial rlc a ; quotient mov r4, a mov a, r5 rlc a mov r5, a djnz B, div_loop mov a, r5 ; put quotient in r0, and r1 mov r1, a mov a, r4 mov r0, a mov a, r7 ; get remainder, saved before the mov r3, a ; last subtraction mov a, r6 mov r2, a ret ; HIGH INPUT - R6, R7 ; LOW INPUT - R4, R5 ; answer resides in R2, and R3. SUBB16_16: ;Step 1 of the process MOV A,R7 ;Move the low-byte into the accumulator CLR C ;Always clear carry before first subtraction SUBB A,R5 ;Subtract the second low-byte from the accumulator MOV R3,A ;Move the answer to the low-byte of the result ;Step 2 of the process MOV A,R6 ;Move the high-byte into the accumulator SUBB A,R4 ;Subtract the second high-byte from the accumulator MOV R2,A ;Move the answer to the low-byte of the result RET Char: DB 135,133,135,128,128,128,128,128,0 Degrees: DB ' Degrees',0 CopyLeft0: DB 'Final Yr Project',0 CopyLeft1: DB ' Accelerometer ',0 NoSignal0: DB 'Detect No Signal',0 END |



