I am a new to this list and PIC in general and I have
a newbe question....
Configuration: 16F628A,HS mode, using 16f628A.inc
I wrote code to shift left b'00000001' and place the
newly shifted bit position into LEDS then into PORTB
to update PORTB, all in an ISR. The main code is
polling PORTA,0 to figure out if it has gone low.
Problem:
If I use the customary upon entry to ISR "preserve"
STATUS,W-reg...etc and "restore" on exit of ISR, my
PORTB is all highs. It does not bit shift to PORTB in
my circuit. Even though MPASM debug says PORTB is
shifting to the left correctly. When I remove the
customary "preserve" and "restore" on the ISR, it bit
shifts correctly to PORTB and I can observe it on my
scope and test circuit.
Why does it not work correctly when I "preserve" and
"restore" my ISR? I have a feeling I need to reset
something in order to work but can not figure out what
it is.....please help!!
I am a new to this list and PIC in general and I have
a newbe question....
> I wrote code to shift left b'00000001' and place the
> newly shifted bit position into LEDS then into PORTB
> to update PORTB, all in an ISR. The main code is
> polling PORTA,0 to figure out if it has gone low.
To me, this description is not clear on exactly what
you are trying to accomplish let alone how you are
trying to implement it. Post your code.
> Problem:
> If I use the customary upon entry to ISR "preserve"
> STATUS,W-reg...etc and "restore" on exit of ISR, my
> PORTB is all highs. It does not bit shift to PORTB
[...]
> Why does it not work correctly when I "preserve" and
> "restore" my ISR? I have a feeling I need to reset
> something in order to work but can not figure out what
> it is.....please help!!
I think that most people would not even hazard a guess
as to what might be wrong without seeing the code that
you wrote.
> Why does it not work correctly when I "preserve" and
> "restore" my ISR? I have a feeling I need to reset
> something in order to work but can not figure out what
> it is.....please help!!
- why on earth would you want to use an interrupt for something like
this?
- are you aware of the read-modify-write 'feature'?
Wouter van Ooijen
-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu
> > Why does it not work correctly when I "preserve" and
> > "restore" my ISR? I have a feeling I need to reset
> > something in order to work but can not figure out what
> > it is.....please help!!
>
> - why on earth would you want to use an interrupt for something like
> this?
Maybe part of the answer to *that*, could be found in
this quote from Nick's original post :
>>> I am a new to this list and PIC in general and I have
>>> a newbe question....
> - are you aware of the read-modify-write 'feature'?
Maybe Nick isn't, and you might have seen something in
his description that I missed, but it's not *that* clear to me
that this is a r-m-w problem. In fact, Nick wrote :
>>> I wrote code to shift left b'00000001' and place the
>>> newly shifted bit position into LEDS then into PORTB
>>> to update PORTB...
Which I read as he is using a *shadow* register ("LEDS")
that is first shifted, then written to PORTB. That is actualy
the recomended cure against the r-m-w problem, not ?
Now, with that said, I hope that Nick could post come code
(stripped down to the smallest possible snippet that shows
this "problem"), so we could se what he actualy is doing.
> - why on earth would you want to use an interrupt for something like this?
I'm guessing most Time-Of-Day clock and moving sign s/w would
have something similar, there'll be thousands of other projects that
update displays or LEDs in an ISR
Nick A - you really need to post the code that's not doing what you
wanted it to do. And please don't assume something is irrelevant and
leave it out
Nick A wrote:
> I wrote code to shift left b'00000001' and place the
> newly shifted bit position into LEDS then into PORTB
> to update PORTB, all in an ISR.
Huh?
> Why does it not work correctly when I "preserve" and
> "restore" my ISR?
Because you didn't pay attention to bank settings somewhere?
*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com
Below is what I managed to piece together. I am an RF
EE by discipline, I apologize ahead of time for any
"rules" or "conventions" I may have broken during
coding! Like I said previously the commented out ISR
code allows the effect I am looking for but I would
like to figure out why it works and how to improve on
it.
Basically I want to shift out as quickly as possible
b'00000001' to portb using the quickest interrupt
available. I want in MAIN to look at a change on
porta,0 and load LEDS with a different duty cycle
value like b'00001111' and have that shifted out to
portb. The effect is much brighter LED light from the
8-white LEDS on PortB. I have this code working all in
MAIN on a different code I wrote, I am just trying to
use interrupts to get this version going.
Thanks in advance for looking at this.
Best Regards,
Nick
LIST P=PIC16F628A, R=HEX, C=120, N=50
include "P16f628A.inc"
__FUSES _CP_OFF&_HS_OSC&_WDT_OFF&_LVP_OFF&_MCLRE_OFF
BCF STATUS, RP0 ; Set to
BCF STATUS, RP1 ; .. bank 0
GOTO MAIN ; Reset the part
;
ORG H'0004' ; Interrupt service
routine
INTR_SVC:
; movwf wsave
; swapf STATUS, W
; clrf STATUS
; movwf ssave
; movf PCLATH, W
; movwf psave
;
;
INTR_POLL:
; ... test bit to see if it is set
BTFSS INTCON,T0IF ; Did Timeer0
Overflow?
GOTO ISR_1 ; No it didn't, so
check next thing.
;
; Process Timer 0 Overflow Interrupt
;
BCF INTCON, T0IF ; Clear Timer 0
interrupt
; DECF COUNT,F ; Decrement interrupt
counter
; INCFSZ COUNT,W ; Read it back to
check for overflow
; GOTO ISR_1 ; Nope, keep counting
;
> > - why on earth would you want to use an interrupt
> for something like this?
>
> I'm guessing most Time-Of-Day clock and moving sign
> s/w would
> have something similar, there'll be thousands of
> other projects that
> update displays or LEDs in an ISR
>
> Nick A - you really need to post the code that's not
> doing what you
> wanted it to do. And please don't assume something
> is irrelevant and
> leave it out
>
>
> I apologize ahead of time for any "rules" or "conventions" I may
> have broken during coding! Like I said previously the commented
> out ISR code allows the effect I am looking for but I would like to
> figure out why it works and how to improve on it
Hi Nick, no apologies necessary, and what follows isn't intended
as a bust-your-b**** exercise, just some suggestions that should
make life easier for you. Once you start tidying up I think you'll spot
a few mistakes. Some of the below is opinion on style, but there
are errors in the code that need to be corrected
regards
=====================
o try to standardise your text, and not mix upper and lower
case so much. Maybe l/c for instructions, u/c for registers, all l/c
(like I prefer) or all u/c (like some others prefer)
o same applies to indenting. Nice neat columns are much easier
to follow and spot mistakes in
o use ,f rather than ,1 or omit it altogether. MPLAB uses ,f as
the default
o status,rpx instructions are clutter. Use BANKSEL (or a macro)
o Similarly, try to minimise instruction usage, eg
clrf trisb
rather than
movlw 0x00
movwf TRISB
o when setting bits in a register, itemise. eg (needs fixed font)
movlw b'00001101
; 00 1:1 prescale
; 1 T1 oscillator enabled
; 1 do not synch ext clk input
; 0 internal clk
; 1 timer1 on
movwf T1CON
or use the "&" format, as in the __CONFIG statement
You'll see for the above in your code that you've enabled T1's
external oscillator. Immediately before that section of code you
change to Bank1. T1CON is in Bank0
Note in that previous bit of code only 7 bits have been typed
MOVLW B'0000000' ; Set TMR0 prescaler
MOVWF OPTION_REG ;
o the .inc file has file addresses already, no need to duplicate them
(a) don't see where Timer0 fits into the scheme of things
(b) the ISR_1 label all on its lonesome is a loose end
(c) even if Timer1 IRQs were working properly, there's no
provision been made to clear TMR1IF
> INTR_SVC:
> ; movwf wsave
> ; swapf STATUS, W
> ; clrf STATUS
> ; movwf ssave
> ; movf PCLATH, W
> ; movwf psave
I don't recall ever saving PCLATH. Maybe there's a problem
with the reload on ISR exit, but that's hard to say, given that
something else in the code is possibly/probably faulty
This is OK (apart from the ,1 - my opinion)
rlf LEDS,1
movf LEDS,W
movwf PORTB
but you should CLRC before the rlf to keep LEDS as a rotating
00000001 or 00001111
Thank you Jinx for the break down and suggestions. I
need to increase my dexterity with using the MACRO's
and the syntax. I will go back to the drawing board
and implement your suggestions.
Thanks again for taking the time to explain it
through.
Best Regards,
Nick
__________________________________
Do you Yahoo!?
Make Yahoo! your home page http://www.yahoo.com/r/hs
Nick A wrote:
> Configuration: 16F628A,HS mode, using 16f628A.inc
Since that, is not necessary to declare PORTB neither CMCOM and you may use
F and W to indicate the destination file instead of 1 and 0.
> Problem:
> If I use the customary upon entry to ISR "preserve"
> STATUS,W-reg...etc and "restore" on exit of ISR, my
> PORTB is all highs. It does not bit shift to PORTB in
> my circuit. Even though MPASM debug says PORTB is
> shifting to the left correctly. When I remove the
> customary "preserve" and "restore" on the ISR, it bit
> shifts correctly to PORTB and I can observe it on my
> scope and test circuit.
This routine is OK to me!
Try not to "clrf STATUS" and, if you need, use "clrc" to clear STATUS,C
And remmeber this:
"For example, CLRF STATUS will clear the upper-three
bits and set the Z bit. This leaves the status register
as “000uu1uu” (where u = unchanged)."
> Thanks again for taking the time to explain it
> through.
No prob
Getting back to macros ........
Now, some people have a pathological dislike of macros. I don't,
but you need to use them wisely. Code can go funny because
of some unseen cause or make debugging troublesome. Or, as
they'd say down this way, you'd come a gutser
For example, I use this a lot. It saves typing and is like syntax
on other micros
Where you have to be careful with is skips/branches
btfsc somebit
mov 0x61,temp
The skip is going to jump into the movwf temp, not skip over
both instructions (although the two are combined on one screen
line). This is a fair concern that some (those with a pathological
dislike ;-)) ) have of macros. If you haven't done so already, it's
a good idea to set up a colour scheme in MPLAB for the various
parts of the text in .asm files
Edit/Properties/Text/Choose Colors
I've got used to 18F commands that make life easier if used on
the 16F parts. eg movff
Another point to remember with macros is that they may not be
as economical from a memory usage POV as a CALL
Say you want a 10us pulse/delay, which could be done with NOPs.
If you had a cycle time of 1us, that would mean executing 10 NOPs.
That could be made into a macro
us01 macro
nop
(8 more NOPs)
nop
endm
In your code you would simply type something like
bsf port_bit
us01pulse
bcf port_bit
which is very convenient to type. But not a good idea if space is
getting short and you use that macro a lot. It would be better to
tidy up and use a routine CALL. Obviously the more the macro
size differs from the called routine, the bigger the saving/wastage
bsf port_bit
call delay
bcf port_bit
delay 6 x NOP ; + 2 for CALL, 2 for RETURN = 10
return
The biggest and most convenient time-saver I've found so far
for macros is interfacing with LCD screens, particularly printing
text at a specified position with a one-line statement
Good point about testing for wrap-around Dennis. The 18F
has alternates to the 16F's simple RLF - RLCF and RLNCF.
The first 4 lines of the above routine could be written as a macro
to partially emulate RLNCF (the real 18F RLNCF has no effect
on C)
Looks to me like you need to make sure your carry flag is set
appropriately
before you get here. Your register-saving operations clear the status
register, and I THINK there aren't any instructions between there and
your rotate code that modify the flags any more, so you'll shortly wind
up with your LEDS register all zeros. Or something...
> > - are you aware of the read-modify-write 'feature'?
>
> Maybe Nick isn't, and you might have seen something in
> his description that I missed, but it's not *that* clear to me
> that this is a r-m-w problem. In fact, Nick wrote :
>From his discription I was not sure that he was using a shadow, so I'd
better ask.
Using a shadow register and using this (also) in an interrupt has some
'interesting aspects in its own, like
(main)
movfw SHADOW
-- interrupt occurs right here
XORLW 0x01
movwf SHADOW
(interrupt)
bsf SHADOW, 7
The bit set in SHADOW by the interrupt will be overwritten by the main
....
Wouter van Ooijen
-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu
MOVWF TMP_W ; Copy W to a
temporary register
SWAPF STATUS,W ; Swap Status Nibbles
and move to W (preserves Status)
MOVWF TMP_STATUS ; Copy STATUS to a
temporary register
CLRC
RLF LEDS,F
BTFSC STATUS,C ; Wrap around
BSF LEDS,0
MOVFW LEDS
MOVWF PORTB
; BCF PORTA,0 ; Test LED on porta bit 0
SWAPF TMP_STATUS,W ; Pull Status back
into W
MOVWF STATUS ; Store it in status
(would change Z but overwrites it)
SWAPF TMP_W,F ; Prepare W to be
restored
SWAPF TMP_W,W ; Return it without
changing Z bit in STATUS
BCF INTCON,2 ; clear interrupt flag
RETFIE
Jinx wrote:
> One other little tip - you can assign a name to a pin, eg
>
> #define pushbutton porta,1
>
> which can be used in the code like
>
> btfsc pushbutton
Or you can take this concept to the next level by using the /INBIT and
/OUTBIT directives of my MPASM preprocessor. See http://www.embedinc.com/pic.
*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com
>> I just wanted to thank you Jinx and all of you that
>> helped me out with your suggestions. I got it to work,
>> below is the "new code".
>
> Well done you, and thanks for reporting back
>
> One other little tip - you can assign a name to a pin, eg
>
> #define pushbutton porta,1
>
> which can be used in the code like
>
> btfsc pushbutton
>
> Makes it a lot easier than remembering what all the porta bits are
It also prevents you from checking whether the symbol pushbutton
resolves to what is needed by that opcode. I prefer to do it separately,
like:
; this file reads buttons in its lower 4 bits
Fbuttons equ PORTB
...
movf Fbuttons, w ; read all buttons together!
andlw Mbutmask ; only button bits
xorwf Fold_buttons, w ; changed ? Z=0
btfsc STATUS, Z
goto no_but_change
; there was a change, process it
; #idef WANT_PRESSED
xorwf Fold_buttons, w ; undo xor
movwf Fold_buttons ; store
; #endif
#ifdef WANT_CHANGED
xorwf Fold_buttons, f ; store change, do not undo xor in w
#endif
; for each button that is down (or changed!)
btfsc Fold_buttons, Bleft
goto no_left_but
>> One other little tip - you can assign a name to a pin, eg
>>
>> #define pushbutton porta,1
>>
>> which can be used in the code like
>>
>> btfsc pushbutton
>>
>> Makes it a lot easier than remembering what all the porta bits are
>
>It also prevents you from checking whether the symbol pushbutton
>resolves to what is needed by that opcode. I prefer to do it
>separately, like: ...
Not really. If you really, really need to do that then look at the assembly
list file. If the abstraction is done correctly there is no reason to do so
however.
Perhaps the abstraction is easier done with Olins macros which I have used,
but I cannot see why the method above should make it any harder to
understand.