# Messing with Assembler - Help!

Status
Not open for further replies.

#### Omar.M

##### Member
Hello!
I've been trying my hand at Assembler with the PIC16F628A and I have to say it is rather neat!

However, while messing around with my "first program" (of course, trying to blink an LED-- but through interrupts), I am totally stumped. I am sure I made some foolish mistakes, but I can't get the LED to blink! The LED just stays on.

Any help would be greatly appreciated!
Thank you,
-Omar

Code:
									;Test program-- lots of stolen snippets, hehe.
LIST	p=16F628A			;tell assembler what chip we are using
include "P16F628A.inc"		;include the defaults for the chip
__config 0x3D18				;sets the configuration settings

ORG 		0				;the start address in program memory is 0
STATUS		equ	03h			;equates section
TRISB		equ 86h
PORTB 		equ	06h
INTCON		equ	0x0B		;Interrupt register
OPT_REG		equ	0x81		;option register
TMR0		equ	0x01		;timer register

bsf		STATUS,	5			;switch to bank 1
movlw	b'00000000'			;all portb pins will be outputs outputs
movwf	TRISB
movlw	b'00000111'			;Setting prescaler values
movwf	OPT_REG
bcf		STATUS, 5			;back to old bank 0
bsf		INTCON,	7			;GIE - needed to be turned on for interrupts
bsf		INTCON,	5			;TOIE - Enable bit for overflow timer
bcf		INTCON,	2			;Just in case, make sure the overflow flag is off
clrf	TMR0				;clear timer, just in case
movlw	b'11111111'			;set all pins high
movwf	PORTB
goto	Flash

Flash
btfss	INTCON,	2			;test if interrupt occured
goto	Flash				;not yet
Interrupt_Section
btfss	PORTB,1				;check if PORTB is on-- turn it off, else turn it on.
goto	ON_LED
goto	OFF_LED
goto 	Flash
ON_LED
movlw	b'11111111'			;set all pins high
movwf	PORTB				;output
bcf		INTCON,	2			;clear the flag before you leave
clrf	TMR0
bsf		INTCON,	7			;GIE - needed to be turned on for interrupts
bsf		INTCON,	5			;TOIE - Enable bit for overflow timer
goto	Flash
OFF_LED
movlw	b'00000000'			;set all pins low
movwf	PORTB				;output
bcf		INTCON,	2			;clear the flag before you leave
clrf	TMR0
bsf		INTCON,	7			;GIE - needed to be turned on for interrupts
bsf		INTCON,	5			;TOIE - Enable bit for overflow timer
goto	Flash
End

#### blueroomelectronics

##### Well-Known Member
The interrupt vector is at 0x004
Run your code through the MPLAB simulator and you'll see it.

#### House0Fwax

##### Member
Well, I'm no expert, but I don't see any kind of delay between swithing the LED on and switching it off.
Having said that... I've just got back from the pub.
Your code looks terribly complicated for flashing a LED.
What I would suggest is try some tested code and the adapt it to suit your needs, that's how I learnt about PICs. ( not that I know an awful lot about programming them )

#### Omar.M

##### Member
House0Fwax,
I've done PIC stuff through BASIC compilers, but I wanted to mess around with Assembler. This isn't so much about efficiency right now, just trying to see if various things work-- and apparently they don't (heh).

Bill, I tried using that to define what happens during an interrupt, but MPASM gave me an error 118, apparently I was trying to overwrite some previously defined thing.

#### eng1

##### New Member
As you're polling the T0IF flag, don't enable global interrupts. The GIE bit should be cleared and never set.

#### blueroomelectronics

##### Well-Known Member
Try this, it toggles the entire PORTB though, easy enough to fix but I'll let you figure that out
Code:
; flash all PORT B
LIST    p=16F628A        ;tell assembler what chip we are using
include "P16F628A.inc"        ;include the defaults for the chip
__config 0x3D18            ;sets the configuration settings

org     0x000        ; reset vector
goto    Init
;Interrupt_Section
org    0x004        ; interrupt vector
movlw    0xFF
xorwf    PORTB        ; toggle the port
bcf    INTCON, T0IF    ; clear T0IF flag
retfie            ; sets GIE automatically
Init    bsf    STATUS,    RP0    ;B1
movlw    b'00000000'    ; all portb pins will be outputs outputs
movwf    TRISB
movlw    b'00000111'    ; setting prescaler values
movwf    OPTION_REG
bcf    STATUS, RP0    ;B0
clrf    TMR0        ;clear timer
movlw    b'11111111'    ;set all pins high
movwf    PORTB
bsf    INTCON,    GIE    ;GIE - needed to be turned on for interrupts
bsf    INTCON,    T0IE    ;TOIE - Enable bit for overflow timer
goto    \$        ; loop forever (till interrupt)
END

#### Omar.M

##### Member
eng1,
Oh really? I did not know that! Thank you very much-- I'll try it very soon!

Bill, thank you too! That code is perfect-- figured out how to toggle individual pins as well !

Boo-yah!

#### futz

##### Active Member
Since you have this line at the top of your code
Code:
	include	"P16F628A.inc"
you don't need all this stuff
Code:
	STATUS	equ	03h		;equates section
TRISB	equ	86h
PORTB 	equ	06h
INTCON	equ	0x0B		;Interrupt register
OPT_REG	equ	0x81		;option register
TMR0	equ	0x01		;timer register
It's already in the above include.

#### eng1

##### New Member
Omar.M said:
eng1,
Oh really? I did not know that! Thank you very much-- I'll try it very soon!

This version doesn't use interrupts.

Code:
        LIST    p=16F628A            ;tell assembler what chip we are using
include "P16F628A.inc"        ;include the defaults for the chip
__config 0x3D18                ;sets the configuration settings

ORG     0x000                ;the start address in program memory is 0
nop

banksel    TRISB
movlw    b'00000000'            ;all portb pins will be outputs outputs
movwf    TRISB
movlw    b'00000111'            ;Setting prescaler values
movwf    OPTION_REG
banksel    INTCON
bsf        INTCON,    T0IE
bcf        INTCON,    T0IF
clrf    TMR0
movlw    b'11111111'
movwf    PORTB
goto    Flash

Flash
btfss    INTCON,    T0IF
goto    Flash

btfss    PORTB, 1
goto    ON_LED
goto    OFF_LED
goto     Flash
ON_LED
movlw    b'11111111'
movwf    PORTB
bcf        INTCON, T0IF
clrf    TMR0
goto    Flash
OFF_LED
movlw    b'00000000'
movwf    PORTB
bcf        INTCON,    T0IF
clrf    TMR0
goto    Flash

End

#### Omar.M

##### Member
Thanks, eng1. Just a question "Banksel"-- it isn't listed on the instruction page from the datasheet-- am I missing something?

I've seen this used in a few other programs as well. Must have overlooked something..
-Omar

Ahh!
I think Futz may have gotten me on the right track-- certain things must be automatically defined in that include file, will check that out.

#### eng1

##### New Member
Omar.M said:
Thanks, eng1. Just a question "Banksel"-- it isn't listed on the instruction page from the datasheet-- am I missing something?

I've seen this used in a few other programs as well. Must have overlooked something..
-Omar
banksel is a directive that sets the RP0 and RP1 bits in the STATUS register for you It's listed in this useful chart, for example.

Last edited:

#### Mike - K8LH

##### Well-Known Member
Eng1,

Since INTCON is defined in all banks, what bank to you end up in when you banksel INTCON ?

Also, since you've already got b'11111111' in WREG why not simplify your toggle loop? Since Timer0 has just rolled over is there really any need to clear it again?

Mike

Code:
Flash
btfss   INTCON,T0IF     ; Timer0 overflow? yes, skip, else
goto    Flash           ; branch
bcf     INTCON,T0IF     ; clear interrupt flag
xorwf   PORTB,F         ; toggle all PortB bits
goto    Flash           ;

End

Just noticed Bill´s example uses the XOR instruction... Cool...

Last edited:

#### eng1

##### New Member
Mike said:
Eng1,

Since INTCON is defined in all banks, what bank to you end up in when you banksel INTCON ?
Bank 0 is selected and it's ok in this case. A simulation can show that. Or you can check the .lst file. banksel INTCON produces this code: 1283 1303 = BCF 0x3, 0x5 BCF 0x3, 0x6
I used it for my convenience but setting the RP0 e RP1 bits was perfectly correct. With the code I posted I wanted to fix the problem with the GIE bit / lack of an ISR. There were two possibilities, both valid: adding an ISR at address 0x04, as Bill did, or clearing the GIE bit, as I did. Other improvements were possible of course, like using the defintions in the include file, using the XOR instruction, simplifing the routines as you pointed out.

Last edited:

#### Mike - K8LH

##### Well-Known Member
Thanks. I was curious as I still use the bcf or bsf instructions on STATUS RP0/RP1 bits and I wasn't on a computer at the time with MPLAB installed so I couldn't look to see which two instructions were generated.

Have a great day. Mike.

#### Omar.M

##### Member
Thank you all very much!

Just a few more questions have popped up after more toying around with Assembler.

-Is there any advantage / disadvantage to using the polling method (of the interrupt flag) over an ISR definition?

-I'm going to be try and play around with the CCP module very soon (capture mode). I've read the "Mid-Range MCU Family" literature on the CCP module, but a few things were a bit over my head regarding capturing the time of a pulse--
Do I set up an ISR, and just read the values of CCPR1H / CCPR1L to get the length of the pulse (of course, after proper initialization)?
And when captured values are recorded-- do I just clear the CCPR1H / L values and and reset the PIR1 bit?

-Omar

#### eng1

##### New Member
Omar.M said:
-Is there any advantage / disadvantage to using the polling method (of the interrupt flag) over an ISR definition?
If you use the polling method, the microcontroller is busy (it just wastes time) until the flag is set. This technique is not efficient, but it's very easy and works well in simple programs.
If you use interrupts, the PIC can do other tasks until an interrupt occurs.

#### Omar.M

##### Member
I seem to have gotten stuck once again!

Currently, I've got CCP1 module set up in Capture mode, and TMR0 (incrementing) to interrupt on rollover.

What I would like to do is save the values of the CCP1 capture, then in the main loop, constantly check if the values of the capture-- if they are less than the value of TMR0.

What this is for:
I am going to be measuring the pulse of a R/C transmitter (buddy box signal), decode the first four channels, and output 4 separate PWM outputs.

I've worked this out as-- CCP1 module will get the capture, I wait until the synchronizing bit is in (captured value that is greater than 4 ms) and then start saving the captured values (4 times-- for four channels).

In the background I have TMR0 incrementing and in the main loop, keep checking to see if the values of the capture (for each individual channel) are less than the value of the TMR0. If they are, I'd set the corresponding channel pin off.

On TMR0 rollover, I'd turn on any channel values that are greater than TMR0.

Pretty much allowing for a 4 separate PWM output through software.

I've got this worked out in theory, just am having a bit of troubles with getting it down in Assembler. What I am having troubles with is finding a way to deal with the captured values (since they're 16-bit) and compare (greater than, less than, etc.) with the values of TMR0.

If anyone could please point me to the right direction, I'll very much appreciate it!
-Omar

Status
Not open for further replies.

Replies
5
Views
2K
Replies
5
Views
1K
Replies
2
Views
911
Replies
26
Views
14K
Replies
17
Views
4K