Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
Thread Tools Display Modes
Old 6th January 2006, 08:06 PM   (permalink)
New Member
marting is on a distinguished road
Default

Pommie/Nigel,

Jast was about to ask that.. I will remove it and leave it running for a while.

Thanks for all the input!
marting is offline   Reply With Quote
Old 7th January 2006, 04:09 AM   (permalink)
akg
Experienced Member
 
akg is on a distinguished road
Default

Quote:
Originally Posted by Nigel Goodwin
Because at the start of the ISR you save the STATUS register (because it must be EXACTLY as it was before the ISR was called), and at the exit you restore the STATUS register. This line changes the STATUS register AFTER it's been restored.
So you can use BCF inside an ISR, but NOT to alter a register that must not be changed.
Thanks Nigel
akg is offline   Reply With Quote
Old 8th May 2008, 08:26 PM   (permalink)
New Member
timoteo_mendes is on a distinguished road
Default delay on time

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''
timoteo_mendes is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes




All times are GMT. The time now is 05:10 PM.


Electronic Circuits  |  Radio Controlled
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.