PDA

View Full Version : Serial and interrupt



test153
- 4th February 2009, 21:57
How do one use a interrupt with the SERIN function? Basically what I'm trying to accomplish is to have a blinking LED and an interrupt on porta.5 - where I retrive a byte and then continue with the main loop.

Currently my code isn't working as expected. It seems that the interrupt doesn't resume the main program loop after SERIN.

I'm compiling for pic12f629.

btw, to be able to do multitasking (updating LEDS and receiving from serial port) do I need to use interrupts?



INCLUDE "modedefs.bas" 'For the Baud Rate modes

char var byte

ON INTERRUPT GOTO myint ' Interrupt handler is myint

INTCON.3 = 1 'PORTA change interupt enabled
INTCON.7 = 1 'Global interrupt enabled
IOC.3 = 1

led_on:
high porta.0
pause 500
low porta.0
pause 500
goto led_on

' Interrupt handler
DISABLE ' Disable interrupts in handler
myint:
SerIN PORTA.3, T9600, ["b"],char ' Will be uesed later
INTCON.0 = 0 'Clear GPIF
RESUME ' Return to main program
ENABLE ' Enable interrupts after handler

End

mister_e
- 4th February 2009, 22:13
You just don't want to use a Software bit banged solution with interrupt. Move on a PIC with Real Hardware USART and use USART inetrrupt.

It might be doable with your PIC, but on slower baudrate, using ASM interrupt (maybe instant interrupt), and an home made serial routine. No way this might work 100% properly with ON INTERRUPT even more with internal OSC.

You could still try something and reduce your delay, using short PAUSEUS loop might work better.

Using DEBUGIN would also help.

If you build yourself the Master you could send few garbarge data, then a Synch character, then your data. Says
SEROUT2 ....[REP 0\32, "~", YourData]

on the receiver side you just use WAIT("~") ... might work.....

test153
- 4th February 2009, 22:22
The thing is that it's kinda to late to change the pic for my current project :(

Well it seems that I will be coding my own serial routine after all...

In what way is the debugIN function different except the syntax?

Do you have some more info about instant interrupt? Something to get me started.

Anyway thanks for the help :)

mister_e
- 4th February 2009, 22:25
DEBUGIN works better on higher baudrate on Slower Speed OSC. Check your manual about that. Syntax is a bit different as well.

Instant-Interrupt
http://darreltaylor.com/DT_INTS-14/intro.html

test153
- 4th February 2009, 22:32
Before posting posting to this forum I tried "DT_INTS-14" but I got some compailing errors, any idea how to fix them?


wsave3 position request 416 beyond RAM_END 95
wsave2 position request 288 beyond RAM_END 95
wsave1 position request 160 beyond RAM_END 95
Unable to fit variable RS2_Save

mister_e
- 4th February 2009, 22:36
open DT_INTS-14.bas file, there you'll find


' --- IF any of these three lines cause an error ?? ----------------------------
' Comment them out to fix the problem ----
' -- It depends on which Chip you are using, as to which variables are needed --
wsave1 var byte $A0 SYSTEM ' location for W if in bank1
wsave2 var byte $120 SYSTEM ' location for W if in bank2
wsave3 var byte $1A0 SYSTEM ' location for W if in bank3

So, just modify it as requested


' --- IF any of these three lines cause an error ?? ----------------------------
' Comment them out to fix the problem ----
' -- It depends on which Chip you are using, as to which variables are needed --
;wsave1 var byte $A0 SYSTEM ' location for W if in bank1
;wsave2 var byte $120 SYSTEM ' location for W if in bank2
;wsave3 var byte $1A0 SYSTEM ' location for W if in bank3

test153
- 4th February 2009, 22:38
So I did and now there's only one error left...

Unable to fit variable RS2_Save

mister_e
- 4th February 2009, 22:49
well, seems we hit one of the limitation of the low-end PIC. In this case, asm INT and home made serial routine would work. 12F683 would provide better range.


Let's see what Darrel would suggest...

test153
- 4th February 2009, 22:56
I suppose that the only way to write the serial routine is to code it in asm.

Damn me for choosing this somewhat limited pic :mad:

Archangel
- 5th February 2009, 00:55
12f683 is 8 pin device and has twice the flash memory available.

test153
- 5th February 2009, 22:51
12f683 is 8 pin device and has twice the flash memory available.

Thanks for the tip, but I have already bought the other one - as I said to late to change my mind. Anyway i've been doing some diggin and I'm going forward with the ASM serial routine part. There's only one little problem - the code I'm using gives me a "Symbol previously not defined" error. How do I setup variables so I can write to them inside the asm code and reuse them in picbasic?

Archangel
- 5th February 2009, 23:30
Thanks for the tip, but I have already bought the other one - as I said to late to change my mind. Anyway i've been doing some diggin and I'm going forward with the ASM serial routine part. There's only one little problem - the code I'm using gives me a "Symbol previously not defined" error. How do I setup variables so I can write to them inside the asm code and reuse them in picbasic?

I can answer that, I think. The name of your variable used in the asm routine needs to have an underscore preceding it in pbp, example:
_MyVar var byte

test153
- 5th February 2009, 23:41
I can answer that, I think. The name of your variable used in the asm routine needs to have an underscore preceding it in pbp, example:
_MyVar var byte

Thanks, it worked. Now there only one other problem. I get a bunch of warnings about "Found opcode in column 1" and then MPASM gives me a "too many errors" message.

Edit: Nevermind about that error, it turned out that one need a tab space before the asm commands.

test153
- 7th February 2009, 13:14
For the past few days I have been searching the net for some sample code for the soft uart - since I couldn't find anything useful that worked I ask you guys. Anyone that can point me to some site with anything useful?

Also I found this asm code:

SERBUF var byte
TEMP var byte
COUNTS var byte
ASM
; ************************************************** ******************
; INCH ROUTINE
; THIS ROUTINE INPUTS RS232 DATA USING A 22K OHM RESISTOR, NO LEVEL-
; CHANGING INVERTER IS USED. GPIO,3 = RX (MARK = 0, SPACE = 1).
; THIS ROUTINE USES A 8-DATA BIT PER CHARACTER PROTOCOL.
; TO RECIEVE A CHARACTER, CALL inch. THE RECEIVED CHARACTER IS PLACED
; IN THE REG 'W' AND IN THE REG 'SERBUF'.
; CHARACTER WILL ECHO IF 'retlw 0' IS REM-ED OUT.
; VARIABLES USED: REG 'TEMP' AND REG 'SERBUF' BOTH VARIABLES ARE
; SHARED WITH THE 'outch' ROUTINE
; ROUTINES CALLED: 'half_baud' AND 'baud' FOR THE BAUD-RATE TIMING.
; ************************************************** ******************
inch
btfss GPIO,3 ; SKIP ON START BIT = "SPACE" (+RS232)
goto inch ; ELSE KEEP LOOKING FOR A START BIT
movlw d'08' ; START SERIAL INPUT SEQUENCE
movwf _TEMP ; COLLECT 8 DATA BITS
clrf _SERBUF ; CLEAR SERIAL CHARACTER BUFFER
call half_baud ; DELAY FOR ONE HALF BAUD TIME
btfss GPIO,3 ; FALL THRU IF START BIT STILL = "SPACE"
goto inch ; ELSE IT WAS JUST A NOISE SPIKE, LOOP
inch1
call baud ; DELAY ONE BAUD-BIT TIME ( = 1/BAUD-RATE)
bcf STATUS,0 ; CLEAR THE CARRY BIT
rrf _SERBUF,F ; ROTATE CRY -> MSB, ROTATE MSB RIGHT
btfss GPIO,3 ; IS INPUT = "SPACE" (+RS232) ?
bsf _SERBUF,7 ; ...SKIP IF YES, ELSE SET BIT TO LOGIC '1'
decfsz _TEMP,F ; EIGHT COUNTS YET?
goto inch1 ; ...NO, GET ANOTHER BIT
call baud ; DELAY FOR THE FIRST STOP BIT
movf _SERBUF,W ; Put the character in reg 'W'
retlw 0 ; NOTE: REM THIS OUT IF YOU NEED AN "ECHO"
; ...AND FALL THROUGH TO THE 'OUTCH' ROUTINE

; ************************************************** ******************
; BAUD ROUTINE @ 4 MHz
; BAUD RATE: CONSTANT:
; 1200 Baud D'137'
; 2400 Baud D'68'
; 4800 Baud D'34'
; 9600 Baud D'16'
; 19200 Baud D'8'
; 38400 Baud and up - use 'NOP' delays
; VARIABLES USED: REG 'COUNT'
; ROUTINES CALLED: NONE
; ************************************************** ******************
baud ; AT 2400 BAUD THE PERIOD IS 416.6 US
; CLK = 4MHz
movlw D'68' ; 1 US (BAUD RATE CONSTANT)
movwf _COUNTS ; 1 US
baud1
decfsz _COUNTS,F ; 1 US (+ 1 US MORE IF SKIP)
goto baud1 ; 2 US
; FALL THRU...AFTER 1+1+3x68+1 = 207 US
half_baud
movlw D'68' ; 1 US
movwf _COUNTS ; 1 US
hbaud1
decfsz _COUNTS,F ; 1 US (+ 1 US MORE IF SKIP)
goto hbaud1 ; 2 US
retlw 0 ; ...AFTER 1+1+3x68+1 = 207 US (X2=414 US)
ENDASM
END


I've tried it but I just get a "Stack underflow executing retlw". Also how do one call the inch routine from picbasic?

mister_e
- 7th February 2009, 16:59
RETLW 0 is the same (almost) as RETURN, this ca be remove if you're not using a GOSUB to call it. A return without a previous Gosub call, will indeed "underflow" the stack.

If you sit this routine in a interrupt service routine, check the PBP manual somewhere at the end about INterrupts.

test153
- 7th February 2009, 17:29
Ok, so I need the interrupt to gosub the rs232 routine and how do I call a asm routine outside the asm...endasm?

Archangel
- 7th February 2009, 20:48
Ok, so I need the interrupt to gosub the rs232 routine and how do I call a asm routine outside the asm...endasm?
Sec. 5.1 pbp: " When used at the beginning of a line, @ provides a shortcut for inserting one assembly language Statement into your PBP program."

test153
- 7th February 2009, 21:55
Well I have this code and still get underflow errors... I have a pritty good idea of what the code does, but I can't understand why it gives me this undeflow error as it is called from the main loop.

SERBUF var byte
TEMP var byte
COUNTS var byte

ASM
; ************************************************** ******************
; INCH ROUTINE
; THIS ROUTINE INPUTS RS232 DATA USING A 22K OHM RESISTOR, NO LEVEL-
; CHANGING INVERTER IS USED. GPIO,3 = RX (MARK = 0, SPACE = 1).
; THIS ROUTINE USES A 8-DATA BIT PER CHARACTER PROTOCOL.
; TO RECIEVE A CHARACTER, CALL inch. THE RECEIVED CHARACTER IS PLACED
; IN THE REG 'W' AND IN THE REG 'SERBUF'.
; CHARACTER WILL ECHO IF 'retlw 0' IS REM-ED OUT.
; VARIABLES USED: REG 'TEMP' AND REG 'SERBUF' BOTH VARIABLES ARE
; SHARED WITH THE 'outch' ROUTINE
; ROUTINES CALLED: 'half_baud' AND 'baud' FOR THE BAUD-RATE TIMING.
; ************************************************** ******************
inch:
btfss GPIO,3 ; SKIP ON START BIT = "SPACE" (+RS232)
goto inch ; ELSE KEEP LOOKING FOR A START BIT
movlw d'08' ; START SERIAL INPUT SEQUENCE
movwf _TEMP ; COLLECT 8 DATA BITS
clrf _SERBUF ; CLEAR SERIAL CHARACTER BUFFER
call half_baud ; DELAY FOR ONE HALF BAUD TIME
btfss GPIO,3 ; FALL THRU IF START BIT STILL = "SPACE"
goto inch ; ELSE IT WAS JUST A NOISE SPIKE, LOOP
inch1:
call baud ; DELAY ONE BAUD-BIT TIME ( = 1/BAUD-RATE)
bcf STATUS,0 ; CLEAR THE CARRY BIT
rrf _SERBUF,F ; ROTATE CRY -> MSB, ROTATE MSB RIGHT
btfss GPIO,3 ; IS INPUT = "SPACE" (+RS232) ?
bsf _SERBUF,7 ; ...SKIP IF YES, ELSE SET BIT TO LOGIC '1'
decfsz _TEMP,F ; EIGHT COUNTS YET?
goto inch1 ; ...NO, GET ANOTHER BIT
call baud ; DELAY FOR THE FIRST STOP BIT
movf _SERBUF,W ; Put the character in reg 'W'
retlw 0 ; NOTE: REM THIS OUT IF YOU NEED AN "ECHO"
; ...AND FALL THROUGH TO THE 'OUTCH' ROUTINE

; ************************************************** ******************
; BAUD ROUTINE @ 4 MHz
; BAUD RATE: CONSTANT:
; 1200 Baud D'137'
; 2400 Baud D'68'
; 4800 Baud D'34'
; 9600 Baud D'16'
; 19200 Baud D'8'
; 38400 Baud and up - use 'NOP' delays
; VARIABLES USED: REG 'COUNT'
; ROUTINES CALLED: NONE
; ************************************************** ******************
baud: ; AT 2400 BAUD THE PERIOD IS 416.6 US
; CLK = 4MHz
movlw D'68' ; 1 US (BAUD RATE CONSTANT)
movwf _COUNTS ; 1 US
baud1:
decfsz _COUNTS,F ; 1 US (+ 1 US MORE IF SKIP)
goto baud1 ; 2 US
; FALL THRU...AFTER 1+1+3x68+1 = 207 US
half_baud:
movlw D'68' ; 1 US
movwf _COUNTS ; 1 US
hbaud1:
decfsz _COUNTS,F ; 1 US (+ 1 US MORE IF SKIP)
goto hbaud1 ; 2 US
retlw 0 ; ...AFTER 1+1+3x68+1 = 207 US (X2=414 US)
ENDASM

high porta.0
loop:
@ goto inch
if SERBUF = 49 then low porta.0
goto loop
END

Darrel Taylor
- 8th February 2009, 04:23
@ goto inch

Try ...


@ L?CALL inch

test153
- 8th February 2009, 10:49
Some how I changed the line "@ call inch" to goto before posting. Using "@ L?CALL inch" didn't do anything...

Darrel Taylor
- 8th February 2009, 14:02
If that's your whole program, then you need to add a

GOTO loop
before the ASM block.

As it's shown, it will fall into the inch routine on power-up.
Then it has nowhere to return to.

hth,