Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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
 
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 )
 
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.
 
As you're polling the T0IF flag, don't enable global interrupts. The GIE bit should be cleared and never set.
 
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
 
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!
 
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.
 
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
 
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.
 
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:
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

<added>

Just noticed Bill´s example uses the XOR instruction... Cool...
 
Last edited:
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:
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.
 
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
 
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.
 
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.

Latest threads

New Articles From Microcontroller Tips

Back
Top