View previous topic :: View next topic |
Author |
Message |
erhane
Joined: 01 Jul 2014 Posts: 41
|
Interrupt re-entrance |
Posted: Fri Jul 25, 2014 7:22 am |
|
|
Hello,
I am using pic16f1946. Just trying to get interrupt from RS485 line. After first interrupt occurs it starts to re-entering interrupt continuously and Led starts blinking. What can be the reason? Here is my code.
Code: |
#INCLUDE <16f1946.h>
#FUSES INTRC_IO // Internal RC clock (OSC1 and OSC2 pins are normal I/O)
#FUSES NOWDT // Watch Dog Timer disabled
#FUSES PUT // Power Up Timer enabled
#FUSES NOMCLR // Master Clear pin is used for I/O
#FUSES PROTECT // Code protected from reads
#FUSES CPD // Data EEPROM code protected
#FUSES NOBROWNOUT // No Brown_Out reset
#FUSES NOCLKOUT // Disable clock output on OSC2
#FUSES NOIESO // Internal External Switch Over Mode disabled
#FUSES NOFCMEN // Fail-safe clock monitor disabled
#FUSES WRT // Program memory write protected
#FUSES NOLVP // Low Voltage Programming disabled
#FUSES NODEBUG // No debug mode for ICD
#USE DELAY(clock = 32000000)
#USE RS232(stream=RS485,baud=38400,xmit=PIN_G1,rcv=PIN_G2,ENABLE=PIN_G3,parity=N,bits=8,stop=1)
// Led pin
#DEFINE LED PIN_E2 //output // Led used in debugging
#INT_RDA2
void set_RS485_flag(){
output_toggle(LED);
delay_ms(1000);
}
void main()
{
// Set I/O states of the ports
// 76543210
set_tris_a(0b00000000);
set_tris_b(0b11000000);
set_tris_c(0b00000000);
set_tris_d(0b00000000);
set_tris_e(0b00000000);
set_tris_f(0b11110000);
set_tris_g(0b11100100);
output_low(LED);
enable_interrupts(global);
enable_interrupts(INT_RDA2);
while(true)
{
}
|
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Fri Jul 25, 2014 7:50 am |
|
|
hardware generates interrupts. You have to "clear" the reason for the interrupt in most of the interrupts, including the one you are using. Look up what RDA2 is for. You must complete the operation it expects or it will keep firing.
Also, no need for TRIS settings. Compiler does it for you. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jul 25, 2014 7:58 am |
|
|
Easy.
When the interrupt is triggered it is up to you to clear the interrupt condition, i.e. when the reason for triggering the interrupt is still there on interrupt exit, a new interrupt will be triggered immediately again. Depending on the interrupt there are different ways to accomplish this, see the datasheet. For portB interrupt for example you have to do a read operation on the port. For UARTs you have to read the received data byte.
Code: | #INT_RDA2
void set_RS485_flag(){
fgetc(RS485); // dummy read to clear the interrupt condition
output_toggle(LED);
delay_ms(1000);
} |
Note 1: it is bad practise to have a long delay in your ISR. For purpose of your demonstration it is allowed but otherwise get out of the ISR as quick as possible.
Note 2: Always add the 'errors' directive to the #RS232 line. With this setting the compiler will create extra code for clearing error conditions in the hardware UART. As it is now the UART will block after 3 characters receiver buffer overflow and appears to be blocked until you reset the PIC. |
|
|
|