bianchi77
Advanced Member level 4
- Joined
- Jun 11, 2009
- Messages
- 1,313
- Helped
- 21
- Reputation
- 44
- Reaction score
- 20
- Trophy points
- 1,318
- Location
- California
- Activity points
- 9,442
LedTimer EQU .20 ;10 decimal (for content of the counter to get 100ms)
led_state_1
bcf INTCON,T0IF ;clear the interrupt flag
bsf PORTB, POWERLED ;Turn on LED
movlw LedTimer
movwf COUNT
;counting
check_counter
btfss INTCON,T0IF
goto check_counter
sublw .1
btfss STATUS, Z ;Is the result 0, clear COUNT
goto check_counter ;if false check the COUNTER again
goto next_state ;if true go to this statement
next_state
clrf COUNT ;if false go to this statement
incf LedState,1 ; if 00 increase the state, for the next state
return
check_counter
btfss INTCON,T0IF
goto check_counter
decfsz COUNT,F ; decrement Count and save result in File Count
; skip the next insrtuction if the Count become Zero
goto check_counter ;if false check the COUNTER again
goto next_state ;if true go to this statement
LIST P=16F628A
#include p16f628A.inc
#include globals.inc
extern TimerInt
;-------------------------------------------------------------------------------
BANK0 UDATA
;-------------------------------------------------------------------------------
;..... your variables here ....
LedState RES 1
COUNT RES 1
COUNT1 RES 1
;-------------------------------------------------------------------------------
PROG0 CODE
;-------------------------------------------------------------------------------
LEDManager
GLOBAL LEDManager
LedTimer set .20
movf LedState,w
addwf PCL,f
goto led_state_1
goto led_state_2
;...... your state machine here ......
led_state_1
bcf INTCON,T0IF ;clear the interrupt flag
bsf PORTB, POWERLED ;Turn on LED
movlw LedTimer
movf COUNT,W
check_counter
btfss INTCON,T0IF
goto check_counter
decfsz COUNT,F ; decrement Count and save result in File Count
goto check_counter ;if false check the COUNTER again
goto next_state ;if true go to this statement
next_state
clrf COUNT ;if false go to this statement
incf LedState,1 ; if 00 increase the state, for the next state
return
;led_state_1 end
;led_state_2 begin
led_state_2
bcf INTCON,T0IF ;clear the interrupt flag
bcf PORTB, POWERLED ;Turn off LED
;movf COUNT,W ; load value to W , Status register bit Zero is altered according to value
movlw LedTimer
;call COUNT
movwf COUNT
;movf COUNT1,W
;count for how many interrupts for the next state
check_counter2
;check if COUNT = 2 ? if COUNT equal to 2 then go to the next state! let's jump 16F648A!
;COUNTER is inside working register now, wait until W = 10 then go to next state
;subwf COUNT, W ;give a test
;sublw .1
decf COUNT ;
btfss STATUS, Z ;Is the result 0
goto check_counter2 ;if false go to this statement
goto next_state2 ;if true go to this statement
;counting1 ;decf LedTimer,1 ;if T0IF=true reduce the counter
;btfsc STATUS, Z ; Z bit is set to 1 if W was 00 - skip next instruction if not 00
;COUNT=0
;goto next_state2 ;from btfsc if it's 1, go to next state
;COUNT!=0
;goto counting1 ;from btfsc if it's 0 keep counting
next_state2
clrf COUNT ;if false go to this statement
decf LedState,1 ; if 00 increase the state, for the next state
;btfss INTCON,T0IF
;goto led_state_2
;movlw .10 ; reload value of content working register
;movwf COUNT_TIMER ;load the working register into file register
;btfsc STATUS, Z ; Z bit is set to 1 if W was 00 - skip next instruction if not 00
; if 00 decrease the state, for the next state
;decf COUNT_TIMER ; if not 00 carry on here
;movlw LedTimer ;reload of content of LedTimer
return
;led_state_2 end
return ;LEDManager
;function decrement led timer with counter ==>begin
;if led timer is not zero, then decrement the timer
;how can I call it from timer.asm ?
;goto led_state_1
;function decrement led timer with counter ==>end
END
;
;
; File: timer.ASM
;
list p=16f628A
#include p16f628A.inc
#include globals.inc
;external routines that are needed
;extern LEDManager
;extern led_state_1
;extern led_state_2
;extern led_state
;------------------------------------------------------------------------------
BANK0 UDATA
;------------------------------------------------------------------------------
COUNT RES 1 ;COUNT OF INTERRUPTS
COUNT1 RES 1 ;COUNT FOR 1 SECOND TIMER
;------------------------------------------------------------------------------
PROG0 CODE ; program code section
;------------------------------------------------------------------------------
TimerInt ; Interrupt routine
global TimerInt ; Define as global
;intsOff bcf INTCON, T0IE ;Disable timer interrupts
bsf INTCON, T0IE ;Enable timer interrupts
bcf INTCON, T0IF ;clear interrupt flag
bsf INTCON, GIE ;Enable global interrupt
;-------------- Insert no new code above here ---------------------------------
;*********************************************************************
; 1 ms timer function calls
;*********************************************************************
bcf STATUS, RP0 ;Select Bank 0
bcf STATUS, RP1
;....... 1ms timer counter here.....
; clrf TMR0 ;Clear TMR0 and prescaler
; banksel TMR0
; ;movlw 0xB2 ;Count=B2 ;I get 2.00ms on stopwatch
; movlw .217 ; 0xD9 for getting 1ms
; movwf TMR0
;test toggle LED here...
;bcf PORTB, POWERLED ;Turn off LED
; movf COUNT,W ; load value to W , Status register bit Zero is altered according to value
;counting btfsc STATUS, Z ;Z bit is set to 1 if W was 00 - skip next instruction if not 00
; ;LedTimer=0
; nop ;from btfsc if it's 1, do nothing for a test
; ;LedTimer!=0
; goto counting
;....................................
incf COUNT, f
movlw .10 ;Compare count to 10 decimal
;movlw .2 ;Test with .2 decimal ?
subwf COUNT, W ;Store the result back in
;how can I take this COUNT variable into LedMgr and use it for a loop?
btfss STATUS, C ;Is the result 0, skip if no
;goto led_state_1
;goto LEDManager ;it can be called and simulation is running
goto exittimer
clrf COUNT ;Clear count register
;**********************************************************************
; 10ms timer function calls
;**********************************************************************
;....... 10ms timer counter here.....
;
;test toggle LED off here...
;bcf PORTB, POWERLED ;Turn off LED
;....................................
incf COUNT1, f
;movlw .1 ;Compare count to 1 decimal to give a test!
movlw .10 ;Compare count to 100 decimal
;movlw .50 ;Probe with 50 decimal will give me 1.007388 second on nop Line 94
subwf COUNT1, W ;Store the result back in
btfss STATUS, C ;Is the result 0, skip if no
;goto state1 ?
;check how many COUNT of interrupts
; movlw 0x64 ;load 100 interrupt for a test
; movwf CNT_T0 ;load the LedTimer into file register
;over btfss INTCON,T0IF ;is it true ?
; bcf INTCON,T0IF ;if false clear interrupt flag
; decfsz CNT_T0 ;true
; goto over
goto exittimer
clrf COUNT1
;**********************************************************************
; 100ms timer function calls
;**********************************************************************
;....... 100ms timer counter here.....
;
;call that function in led manager
;test toggle LED on here...
;bsf PORTB, POWERLED ;Turn on LED
;call count100
;goto led_state_2
;nop ;test with stopwatch here, how long do I get ? it's 204.728800ms
;what different does it make ? there'll be a loop on counter ?
;how can I see it, it seems, it's never being called or used when I ran it
;how can I call my state from here ? come on.....
;call led_state
;goto LEDManager ;it can be called and simulation is running but not on the board
;goto led_state_1
;
;
;....................................
exittimer
movlw .217 ;count 14
;goto led_state
;reload the timer value
clrf TMR0 ;Clear TMR0 and prescaler
banksel TMR0
movwf TMR0
;-------------- Insert no new code below here ---------------------------------
bcf INTCON, T0IF ;Clear timer overflow flag
bsf INTCON, T0IE ;Enable interrupts again
return
;----------------------------------------------------------------------------------
;**********************************************************************************
initTimer
Global initTimer
GLOBAL COUNT
GLOBAL COUNT1
clrf COUNT
clrf COUNT1
return
end
LIST P=16F628A
#include p16f628A.inc
#include globals.inc
extern Start,TimerInt
;---------------------------------------------------------------------
shareA UDATA_SHR
;---------------------------------------------------------------------
W_TEMP RES 1
;---------------------------------------------------------------------
BANK0 UDATA
;---------------------------------------------------------------------
PCLATH_TEMP RES 1
STATUS_TEMP RES 1
FSR_TEMP RES 1
;---------------------------------------------------------------------
STARTUP CODE
;---------------------------------------------------------------------
goto Start ; Reset Vector
nop
nop
nop
movwf W_TEMP ; Save State
SWAPF STATUS,W
BANKSEL STATUS_TEMP
movwf STATUS_TEMP ; save STATUS
movf FSR,w
movwf FSR_TEMP ; save FSR
movf PCLATH,w
movwf PCLATH_TEMP
;******************************************************************************
call TimerInt
;******************************************************************************
BANKSEL PCLATH_TEMP
movf PCLATH_TEMP,w
movwf PCLATH
movf FSR_TEMP,w
movwf FSR
swapf STATUS_TEMP,W ; Restore State
movwf STATUS
swapf W_TEMP,F
swapf W_TEMP,W
retfie
;---------------------------------------------------------------------
END
Works for me. I'm using a program called "PowerArchiver" which opens it and displays it without having to unzip it.
Brian.
how can I open the file ?
led_state_1
;call counter
movf COUNT
; Now you can check the Z flag:
btfsc STATUS,Z
goto next ; Counter is zero...
nop ; Counter is non-zero...
bsf PORTB, POWERLED ;Turn on LED
next incf LedState,1 ;increase the state, for the next state
;**********************************************************************
list p=16f628A ; list directive to define processor
#include <p16F628A.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT
; This Config line selects the chips Internal 4mhz oscillator
cblock 0x020 ; user variables
LEDSTATE
COUNT
COUNT1
endc
cblock 0x70 ; variables in Access area for ISR
w_temp ; variable used for context saving
status_temp ; variable used for context saving
endc
;**********************************************************************
ORG 0x000 ; processor reset vector
goto main ; go to beginning of program
ORG 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
btfss INTCON,T0IF ; Make sure it is Timer0 that has Flagged up
goto isrend ; not tmr0 overflow - error - go back
bcf INTCON,T0IF ; Clear it Interrupt Flag
decf COUNT,F ; decrement COUNT
isrend
movf 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
main
clrf PORTA ; Set up all I/O ports as outputs
clrf PORTB
movlw 0x07
movwf CMCON ; turns off Comparator
banksel TRISA
clrf TRISA
clrf TRISB
movlw B'10000111' ; set up timer0 , bits 0-2 prescaler 1:256, bit3 prescaler to Timer 0, PortB Pull ups disabled
movwf OPTION_REG ; Timer 0 is now running !
banksel 0 ; return to bank 0
; the timing formula for TMR0
; oscillator 4meg/ 4 = 1meg processor cycle.
; timer0 prescaler 1,000,000 / 256
;
movlw d'255' ; load count with the delay multiplier
movwf COUNT
tm0start
clrf TMR0 ; clear Timer0 register so it starts counting from 0
bcf INTCON,T0IF ; Clear the TMR0 Flag, When its Full it SETS its Flag to let the system know the count is up.
bsf INTCON,T0IE ; ENABLE TIMER0 INTERRUPT
BSF INTCON,GIE ; ENABLE GLOBAL INTERRUPTS
again movfw COUNT ; run you maion code here, testing for when COUNT is Zero
btfss STATUS,Z
goto again ; not Zero
set_output ;YES is Zero so set you outputs etc. then repaet the countdown routine.
bsf PORTB,0 ; TURN ON LED
LOOP GOTO LOOP
END ; directive 'end of program'
Dear Brian,I spent about 30 minutes trying to work out what your code is supposed to do - and failed miserably. It looks to be the worlds most complicated LED flasher but it has so many strange constructs i gave up trying to work it out.
I can tell you that you used the wrong linker script and you have labels in the wrong columns and a strange mix of 'banksel' and bank setting instructions. I can't see any trace of a valid interrupt routine although you do seem to expect one and it certainly isn't present in the hex file. I'm also confused why you use binary numbers to set register bits when you can use the bit names.
Before going further:
1. please explain exactly what it is supposed to do?
2. what clock speed and configuration are you using?
3. what version of MPLAB are you using? (latest and sadly final version is 8.91)
4. does it have to be relocatable code?
5. what 'tab' setting are you using in the editor, the columns are all over the place.
6. confirm you are actually using a 16F628A (the linker is set to 16F628 - the non 'A' version)
Brian.
;**********************************************************************
list p=16f648A ; list directive to define processor
#include <p16F648A.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
cblock 0x020 ; user variables
LEDSTATE
COUNT
COUNT1
endc
cblock 0x70 ; variables in Access area for ISR
w_temp ; variable used for context saving
status_temp ; variable used for context saving
endc
;**********************************************************************
ORG 0x000 ; processor reset vector
goto main ; go to beginning of program
ORG 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
btfss INTCON,T0IF ; Make sure it is Timer0 that has Flagged up
goto isrend ; not tmr0 overflow - error - go back
bcf INTCON,T0IF ; Clear it Interrupt Flag
decf COUNT,F ; decrement COUNT
isrend
movf 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
main
clrf PORTA ; Set up all I/O ports as outputs
clrf PORTB
movlw 0x07
movwf CMCON ; turns off Comparator
banksel TRISA
clrf TRISA
clrf TRISB
movlw B'10000011' ; set up timer0 , bits 0-2 prescaler 1:16, bit3 prescaler to Timer 0, PortB Pull ups disabled
movwf OPTION_REG ; Timer 0 is now running !
banksel 0 ; return to bank 0
; the timing formula for TMR0
; oscillator 20meg/ 4 = 5meg processor cycle.
; timer0 prescaler 1;16 = 0.0008ms
; x count of .122 = 1ms (almost)
movlw d'122' ; load count with the delay multiplier
movwf COUNT
tm0start
clrf TMR0 ; clear Timer0 register so it starts counting from 0
bcf INTCON,T0IF ; Clear the TMR0 Flag, When its Full it SETS its Flag to let the system know the count is up.
bsf INTCON,T0IE
BSF INTCON,GIE ; ENABLE GLOBAL INTERRUPTS
again movfw COUNT ; run you maion code here, testing for when COUNT is Zero
btfss STATUS,Z
goto again ; not Zero
set_output ;YES is Zero so set you outputs etc. then repaet the countdown routine.
movlw B'00000001' ;toggle PORTB,bit0
xorwf PORTB,F
movlw d'122' ; Re load count with the delay multiplier
movwf COUNT
goto again ;restart countdown loop
END ; directive 'end of program'
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?