![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Cam Bruce
Joined: 08 Sep 2003 Posts: 8
|
Write_EEPROM and RDA interrupt conflict. |
Posted: Mon Jan 24, 2005 2:19 pm |
|
|
My problem is an unexplainable disabling of the serial interrupt.
Using a 18F452, PCH 3.152
I have a host computer polling one register in EEPROM. The PIC receives this poll, and replies with the register value. The register value changes, repending on an Input Logic level. I think that I hit a snag, when the poll ocurrs as the input pin changes state.
At that time, I no longer get the serial interrupt.
I added LEDs to the code, so I could see. The program enters, and leaves the ISR, but, once a conflict ocurrs, the serial interrupt is disabled.
The attached code still conflicts. I have thinned it out, to try to find the problem.
Any thoughts ?
Thanks
Cam
Code: |
////////////////////////////////////////////////////////////////////////////
//// TMB_452-13Jan05.C ////
//// Thinned out, to find why Serial Interrupt is being Disabled. ////
////////////////////////////////////////////////////////////////////////////
#include "18F452.H"
//// Definitions ////
#DEFINE DIGIN1 PIN_D1 //PIN FOR DIGITAL INPUT 1
#DEFINE FULL_RESET PIN_B1 //RESET RELAY, OUTPUT PIN
#use standard_io(C)
#DEFINE DIG_MASK 0XF4 //DIGITAL ALARM DISABLE MASK
short check_alarm=0; //used to set how long between alarm checks.
INT DIG_AMIOK; //BIT BY BIT (FOR 6 BITS) DIGITAL "AM I OK?"
INT LAST_DIG=0xFF; //THIS IS THE LAST ALARMS I HAD.
long silent_time; //used for a "long idle time" reset.
long int_count=0; // Number of interrupts left before a second has elapsed
int SECONDS=0; //a running real time counter. starts at 0 on reset, counts forever.
short from_host=0; //set in Serial ISR, while Host is sending
int byte_count=0; //counter for received numbers
int RMC_data_in[8]; //Array for data received from Host.
#byte porta=5 //These lines define the Ports.
#byte portb=6
#byte portc=7
#byte portd=8
#byte porte=9
//// End of Definitions ////
#fuses HS,NOPROTECT,NOWDT,PUT,NOLVP //WDT disabled for testing, NEEDS re-enabled
#use delay(clock=4000000) //USING A 4MHz CRYSTAL
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=n)
////////////////////////////////////////////////////////////
//// THE NEXT LINES ARE THE Rx Data INTERRUPT ROUTINE. ////
#int_rda
VOID serial_isr()
{
if(kbhit()) //is there a serial byte ready ?
{
output_high(pin_d5); //turn on a LED for testing
RMC_data_in[byte_count]=getc(); //save data to the array
Silent_Time=0; //reset silent time counter
if(++byte_count>=6) //ARRAY NOW HAS THE 6 BYTE MODBUS COMMAND (use >=, to catch a runaway)
{byte_count=0; // Buffer full, RESET IT
from_host=1; //set flag, to check the string
}//end if byte_count==6
output_low(pin_d5); //turn off the LED
}
}
//// END OF INTERRUPT SERVICE ROUTINE ////
////////////////////////////////////////////////////////////
VOID main() //
{
output_low(full_reset); //don't do it.....
int_count=1; //Initialize to roll over next time through.
set_timer0(0);
setup_timer_0( RTCC_INTERNAL|rtcc_8_bit|rtcc_div_2);
SETUP_WDT(WDT_OFF); //DISABLED FOR TESTING
ENABLE_INTERRUPTS(INT_RDA); //RDA (Serial Receive Data).
enable_interrupts(global);
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
DO
{
if(--int_count==0) //has one second gone by ?
{
if(++SECONDS==60) //start again after one minute.
SECONDS=0;
int_count=10000; //Trial and error, 500-low,1000-low,5000-low,10000
CHECK_ALARM=1; //check alarms every second
}//end of --int count==0
if(check_alarm) //has one second gone by?
{//// Check the Digital Input Pin.
DIG_AMIOK=0xFF; //INITIALISE, ASSUMING NO ALARMS
IF(!INPUT(DIGIN1)) //CLECK EACH DIGITAL INPUT, ONE AT A TIME.
{
BIT_CLEAR(DIG_AMIOK,1); //This is for real, CLEAR THE ALARM BIT.
}
Else BIT_SET(DIG_AMIOK,1); //No alarm on input 1.
Check_Alarm=0; //reset flag
}//end of check_alarm
if((dig_amiok!=LAST_DIG)) //check for change of state in alarms
{
Write_EEPROM(0XD8,DIG_AMIOK); //FORCE A SAVE
LAST_DIG=DIG_AMIOK;
}
//////////////////////////////////////////////////////////////////////////////////////////
if(from_host) //from_host is a flag, set in the serial interrupt routine.
//by now, the array RMC_Data_In[] holds the 6 byte ModBus string.
{
output_high(pin_d6); //turn on a LED for testing
if(RMC_data_in[1]==3) //is this a "Read Register Function"?
{
if(RMC_data_in[2]==0) //"TRUE" EEPROM Area
{
putc(0x55); //repeat site address
putc(0x03); //repeat command (0x03)
putc(0x02); //number of bytes to follow
putc(0x00); //Low Byte Filler
putc(read_eeprom(RMC_Data_In[3])); //actual data from eeprom.
}//End of TRUE EEPROM Reads
}//End of all "READS"
output_low(pin_d6); //turn off the LED
from_host=0; //re-set flag.
}//END OF IF FROM_HOST...
/////////////////////////////////////////////////////////////////////////////////////
//// not much happening...
if(++silent_time>1000) //count, while waiting for another Serial Byte
{
silent_time=0; //reset silent serial time timer
byte_count=0; //reset byte counter. Clears a Runt.
}//end of silent_time>1000
}WHILE (TRUE); //"DO" IT ALL AGAIN.
} //end of Main.
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jan 24, 2005 2:34 pm |
|
|
Without examining your code in detail, I can think of a number
of reasons for this:
1. You could be getting several incoming characters in a short time.
The eeprom write takes several milliseconds. You're not servicing
the interrupt during that time, so an overrun occurs. You don't
have the ERRORS directive in your #use rs232 statement, so the
USART receiver locks up.
2. In some versions of the compiler, CCS didn't handle disabling/
enabling interrupts properly during writes to eeprom. |
|
![](templates/subSilver/images/spacer.gif) |
Nandus2000
Joined: 17 Sep 2008 Posts: 10
|
Write_EEPROM and RDA interrupt conflict |
Posted: Wed Jul 08, 2009 4:54 am |
|
|
Hi,
I've used #use rs232 statement in my code.
But still I've similar issue because I'm not able to serve RS232 RDA interrupt as program is busy in write_eeprom library function.
I'm using Compiler: CCS version 4.076.
Does anybody know that this conflict has been resolved in the latest version 4.093 at the moment?
Awating your prompt reply.
Thanks!! |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|