|
|
View previous topic :: View next topic |
Author |
Message |
surfer0815
Joined: 10 Sep 2010 Posts: 7 Location: Germany
|
18f8722 two serial ports Problems |
Posted: Sat Jan 08, 2011 4:57 am |
|
|
Hi!
I tried it now for a few days, to get serial com working on 18f8722, so now I hope someone here could give me the tricky bit I have to set for a working pic.
If I compile this code, I can see on both serial Ports on PC the 2 different messages on startup, but Interrupt is not working.
I send a charachter from PC to PIC (on both Ports the same) and nothing happens.
Normaly I should get the "fire-1" or "fire-2" Message, if Interrupt occured, but nothing hapens.
My Compiler Version is 4.110
Hope there is someone who had same Problems an got it out?
//#####8722-serial-test.h###########
#include <18F8722.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES noLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES noFCMEN //Fail-safe clock monitor enabled
//#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES MCU //Microcontroller Mode
#use delay(clock=10000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS,stream=uart1)
#use rs232(baud=9600,parity=N,xmit=PIN_g1,rcv=PIN_g2,bits=8,errors,stream=uart2)
#define led pin_f0
//#######8722-serial-test.c############
#include "8722-serial-test.h"
short int int_=0,int2_=0;
#int_RDA
void RDA_isr()
{
int_=1;
}
#int_RDA2
void RDA2_isr()
{
int2_=1;
}
void main()
{
port_b_pullups(TRUE);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_spi2(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//enable_interrupts(INT_RDA);
enable_interrupts(INT_RDA2);
enable_interrupts(GLOBAL);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
output_high(led);delay_ms(500);output_low(led);delay_ms(500);output_high(led);delay_ms(500);output_low(led);
fprintf(uart1,"here i am uart1");
fprintf(uart2,"here i am uart2");
while(1){
If (int_==1){
disable_interrupts(INT_RDA);
output_toggle(led);
fprintf(uart1,"fire-1");
int_=0;
enable_interrupts(INT_RDA);
}
If (int2_==1){
disable_interrupts(INT_RDA2);
output_toggle(led);
fprintf(uart2,"fire-2");
int2_=0;
enable_interrupts(INT_RDA2);
}
}
} |
|
|
surfer0815
Joined: 10 Sep 2010 Posts: 7 Location: Germany
|
|
Posted: Sat Jan 08, 2011 6:11 am |
|
|
Ok, I tried a few things more and here is what i got:
If I put this to one of the ISR Routines: fprintf(uart1,"int occured");
I send a char to the pic, and then I see an endless output off "int occuredint occuredint occured....."
So the Problem seems to be, that the Pic never gets out of the ISR again, but why?
Does CCS not clear the Interrupt Flag bit by itself, so a new interrupt can occur? |
|
|
drh
Joined: 12 Jul 2004 Posts: 192 Location: Hemet, California USA
|
|
Posted: Sat Jan 08, 2011 7:07 am |
|
|
You need to read the RCREG in the isr to clear the RX interrupt flag. _________________ David |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Sat Jan 08, 2011 7:38 am |
|
|
drh wrote: | You need to read the RCREG in the isr to clear the RX interrupt flag. |
I don't think that's true, even though the symptoms he describes may indicate otherwise. I believe the compiler handles clearing the interrupt bit automatically in the ISR call.
Surfer, try this and see what happens. Try to post the actual code that you are using at the time of the problem and use the 'code' feature in the forum.
Code: | //#####8722-serial-test.h###########
#include <18F8722.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES noLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES noFCMEN //Fail-safe clock monitor enabled
//#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES MCU //Microcontroller Mode
#use delay(clock=10000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS,STREAM=uart1)
#use rs232(baud=9600,parity=N,xmit=PIN_G1,rcv=PIN_G2,bits=8,ERRORS,STREAM=uart2)
#define led pin_f0
//#######8722-serial-test.c############
#include "8722-serial-test.h"
short int int_=0,int2_=0;
#int_RDA
void RDA_isr()
{
int_=1;
}
#int_RDA2
void RDA2_isr()
{
int2_=1;
}
void main()
{
port_b_pullups(TRUE);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_spi2(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RDA);
enable_interrupts(INT_RDA2);
enable_interrupts(GLOBAL);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
output_high(led);
delay_ms(500);
output_low(led);
delay_ms(500);
output_high(led);
delay_ms(500);
output_low(led);
fprintf(uart1,"here i am uart1\n\r");
fprintf(uart2,"here i am uart2\n\r");
while(1)
{
If (int_==1)
{
output_toggle(led);
fprintf(uart1,"fire-1\n\r");
int_=0;
}
If (int2_==1)
{
output_toggle(led);
fprintf(uart2,"fire-2\n\r");
int2_=0;
}
}
} |
I didn't actually try to compile this, so there might need to be some minor corrections.
Report back with the results. Try only sending one character to the first UART and see what happens. Then try sending just one character to the second UART and see what happens. Then try sending one character to both.
Also, describe your hardware. Are you using a RS232 level converter? Do you have pullups on the RX pins? Is this a production development board? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Jan 08, 2011 7:58 am |
|
|
jecottrell wrote: | drh wrote: | You need to read the RCREG in the isr to clear the RX interrupt flag. |
I don't think that's true, even though the symptoms he describes may indicate otherwise. I believe the compiler handles clearing the interrupt bit automatically in the ISR call.
|
It is true.
You cannot clear the interrupt flag, _without_ first reading the character. If a character is still present in the input buffer, the flag will immediately set itself again, and the interrupt handler will be called again.
The compiler _attempts_ to clear the flag, but unless the hardware condition is cleared, it won't work.
On the following interrupts, you _must_ clear the hardware condition in the handler:
INT_RDA (and RDA2). Must read the character.
INT_TBE (you need to load a character, or disable the interrupt).
INT_RB (need to read port B).
and several more when you get into things like Can bus, USB etc..
Best Wishes |
|
|
surfer0815
Joined: 10 Sep 2010 Posts: 7 Location: Germany
|
|
Posted: Sat Jan 08, 2011 8:07 am |
|
|
David (drh):
Thats it! Thanks a lot!
If i read the rcreg1 in isr1 and rcreg2 in isr2, the code WORKS!!!!
jecottrell:
I tried out your posted code, but same issue as my own code, if i send one char, programm hangs in isr.
But if i clear rcreg1 and rcreg2, your code is working and putting chars out!
For now I just worked with one single serial port, and didnĀ“t had this Problems, could it be a compiler bug?
Thanks for your help guys! |
|
|
surfer0815
Joined: 10 Sep 2010 Posts: 7 Location: Germany
|
|
Posted: Sat Jan 08, 2011 8:13 am |
|
|
Ttelmah:
You are right, that the incoming char, has to be read in the isr itself, otherwise rcreg is not cleared and the isr loops endless times!
Now I put a simple buf=fgetc(ua1); to the isr and rcreg is cleared automatically! |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Sat Jan 08, 2011 8:38 am |
|
|
Excellent.
That's interesting to know, it's not the ISR that clears the interrupt, its reading the character.
Are there any other Interrupts that are like that, merely calling the ISR doesn't clear the INT bit?
Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Jan 08, 2011 9:21 am |
|
|
jecottrell wrote: | Excellent.
That's interesting to know, it's not the ISR that clears the interrupt, its reading the character.
Are there any other Interrupts that are like that, merely calling the ISR doesn't clear the INT bit?
Thanks. |
It is worth looking at the data sheet for RBIF.
"This interrupt can wake the device from SLEEP. The user in the Interrupt Service Routine, can clear the interrupt in the following manner:
a) Any read or write of PORTB (except with the MOVFF instruction). This will end the mismatch condition.
b) Clear flag bit RBIF.
A mismatch condition will continue to set flag bit RBIF. Reading PORTB will end the mismatch condition, and allow flag bit RBIF to be cleared."
Note the critical thing. You can 'clear' RBIF, but it will set again immediately, if the 'mismatch' is still there.
This applies to _all_ interrupts reflecting a 'hardware' condition. You can't exit the I2C interrupt, unless you update the I2C buffer (writing or reading). Serial transmit can't be left, unless you load a character to send (or disable the interrupt). The USB serial receive code must read the data. If (on a DS PIC), you program an interrupt to be 'level' triggered, you can't leave, till either the line changes state again, or you reverse the 'sense' of the interrupt. etc. etc.. There are more interrupts that behave this way, than don't.....
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|