|
|
View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
"INT_EXT" problem. |
Posted: Fri Sep 30, 2011 2:10 pm |
|
|
Hi all !!
I have strange problem ! I want to use 1 or 2 INT_EXT for serial interrupts and gate the data from card reader. When I powered my schematics my CPU (PIC18F2525) blocking and do nothing! The Pic start working normally when "catch" ISR INT_EXT and INT_EXT1 if I defined 2 int_ext isr.
My compiler ver. is 4.104, my configuration for PIC 18F2525 it's:
Code: |
#include <18F2525.h>
#device HIGH_INTS=TRUE
#build (nosleep)
#fuses HS,PROTECT,NODEBUG,PUT,NOWDT,NOBROWNOUT,NOLVP,NOCPB,MCLR
//#fuses NOFCMEN,NOWRTB,NOIESO,NOPBADEN,NOXINST,
#use delay(clock=11059200)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,errors,STREAM=rs_485)
#use rs232(baud=9600,rcv=PIN_B0,STREAM=GP_20_1,errors)
#use rs232(baud=9600,rcv=PIN_B1,STREAM=GP_20_2,errors)
//.................................................
#int_ext HIGH
void EXT_GP20_1isr()
{
buffer_GP20_1[index_gp20_1] = fgetc(GP_20_1);
if(++index_gp20_1 == buffer_size_GP20)
{
index_gp20_1 = 0;
}
set_timer0(52500);
clear_interrupt(int_TIMER0);
enable_interrupts(int_TIMER0);;
}
#int_ext1
void EXT_GP20_2isr()
{
buffer_GP20_2[index_gp20_2] = fgetc(GP_20_2);
if(++index_gp20_2 == buffer_size_GP20)
{
index_gp20_2 = 0;
}
set_timer0(52500);
clear_interrupt(int_TIMER2);
enable_interrupts(int_TIMER2);
}
#int_rda //receive data from rs485;
void rs485_isr ()
{
x = fgetc(rs_485);
if(!packet)
{
buffer_485_rx[index_485_rx] = x;
if(++index_485_rx == buffer_size_485_rx)
{
index_485_rx =0;
}
temp_index=index_485_rx;
set_timer1(62500);
clear_interrupt(int_TIMER1);
enable_interrupts(int_TIMER1);
}
}
// ...........................................................
void main ()
{
delay_ms (1000);
packet=0;
index_485_rx=0;
index_gp20_1=0;
index_gp20_2=0;
tony_fl = 0;
card_rdy1=FALSE;
card_rdy2=FALSE;
fprintf(rs_485,"Projec running..->\n\r");
lcd_init ();
lcd_putc("\fLCD_test..");
SETUP_ADC(ADC_OFF);
SETUP_CCP1(CCP_OFF);
SETUP_CCP2(CCP_OFF);
setup_vref(FALSE);
setup_comparator(NC_NC_NC_NC);
setup_timer_0(T0_INTERNAL|T0_DIV_1); //T0_DIV_8
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_16, 0xc0, 10);
//setup_timer_3(T3_INTERNAL|T3_DIV_BY_8);
enable_interrupts(global);
enable_interrupts(int_rda);
enable_interrupts(INT_EXT_H2L);
enable_interrupts(INT_EXT1_H2L);
port_b_pullups (TRUE);
//......................................... |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 30, 2011 4:59 pm |
|
|
You need to show a complete and compilable test program that fails.
Also, explain what you mean by "blocking and do nothing". Do you
mean that the fprintf() and lcd_putc() lines don't display anything ?
If so, first make a very small program with only fprintf() and lcd_putc()
(and lcd_init) and prove that you can display text. If so, then debug
the full test program by commenting out lines or sections of the program
until you discover which part is causing the failure to print. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Oct 01, 2011 2:38 am |
|
|
Several little comments though:
1) Get rid of the errors keyword on the GP_20_1, and GP_20_2 streams. These are doing nothing for you.
2) Understand, that if you perform an fgetc, on a software UART, the code will sit in the handler for 9.5/9600th second. So if you are receiving a byte on EXT1, and have started receiving, then receive an interrupt on ext, the code will jump to handle the data on B0, and return basically a mSec later. The receive code on EXT, will then _continue_, with the data now being garbage.
With the CCS software UART, you can _only_ receive on one software stream at a time. As written your code _will_ get garbage if data arrives on a second source at the same time, even if using interrupts
3) You don't show your timer interrupt handler, so no comments can be made about what effect this may also have on receiving data.
4) Enable the pullups, and clear the interrupts _before_ enabling them. Otherwise if the pins were low when you setup the interrupts, you will get a spurious receive at the start.
If you genuinely need to handle RS232 receive on three streams at the same time, you will have to change your approach. Use a timer interrupt at 19200 * per second or more, and poll the two serial lines in this, then when a start bit is seen, use a state machine to build the byte on subsequent interrupt calls, or have two 9600* per second interrupts available, and on the falling edge in int0/int1, delay for few uSec, then start one of these, and shift in the bits with state machines in these. The CCS software UART implementation, won't do it.
Best Wishes |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Sun Oct 02, 2011 3:29 pm |
|
|
Hi PCM, Ttelmah ! thanks for your reply! I will paste small test program that demonstrate my problem. Code: |
#include <18F2525.h>
#device HIGH_INTS=TRUE
#build (nosleep)
#fuses HS,PROTECT,NODEBUG,NOPUT,NOWDT,NOBROWNOUT,NOLVP,NOCPB,MCLR
#use delay(clock=11059200)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,errors,STREAM=rs_485)
#use rs232(baud=9600,rcv=PIN_B0,STREAM=GP_20_1)
#use rs232(baud=9600,rcv=PIN_B1,STREAM=GP_20_2)
#define buffer_size_GP20 14
#define buffer_size_485_tx 16
#define buffer_size_485_rx 64
// Global variable
//int1 packet;
//int index_485_rx,temp_index;
//int x;
int index_gp20_1;
int index_gp20_2;
int1 card_rdy1,card_rdy2;
int buffer_GP20_1 [buffer_size_GP20];
int buffer_GP20_2 [buffer_size_GP20];
#int_ext HIGH
void EXT_GP20_1isr() // ext_Gp20 interrupt receiver func;
{
buffer_GP20_1[index_gp20_1] = fgetc(GP_20_1);
if(++index_gp20_1 == buffer_size_GP20)
{
index_gp20_1 = 0;
}
set_timer0(52500);
clear_interrupt(int_TIMER0);
enable_interrupts(int_TIMER0);;
}
#int_ext1
void EXT_GP20_2isr()
{
buffer_GP20_2[index_gp20_2] = fgetc(GP_20_2);
if(++index_gp20_2 == buffer_size_GP20)
{
index_gp20_2 = 0;
}
set_timer3(52500);
clear_interrupt(int_TIMER3);
enable_interrupts(int_TIMER3);
}
#int_timer0
void timer_0_isr ()
{
card_rdy1=TRUE;
index_gp20_1 = 0;
disable_interrupts(int_TIMER0);
}
#int_timer3
void timer_2_isr ()
{
card_rdy2=TRUE;
index_gp20_2 = 0;
disable_interrupts(int_TIMER3);
}
void main (void)
{
delay_ms (1000);
fprintf(rs_485,"Projec running...\n\r");
SETUP_ADC(ADC_OFF);
SETUP_CCP1(CCP_OFF);
SETUP_CCP2(CCP_OFF);
setup_vref(FALSE);
setup_comparator(NC_NC_NC_NC);
setup_timer_0(T0_INTERNAL|T0_DIV_1); //T0_DIV_8
setup_timer_3(T3_INTERNAL|T3_DIV_BY_1);
enable_interrupts(global);
enable_interrupts(INT_EXT_H2L);
enable_interrupts(INT_EXT1_H2L);
clear_interrupt(INT_EXT);
clear_interrupt(INT_EXT1);
while (TRUE){
fprintf(rs_485,"TEST UART ...\n\r");
delay_ms(1000);
}
} |
PS. Ttelmah I know for garbage data if INT_EXT and INT_EXT1 occur on the same time, but I'm using LCD display in my project and show error message on lcd if data is garbage.
My general problem is why cpu don't reach: " while (TRUE){
fprintf(rs_485,"TEST UART ...\n\r");
delay_ms(1000);
} " ??
PIC reach "while (true)...." when get ext_isr if one or two ext_isr's for my case.
This event happen when reset or power up PIC.
Thanks for your attention ! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 02, 2011 6:47 pm |
|
|
Ttelmah told you to do this, but you didn't do it or you did the wrong thing:
Quote: |
4) Enable the pullups, and clear the interrupts _before_ enabling them. Otherwise if the pins were low when you setup the interrupts, you will get a spurious receive at the start. |
He means do it like this:
Code: |
port_b_pullups(TRUE);
enable_interrupts(INT_EXT_H2L);
enable_interrupts(INT_EXT1_H2L);
clear_interrupt(INT_EXT);
clear_interrupt(INT_EXT1);
enable_interrupts(global);
|
Also, I have found in the past that it can take some time for the Port B
pull-ups to completely pull-up. So add a short delay after that line,
like this:
Code: |
port_b_pullups(TRUE);
delay_us(10);
enable_interrupts(INT_EXT_H2L);
enable_interrupts(INT_EXT1_H2L);
clear_interrupt(INT_EXT);
clear_interrupt(INT_EXT1);
enable_interrupts(global);
|
|
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Sun Oct 02, 2011 11:02 pm |
|
|
Hi PCM! I've external 4k7 pull up resistor on B0 and B1 pins. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Mon Oct 03, 2011 12:58 pm |
|
|
I don't know, but pic get start work normaly if add keyword "INVERT" in : Code: | #use rs232(baud=9600,rcv=PIN_B0,INVERT,STREAM=GP_20_1)
#use rs232(baud=9600,rcv=PIN_B1,INVERT,STREAM=GP_20_2) |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 03, 2011 2:54 pm |
|
|
Quote: | pic get start work normaly if add keyword "INVERT
|
If it works with the INVERT parameter, it probably means:
1. You don't have a MAX232 chip or any inverter chip connected between
the PIC and card reader.
2. Your card reader sends out CMOS voltage level, inverted serial
port signals.
Are those two things true ?
Describe the connections between your card reader and the PIC.
Post a link to the data sheet for your card reader. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Mon Oct 03, 2011 3:24 pm |
|
|
Hi PCM!
Yes my cardreader send rs232 compatible signal with 0-5v level (p-p) , and I'm inverting signal with sn74HC04. The form signal from card reader is OK,because I've a Scope and saw signal, and if disconnecting PIN_B0,PIN_B1 from schematics and connect only external pull up resistors THE Problem is same!! |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Tue Oct 04, 2011 2:44 pm |
|
|
The problem was solved with this configuration for interrupts:
Code: |
enable_interrupts(int_rda);
enable_interrupts(INT_EXT_H2L);
enable_interrupts(INT_EXT1_H2L);
clear_interrupt(int_rda);
clear_interrupt(INT_EXT);
clear_interrupt(INT_EXT1);
enable_interrupts(global); |
And an external 4k7 resistors on PIN_B0 and PIN_B1. |
|
|
|
|
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
|