PDA

View Full Version : 12f1822, serial RX under interrupt, echo program doesn't want to play



Chris Barron
- 3rd December 2012, 23:44
I've been trying to get some code working on the 12F1822 which works fine on the 16F690

I can't explain why there should be a big difference in operation. I've gone through the datasheet trying to find differences between teh two chips and making any necessary adjustments.

All I am trying to do at this stage is prove correct operation of the UART, so I have written a simple echo routine.



; __config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _MCLRE_OFF & _PWRTE_OFF & _BOREN_OFF & _CLKOUTEN_OFF
; __config _CONFIG2, _PLLEN_OFF & _LVP_OFF

Include "modedefs.bas"

DEFine OSC 8
define INTHAND myint

RX_Byte var byte

goto init

asm
myint:
btfss PIR1,5
goto int_out
bcf PIR1,5
movfw RCREG
movwf _RX_Byte
movwf TXREG
nop
btfss PIR1,TXIF
goto $-1

int_out:
retfie
endasm

init:

TRISA = %00000010 ; set pins for serial data
ANSELA = 0 ; set all pins digital
PORTA = %00000000


pause 200

asm
movfw RCREG
movfw RCREG
movfw RCREG
endasm

; Power on
; Initialise variables


Restart:

; Initialise SFR's

;EUSART
TXSTA = %10100100
RCSTA = %10010000
BAUDCON = %00000000
SPBRG = 12 '38400 baud
;SPBRGH = 0

;INTERRUPTS
INTCON = %11000000
PIE1 = %00100000 ; interrrupt on data received

;OSCILLATOR
OSCCON = %01110011

;PORT A
TRISA = %00000010 ; set pins for serial data
ANSELA = 0 ; set all pins digital
PORTA = 255

;COMPARATOR
CM1CON0 = 0

main:

while 1
if (RCSTA.1 = 1) or (RCSTA.2 = 1) then
gosub Clear_err
endif
wend


Clear_err:
RCSTA = 0
@ movfw RCREG
@ movfw RCREG
@ movfw RCREG
RCSTA = %10010000
return


stop


The chip seems to repeatedly reset itself.

Any help getting this going will be very much appreciated. I have tried loits of variations of the commands in case there is a datasheet error ( I recall from previous experience with the 12F1822 I found a datasheet error).

Chris

Chris Barron
- 4th December 2012, 11:50
I can't remember how i resolved a similar issue like this with this chip previously, but I know I've managed it.

I've just looked at the project again and the receiving unit never sends data without a request for it to be sent, so the code doesn't need to expect the arrival of random data. I've just tested it using HSERIN and HSEROUT and it looks like I'll be able to work with the native Pbasic commands instead.

I like having control of interrupts, usually, but this time it's not important to me :)

Darrel Taylor
- 4th December 2012, 16:35
When you're working with PBP, it's easy to forget that there are "BANKs" in the RAM because it's all handled for you.
But when you are writing at the ASM level, you have to remember about the BANKs. And on the F1 type parts, there are a lot of them. (32 to be exact).

In your case, RCREG is in BANK3.
And since you only have 1 variable in your program, it will obviously end up in BANK0. But when the program gets bigger, that may not be the case.
It should be able to find your variables no matter what bank they end up in.

Also, when you get an interrupt on an F1 part. You have no idea what bank it is in when it gets to the ISR.
It's up to you to change it to BANK0 (if that's the bank your ISR needs).

Mike, K8LH
- 4th December 2012, 16:51
When you're working with PBP, it's easy to forget that there are "BANKs" in the RAM because it's all handled for you.
But when you are writing at the ASM level, you have to remember about the BANKs. And on the F1 type parts, there are a lot of them. (32 to be exact).

In your case, RCREG is in BANK3.
And since you only have 1 variable in your program, it will obviously end up in BANK0. But when the program gets bigger, that may not be the case.
It should be able to find your variables no matter what bank they end up in.

Also, when you get an interrupt on an F1 part. You have no idea what bank it is in when it gets to the ISR.
It's up to you to change it to BANK0 (if that's the bank your ISR needs).

Really? I'm surprised! The BoostC compiler I use (sorry, still no PBP to play with here) apparently keeps track of the variables and registers used in my assembly language instructions and automatically inserts the 'movlb x' instructions for me. Now you have me wondering if that feature is unique to BoostC or if other compilers have it as well? Anyway, please notice how I had to comment out all of my bank select instructions after I discovered they were redundant;


/* *
* (C) 2012, K8LH - low level One-Wire R/W (Carry) Bit Driver *
* (hard coded for "owpin" defines and 8-MHz clock) (30 words) *
* */
void owrw() // read/write Carry bit
{ intcon.GIE = 0; // interrupts off
//asm movlb owport // bank 0 (inserted by compiler)
asm bcf owport,owpin // clear owpin output latch
//asm movlb owtris // bank 1 (inserted by compiler)
asm bcf owtris,owpin // owpin low (falling edge)
asm movf _pcl,F // pseudo bra $+1 (2 cycles)
asm movf _pcl,F // "
asm movf _pcl,F // "
asm skpnc // if a '1' (C=1)
asm bsf owtris,owpin // set owpin to hi-z '1'
asm movlw 18/3 //
dly1:
asm decfsz _wreg,W // DelayCy(14*usecs-10)
asm bra dly1 //
//asm movlb owport // bank 0 (inserted by compiler)
asm btfss owport,owpin // exactly 14-us from falling edge
asm clrc // clear Carry if 'owpin' was low
asm movlw 84/3 // balance of 60-usec "r/w slot"
dly2:
asm decfsz _wreg,W // DelayCy(47*usecs-10)
asm bra dly2 //
//asm clrf _wreg // wreg already 0 (see above)
asm rlf _wreg,W // save C (wreg = 0x00 or 0x01)
asm xorwf _crc,F // xor b0 bits, result in 'crc'
asm rrf _crc,F // xor result 0 (C=0)?
asm skpnc // yes, skip, else
asm iorlw 0x18 // wreg = x8+x5+x4+1 poly and b0 bit
asm rrf _wreg,W // restore C (wreg = 0x8C or 0x00)
asm xorwf _crc,F // apply the polynomial, or not
//asm movlb owtris // bank 1 (inserted by compiler)
asm bsf owtris,owpin // set owpin to hi-z '1' @ 61-usecs
intcon.GIE = 1; // interrupts on
} //

/* *
* (C) 2012, K8LH - One-Wire R/W Byte Function (11 words) *
* */
char owrw(u08 pbyte) // read/write byte
{ u08 i = 0; // bit counter
do //
{ asm rrf _pbyte,W // put output bit b0 in Carry
owrw(); // write then read bit
asm rrf _pbyte,F // save input bit from Carry
i++; //
} while(i.3 == 0); //
return pbyte; //
} //

Chris Barron
- 4th December 2012, 19:37
Thanks Darrel. Can't tell yoiu how close i came to putting in banksels, but then tried something else.

Job done,

Much appreciated, many thanks

Chris

Dick Ivers
- 4th December 2012, 21:01
Hi Chris,
Could you post your corrected code? Myself and others also use 16F1 parts, so this is an important issue.

Thanks,
Dick

Chris Barron
- 5th December 2012, 22:32
Hello Dick

I tested the same code as above, changing the interrupt handler to the following


asm
myint:
banksel PIR1
btfss PIR1,5
goto int_out
bcf PIR1,5
banksel RCREG
movfw RCREG
banksel _RX_BYTE
movwf _RX_Byte
banksel TXREG
movwf TXREG
nop
btfss PIR1,TXIF
goto $-1

int_out:
retfie
endasm

If in doubt, add another banksel ;)

I'm not using the code now but I did test it upon receipt of Darrel's input to check it out.
I have used this part as a battery cell monitor and I can recall scratching my head over the same issue as then.
Hopefully I'm twice bitten, third time shy :)

Mike, K8LH
- 6th December 2012, 02:36
Are you missing a bank select in that code snippet?


asm
myint:
banksel PIR1 ' |B0
btfss PIR1,RCIF ' |B0
goto int_out ' |B0
bcf PIR1,RCIF ' |B0
banksel RCREG ' |B3
movfw RCREG ' |B3
banksel _RX_BYTE ' |B?
movwf _RX_Byte ' |B?
banksel TXREG ' |B3
movwf TXREG ' |B3
nop ' |B3
btfss PIR1,TXIF ' |B0 <-- *****
goto $-1 ' |B0

int_out:
retfie
endasm


If _RX_Byte is in bank 0, then maybe this would work?


asm
myint:
banksel PIR1 ' |B0
btfss PIR1,RCIF ' |B0
retfie ' |B0
bcf PIR1,RCIF ' |B0
banksel RCREG ' |B3
movfw RCREG ' |B3
movwf TXREG ' |B3
banksel _RX_BYTE ' |B0
movwf _RX_Byte ' |B0
btfss PIR1,TXIF ' |B0
goto $-1 ' |B0
retfie ' |B0
endasm

Chris Barron
- 7th December 2012, 08:13
Whatever.

Darrel's answer covered it.