![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
Pommie/Nigel,
Jast was about to ask that.. I will remove it and leave it running for a while. Thanks for all the input! |
|
|
|
|
|
|
(permalink) | |
|
Quote:
|
||
|
|
|
|
|
(permalink) |
|
hello
I have made same changes to the code that nigel have post. My LCD is in portA But every 4 second it have a delay of 1 second aproximatly... Could anyone explain me why? the code is below: LIST p=16F628 ;tell assembler what chip we are using include "P16F628.inc" ;include the defaults for the chip ERRORLEVEL 0, -302 ;suppress bank selection messages __config 0x0118 ;sets the configuration settings (oscillator type etc.) ;***** VARIABLE DEFINITIONS cblock 0x20 ; define a series of variables. w_temp ; variable used for context saving status_temp ; variable used for context saving Hours ; hours counter Mins ; minutes counter Secs ; seconds counter MSecs ; 10's of millisconds counter count0 ; Interrupt counter flagsecs ; Contains a 0 unless 500 1-ms Timer 2 ; interrupts have been processed. flag10s ; ten second flag flag60s ; sixty second flag HoursA ; alarm hours register MinsA ; alarm minutes register SecsA ; alarm seconds register count ;used in looping routines count1 ;used in delay routine counta ;used in delay routine countb ;used in delay routine tmp1 ;temporary storage tmp2 templcd ;temp store for 4 bit mode templcd2 NumL ;Binary inputs for decimal convert routine NumH TenK ;Decimal outputs from convert routine Thou Hund Tens Ones MaxDigit1 MaxDigit2 endc ORG 0x00 ; processor reset vector clrf PCLATH ; ensure page 0 is used goto main ; go to beginning of program ORG 0x04 ; interrupt vector location movwf w_temp ; save off current W register contents swapf STATUS,W ; move status register into W register clrf STATUS ; select Bank 0 movwf status_temp ; save off contents of STATUS register ; There's no need to save PCLATH since ; we'll stick to Bank 0 of program memory. ; isr code can go here or be located as a call subroutine elsewhere btfsc PIR1,TMR2IF ; If Timer 2 caused the interrupt, handle it. call Timer2 swapf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt ; ********************************************* ; Timer 2 Interrupt handler. ; Timer 2 has overflowed ; Timer2 incf MSecs,F ; increment milli second counter movlw d'100' ; Is MSecs 100 yet? subwf MSecs,W btfss STATUS,Z ; If MSecs is not 100, end ISR. goto EndTimer2Interrupt movlw H'FF' movwf flagsecs ; Reinitialize Secs clrf MSecs incf Secs,F ; increment 10 second counter movlw d'60' ; Is Secs 60 yet? subwf Secs,W btfss STATUS,Z ; If Secs is not 60, end ISR. goto EndTimer2Interrupt movlw H'FF' movwf flag10s ; Reinitialize Secs clrf Secs incf Mins,F ; increment 60 second counter movlw d'60' ; Is Mins 60 yet? subwf Mins,W btfss STATUS,Z ; If Mins is not 60, end ISR. goto EndTimer2Interrupt movlw H'FF' movwf flag60s ; Reinitialize Mins clrf Mins incf Hours,F ; increment hour counter movlw d'24' ; Is Mins 24 yet? subwf Hours,W btfss STATUS,Z ; If Hours is not 24, end ISR. goto EndTimer2Interrupt movlw H'FF' movwf flag60s ; Reinitialize Hours clrf Hours ; reset hours to zero EndTimer2Interrupt bcf PIR1,TMR2IF ; Clear flag and continue. return main ; ************************************************** ********************************* ; START OF CODE to initialize the processor ; The initialization code goes here since we'll end up here shortly after a reset. ; ************************************************** ********************************* SetPorts bsf STATUS, RP0 ;select bank 1 movlw b'00010000' movwf TRISA ;all pins outputs movlw b'00001111' movwf TRISB ;B0-B3 IN B4-B7 Out movlw b'11111000' ; 1:1 TMR0, counter, falling edge RA4. movwf OPTION_REG movlw b'00000000' ; disable interrupts. movwf INTCON movlw b'00000000' ; disable TMR1 overflow interrupt. movwf PIE1 bcf STATUS, RP0 ;select bank 0 movlw b'00000111' movwf CMCON ;turn comparators off clrf PORTA clrf PORTB clrf count0 clrf MSecs clrf Secs clrf Mins clrf Hours clrf flagsecs ; Turn off the flag which, when set, says 500 ms has elapsed. clrf flag10s clrf flag60s movlw 0x01 ;set 1 hour movwf HoursA movlw 0x02 movwf MinsA ;set 2 minute movlw 0x1E ;set 30 seconds movwf SecsA ; ************************************************** ********************************* ; START OF CODE to initialize Timer 2 ; These come next only because it's convenient to group them together, not because ; it's a necessity. ; Set up Timer 2 to generate interrupts every 1 ms. Since we're assuming an instruction ; cycle consumes 1 us, we need to cause an interrupt every 1000 instruction cycles. ; We'll set the prescaler to 4, the PR2 register to 25, and the postscaler to 10. This ; will generate interrupts every 4 x 25 x 10 = 1000 instruction cycles. ; ************************************************** ********************************* clrf TMR2 ; Clear Timer2 register bsf STATUS, RP0 ; Bank1 bsf INTCON,PEIE ; Enable peripheral interrupts clrf PIE1 ; Mask all peripheral interrupts except bsf PIE1,TMR2IE ; the timer 2 interrupts. bcf STATUS, RP0 ; Bank0 clrf PIR1 ; Clear peripheral interrupts Flags movlw B'01001001' ; Set Postscale = 10, Prescale = 4, Timer 2 = off. movwf T2CON bsf STATUS, RP0 ; Bank1 movlw D'250' ; Set the PR2 register for Timer 2 to divide by 250. movwf PR2 bcf STATUS, RP0 ; Bank0 bsf INTCON,GIE ; Global interrupt enable. bsf T2CON,TMR2ON ; Timer2 starts to increment ; ************************************************** ********************************* ; END OF CODE to initialize Timer 2 ; ************************************************** ********************************* call Delay100 ;wait for LCD to settle call LCD_Init ;setup LCD ; ************************************************** ********************************* ; main() ; This is the main program. It does only one thing: check to see if it's time to ; toggle PORTA<togglebit> and do so if it is time. Otherwise it's busily engaged ; in using up all the instruction cycles not required by the interrupt handlers. loop call Check_Keys movf flagsecs, W ; Has the flagsecs been set? btfsc STATUS,Z goto loop ; Not yet. Keep looking. call Check_Alarm ; check alarm every LCD update call LCD_Line1 movlw ' ' call LCD_Char movlw 'H' call LCD_Char movlw 'o' call LCD_Char movlw 'r' call LCD_Char movlw 'a' call LCD_Char movlw ' ' call LCD_Char movf Hours, w movwf NumL call Display movlw ':' call LCD_Char movf Mins, w movwf NumL call Display movlw ':' call LCD_Char movf Secs, w movwf NumL call Display movlw ' ' call LCD_Char call LCD_Line2 movlw 'A' call LCD_Char movlw 'l' call LCD_Char movlw 'a' call LCD_Char movlw 'r' call LCD_Char movlw 'm' call LCD_Char movlw ' ' call LCD_Char movf HoursA, w movwf NumL call Display movlw ':' call LCD_Char movf MinsA, w movwf NumL call Display movlw ':' call LCD_Char movf SecsA, w movwf NumL call Display movlw ' ' call LCD_Char goto loop ; Now wait for the next occurence. ; ************************************************** ********************************* Check_Keys btfss PORTB, 0 goto Clear_Clk btfss PORTB, 1 bcf T2CON,TMR2ON ; stop Timer2 btfss PORTB, 2 bsf T2CON,TMR2ON ; start Timer2 btfss PORTB, 3 goto Edit_Hours return Edit_Hours movlw 0x07 ;set cursor position call LCD_Line2W call LCD_CurOn movlw d'24' movwf MaxDigit1 movlw d'23' movwf MaxDigit2 Butt_Loop btfss PORTB, 1 call Increment btfss PORTB, 2 call Decrement btfsc PORTB, 0 ;exit routine goto Butt_Loop goto Edit_Mins Increment incf HoursA, f ; increment HoursA movf MaxDigit1, w ; Is Hours 24 yet? subwf HoursA,W btfss STATUS,Z ; If Hours is not 24, carry on goto $+3 movlw 0x00 ; else zero hours movwf HoursA movlw 0x06 ; set cursor position call LCD_Line2W ; movf HoursA, w movf HoursA, w movwf NumL call Display movlw 0x07 ; set cursor position call LCD_Line2W call Delay20 return Decrement decf HoursA, f ; increment HoursA movlw d'255' ; Is hours 255 yet? subwf HoursA,W btfss STATUS,Z ; If Hours is not 255, carry on goto $+3 movf MaxDigit2, w ; else hours = 23 movwf HoursA movlw 0x06 ; set cursor position call LCD_Line2W ; movf HoursA, w movf HoursA, w movwf NumL call Display movlw 0x07 ; set cursor position call LCD_Line2W call Delay20 return Edit_Mins ; call Delay20 ;delay for contact bounce btfss PORTB, 0 ;exit routine goto $-1 ;loop until button released movlw 0x0A ;set cursor position call LCD_Line2W call LCD_CurOn movlw d'60' movwf MaxDigit1 movlw d'59' movwf MaxDigit2 Butt_Loop2 btfss PORTB, 1 call IncrementM btfss PORTB, 2 call DecrementM btfsc PORTB, 0 ;exit routine goto Butt_Loop2 goto Edit_Secs IncrementM incf MinsA, f ; increment MinssA movf MaxDigit1, w ; Is MinsA 60 yet? subwf MinsA,W btfss STATUS,Z ; If MinsA is not 60, carry on goto $+3 movlw 0x00 ; else zero MinsA movwf MinsA movlw 0x09 ; set cursor position call LCD_Line2W movf MinsA, w ; movf MinsA, w movwf NumL call Display movlw 0x0A ; set cursor position call LCD_Line2W call Delay20 return DecrementM decf MinsA, f ; increment MinsA movlw d'255' ; Is MinsA 255 yet? subwf MinsA,W btfss STATUS,Z ; If MinsA is not 255, carry on goto $+3 movf MaxDigit2, w ; else MinsA = 59 movwf MinsA movlw 0x09 ; set cursor position call LCD_Line2W movf MinsA, w movf MinsA, w movwf NumL call Display movlw 0x0A ; set cursor position call LCD_Line2W call Delay20 return Edit_Secs ; call Delay255 ;delay for contact bounce btfss PORTB, 0 ;exit routine goto $-1 ;loop until button released movlw 0x0D ;set cursor position call LCD_Line2W call LCD_CurOn movlw d'60' movwf MaxDigit1 movlw d'59' movwf MaxDigit2 Butt_Loop3 btfss PORTB, 1 call IncrementS btfss PORTB, 2 call DecrementS btfsc PORTB, 0 ;exit routine goto Butt_Loop3 call Delay255 ;delay for contact bounce btfss PORTB, 0 ;exit routine goto $-1 ;loop until button released return IncrementS incf SecsA, f ; increment SecsA movf MaxDigit1, w ; Is SecsA 60 yet? subwf SecsA,W btfss STATUS,Z ; If SecsA is not 60, carry on goto $+3 movlw 0x00 ; else zero SecsA movwf SecsA movlw 0x0C ; set cursor position call LCD_Line2W movf SecsA, w movf SecsA, w movwf NumL call Display movlw 0x0D ; set cursor position call LCD_Line2W call Delay20 return DecrementS decf SecsA, f ; decrement SecsA movlw d'255' ; Is SecsA 255 yet? subwf SecsA,W btfss STATUS,Z ; If SecsA is not 255, carry on goto $+3 movf MaxDigit2, w ; else SecsA = 59 movwf SecsA movlw 0x0C ; set cursor position call LCD_Line2W movf SecsA, w movf SecsA, w movwf NumL call Display movlw 0x0D ; set cursor position call LCD_Line2W call Delay20 return Clear_Clk bcf T2CON,TMR2ON ; stop Timer2 clrf Hours clrf Mins clrf Secs clrf MSecs clrf count0 clrf flagsecs clrf flag10s clrf flag60s clrf PORTB ; turn off LED B4 bsf T2CON,TMR2ON ; start Timer2 return Check_Alarm movf Hours, w ;check hours subwf HoursA, w btfss STATUS, Z return movf Mins, w ;check minutes subwf MinsA, w btfss STATUS, Z return movf Secs, w ;check seconds subwf SecsA, w btfsc STATUS, Z bsf PORTB, 4 return Display clrf NumH call Convert ;convert to decimal movf Tens, w call LCD_CharD movf Ones, w call LCD_CharD return ;LCD routines ;Initialise LCD LCD_Init movlw 0x20 ;Set 4 bit mode call LCD_Cmd movlw 0x28 ;Set display shift call LCD_Cmd movlw 0x06 ;Set display character mode call LCD_Cmd movlw 0x0d ;Set display on/off and cursor command call LCD_Cmd call LCD_Clr ;clear display retlw 0x00 ; command set routine LCD_Cmd movwf templcd swapf templcd, w ;send upper nibble andlw 0x0f ;clear upper 4 bits of W movwf PORTA bcf PORTA, 6 ;RS line to 0 call Pulse_e ;Pulse the E line high movf templcd, w ;send lower nibble andlw 0x0f ;clear upper 4 bits of W movwf PORTA bcf PORTA, 6 ;RS line to 0 call Pulse_e ;Pulse the E line high call Delay5 retlw 0x00 LCD_CharD addlw 0x30 LCD_Char movwf templcd swapf templcd, w ;send upper nibble andlw 0x0f ;clear upper 4 bits of W movwf PORTA bsf PORTA, 6 ;RS line to 1 call Pulse_e ;Pulse the E line high movf templcd, w ;send lower nibble andlw 0x0f ;clear upper 4 bits of W movwf PORTA bsf PORTA, 6 ;RS line to 1 call Pulse_e ;Pulse the E line high call Delay5 retlw 0x00 LCD_Line1 movlw 0x80 ;move to 1st row, first column call LCD_Cmd retlw 0x00 LCD_Line2 movlw 0xc0 ;move to 2nd row, first column call LCD_Cmd retlw 0x00 LCD_Line1W addlw 0x80 ;move to 1st row, column W call LCD_Cmd retlw 0x00 LCD_Line2W addlw 0xc0 ;move to 2nd row, column W call LCD_Cmd retlw 0x00 LCD_CurOn movlw 0x0d ;Set display on/off and cursor command call LCD_Cmd retlw 0x00 LCD_CurOff movlw 0x0c ;Set display on/off and cursor command call LCD_Cmd retlw 0x00 LCD_Clr movlw 0x01 ;Clear display call LCD_Cmd retlw 0x00 LCD_HEX movwf tmp1 swapf tmp1, w andlw 0x0f call HEX_Table call LCD_Char movf tmp1, w andlw 0x0f call HEX_Table call LCD_Char retlw 0x00 Pulse_e bsf PORTA, 7 nop bcf PORTA, 7 retlw 0x00 HEX_Table addwf PCL, f RETLW 0x30 RETLW 0x31 RETLW 0x32 RETLW 0x33 RETLW 0x34 RETLW 0x35 RETLW 0x36 RETLW 0x37 RETLW 0x38 RETLW 0x39 RETLW 0x41 RETLW 0x42 RETLW 0x43 RETLW 0x44 RETLW 0x45 RETLW 0x46 ;end of LCD routines Delay255 movlw 0xff ;delay 255 mS goto d0 Delay100 movlw d'100' ;delay 100mS goto d0 Delay50 movlw d'50' ;delay 50mS goto d0 Delay20 movlw d'20' ;delay 20mS goto d0 Delay5 movlw 0x05 ;delay 5.000 ms (20 MHz clock) d0 movwf count1 d1 movlw 0xE7 ;delay 1mS movwf counta movlw 0x04 movwf countb Delay_0 decfsz counta, f goto $+2 decfsz countb, f goto Delay_0 decfsz count1 ,f goto d1 retlw 0x00 ;end of LCD routines Convert: ; Takes number in NumH:NumL ; Returns decimal in ; TenK:Thou:Hund:Tens:Ones swapf NumH, w iorlw B'11110000' movwf Thou addwf Thou,f addlw 0XE2 movwf Hund addlw 0X32 movwf Ones movf NumH,w andlw 0X0F addwf Hund,f addwf Hund,f addwf Ones,f addlw 0XE9 movwf Tens addwf Tens,f addwf Tens,f swapf NumL,w andlw 0X0F addwf Tens,f addwf Ones,f rlf Tens,f rlf Ones,f comf Ones,f rlf Ones,f movf NumL,w andlw 0X0F addwf Ones,f rlf Thou,f movlw 0X07 movwf TenK ; At this point, the original number is ; equal to ; TenK*10000+Thou*1000+Hund*100+Tens*10+Ones ; if those entities are regarded as two's ; complement binary. To be precise, all of ; them are negative except TenK. Now the number ; needs to be normalized, but this can all be ; done with simple byte arithmetic. movlw 0X0A ; Ten Lb1: addwf Ones,f decf Tens,f btfss 3,0 goto Lb1 Lb2: addwf Tens,f decf Hund,f btfss 3,0 goto Lb2 Lb3: addwf Hund,f decf Thou,f btfss 3,0 goto Lb3 Lb4: addwf Thou,f decf TenK,f btfss 3,0 goto Lb4 retlw 0x00 END ; directive 'end of program'' |
|
|
|
|