CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

The serial port is unable to receive data with the interrupt

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stefsun



Joined: 23 May 2007
Posts: 22

View user's profile Send private message

The serial port is unable to receive data with the interrupt
PostPosted: Thu Mar 20, 2008 2:28 am     Reply with quote

The serial port is unable to receive data with the interrupt correctly

In the beginning, Receive data with interrupt and Transmit data with putc, have the following problem. afterward transmit and receive data both use the interrupt, the function is still not work correctly, when the programme run to workmode1, PIC can’t receive data correctly with interrupt.

Programme to achieve the function of waiting for PC sent 05, and then send ACK 06 to the PC,
Then wait for the PC transmit work methods
03 11 01 95 for workmode1
03 12 01 95 for workmode2
03 13 01 95 for workmode3
03 14 01 95 for workmode4
workmode2, workmode3, workmode4, I have not written specific realization process,
However, when PC sent 03 11 01 95 to start workmode1, after a while, PC sent 03 12 01 95 to PIC ,PIC is running workmode1 as usual, PIC did not stop, continue to send data to the PC, PIC didn’t send 0X12 to the PC.


can anyone help me?


Code:

#include <18F4523.h>                             // PICF4523 header file
#device ADC=12                                   // 12 bits ADC
#use delay(clock=4000000)                       // for 4Mhz crystal
#fuses XT, NOWDT, NOPROTECT, NOLVP               // for debug mode
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, Parity=N, Bits=8, ERRORS)

#define  KEYHIT_DELAY   500     // in milliseconds
#define HEAD 0X03  //data header
#define TAIL 0X95  //data tailer
#define RDSize 20
#define BUFFER_SIZE 32
#define T_BUFFER_SIZE 32

int ScanMode = 0;
int ReceiveData[RDSize];
int ReceiveChar = 0;
int i = 0 ;
int n = 0 ;
long x;

byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;

BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;

#define bkbhit (next_in!=next_out)

#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

//#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}


//-----------------------------------------------------
// commport communications: buffered, interrupt & hardware driven
#INT_TBE
void t_serial_isr() {
   putc(t_buffer[t_next_out]);
   t_next_out = (t_next_out + 1) % T_BUFFER_SIZE;
   if(t_next_in == t_next_out)
      {
    disable_interrupts(int_tbe);
   }
}

// bputc() modified to prevent lockups:
void bputc(char c) {
   short restart;
   int ni;
   restart = t_next_in == t_next_out;
   t_buffer[t_next_in] = c;
   ni=(t_next_in + 1) % T_BUFFER_SIZE;
   while(ni == t_next_out)
         {
         enable_interrupts(int_tbe); //make sure int_tbe is enabled to provide exit (assuming this triggers int)
         }
   t_next_in = ni;
   if(restart)
      {
      enable_interrupts(int_tbe);
      }
}

//
char timed_getc() {
   long timeout;
   char retval;

   timeout=0;
   while(!kbhit() && (++timeout< (KEYHIT_DELAY*100)))
      delay_us(10);
   if(kbhit())
      retval = getc();
   else
      retval = 0;
   return(retval);
}


long AcquireVol44()

  long C44Vol;
  SET_TRIS_A( 0XFF );
  SETUP_ADC_PORTS( AN0_TO_AN1 );
  SETUP_ADC( ADC_CLOCK_DIV_32 );
  SET_ADC_CHANNEL( 0 );   
  C44Vol = READ_ADC();
  return C44Vol;
}

long AcquireVol45()
{
  long C45Vol;
  SET_TRIS_A( 0XFF );
  SETUP_ADC_PORTS( AN0_TO_AN1 );
  SETUP_ADC( ADC_CLOCK_DIV_32 );
  SET_ADC_CHANNEL( 1 );   
  C45Vol = READ_ADC();
  return C45Vol;
}

void DataHandle()
{

   while(bkbhit)
   {
      ReceiveChar = bgetc();
      while( ReceiveChar != 0X03 )//data header
         {
            while( bgetc() != 0X95)//data tailer
               ;
            ReceiveChar = bgetc();
         }
      ReceiveData[0] = ReceiveChar;
      ReceiveData[1] = bgetc();
      n = ReceiveData[2] = bgetc();
      
      for( i = 0 ; i < n ; i++ )
         ReceiveData[i+3] = bgetc();
      //
      
      if( ReceiveData[i+2] != 0X95 )//judge the data
         break;
      
      switch( ReceiveData[1] )
         {
            case 0X11:  //workmode1
               ScanMode = 1;
               putc( 0X11 );
               break;
            case 0X12:  //workmode2
               ScanMode = 2 ;
               putc( 0X12 );
               break;
            case 0X13:  //workmode3
               ScanMode = 3 ;
               putc( 0X13 );
               break;
            case 0X14:  //workmode4
               ScanMode = 4 ;
               putc( 0X14 );
               break;
            default:     
               ScanMode = 0;
               putc( 0x99 );
               break;
         }
      }
}


void SendData(int data[],n)
{
   int i;
   bputc( HEAD );
   for(i = 0; i < n ; i++)
      {
         bputc( data[i] );
      }         
      bputc( TAIL );
}

void main()
{
   long C44Vol,C45Vol;
  int8 HighVolLow,HighVolHigh,C44VolLow,C44VolHigh,C45VolLow,C45VolHigh;
  long HighVolBegin=30000,HighVolEnd=32000;
   
   char LinkSerial=0;//
   
   SET_TRIS_A( 0XFF );
   SET_TRIS_B( 0X00 );
   SET_TRIS_C( 0X80 );
   SET_TRIS_D( 0X00 );
   SET_TRIS_E( 0X00 );
   
   disable_interrupts(GLOBAL); // all interrupts OFF
  disable_interrupts(INT_RDA); // RS232 OFF
 
     while( LinkSerial !=5 )
   {
               
      LinkSerial = timed_getc();
      
      if( LinkSerial == 5 )
         putc( 0X06 );//ACK 06
      else
         putc( LinkSerial );
   
  }
   
   enable_interrupts(global);
   enable_interrupts(int_rda);
   enable_interrupts(int_tbe);
   
   while(true)
   {
         DataHandle();

      while( ScanMode == 1)
      {
        for( x=HighVolBegin; x<=HighVolEnd; x++)
        {
              if(bkbhit)
                 DataHandle();
              
              if( ScanMode == 1 )
                 {                        
                    C44Vol = AcquireVol44();
                    C45Vol = AcquireVol45();            
                    HighVolLow = make8(x,0);
                    HighVolHigh = make8(x,1);      
                    C44VolLow = make8(C44Vol,0);
                    C44VolHigh = make8(C44Vol,1);
                    C45VolLow = make8(C45Vol,0);
                    C45VolHigh = make8(C45Vol,1);
     
                    buffer[0]=HighVolLow;
                    buffer[1]=HighVolHigh;
                    buffer[2]=C44VolLow;
                    buffer[3]=C44VolHigh;
                    buffer[4]=C45VolLow;
                    buffer[5]=C45VolHigh;
                             
                    SendData(buffer,6);
                    
                    delay_ms(1000);
                 }
              else
                 {
                    break;
                 }
 
          }

      }
   }//while true
}//main
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

serial in
PostPosted: Sun Mar 23, 2008 4:19 am     Reply with quote

i don't understand your program exactly but:
using delay is tricky. interrupts are not served during delays!!!
delay_ms(1000); is 1 second with no int_RDA or int_TBE served.
in 9600bps one byte (start+8*data+stop) is aprox 1.042ms
best regards
joseph
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Sun Mar 23, 2008 8:57 am     Reply with quote

gjs_rsdi wrote:
Quote:

using delay is tricky. interrupts are not served during delays!!!
delay_ms(1000); is 1 second with no int_RDA or int_TBE served.

Wrong.
The conditions to trigger an interrupt are:
1) That the corresponding interrupt flag is enabled (INT_RDA in this case)
2) The GLOBAL Interrupt is enabled
3) The trigger event is produced (Rx going down signal).

Sofware delays are time consuming loops, the MCU does not know if it is running in such loop.

Regarding the posted code:
In this function add the following:
Code:

void DataHandle()
{
   disable_interrupts(int_tbe);
   ..............
   your code
   ..............
   enable_interrupts(int_tbe);
}


Quote:

#define KEYHIT_DELAY 500 // in milliseconds


Then in your code:
Code:

(++timeout< (KEYHIT_DELAY*100)))

you get 500000 msec !!!
is this time really what you want to wait ?


Humberto
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

delay
PostPosted: Sun Mar 23, 2008 4:11 pm     Reply with quote

Humberto you are right.
i put my delay in wrong place (long time ago) and I assumed that is not serving interrupts during delays.
best regards
joseph
baltazar_aquino



Joined: 16 Mar 2008
Posts: 27

View user's profile Send private message

PostPosted: Wed Mar 26, 2008 11:23 am     Reply with quote

Can someone out there help trace the problem? I'm also getting this interrupt not being responded to. I even tried the example EX_SISR.C provided by CCS C but the problem remains. It is problematic only in PIC18F2550 and probably on other 18F but it runs Ok on my PIC16F877a. I traced the assembly code in the lst file but everything seems to be ok. It is just that the interrupt is not being serviced. My version is 4.057 and here is another test code that run well on 877a but doesn't on 18F2550:
During the waiting time (4s) try to send something from your PC thru the RS232
Code:


#include <18F2550.h>
#device adc=8
#use delay(clock=24000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
char tx;  // we will send this out later

#int_rda
void rx_isr()
{tx = getc();} // this one works well on 877a

void main()
{

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);


   // TODO: USER CODE!!
   enable_interrupts(int_rda);
   enable_interrupts(global);
   while(1)
   { printf("Let's take a nap...\r\n");
     delay_ms(4000);
     printf("Character=> ");
     putc(tx);    // the value doesn't change even if you send something
     
   }

}

I purposely removed the #FUSEs as i am using a bootloader.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 26, 2008 1:00 pm     Reply with quote

Try a more a more simple test program, as shown below.

I don't have 18F2550, but I do have an 18F4550. I don't have a 24 MHz
oscillator, but I do have a 25 MHz "can" oscillator. You didn't show your
fuses (the bootloader fuses), so I used the ones shown below. I tested
this program with vs. 4.057 on a PicDem2-Plus board. It worked OK.

If it doesn't work, I suspect some hardware problem. It could be
a missing MCLR pullup resistor (10K for ICD2, or 47K for ICD-U40),
or some of the Vdd and Vss pins may not be connected to the power
supply, or something wrong with the oscillator circuit. I also strongly
suspect the bootloader fuses are in "LVP" mode, or have the wrong
oscillator setting.
Code:
#include <18F4550.h>
#fuses EC_IO, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=25000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)


#int_rda
void rx_isr()
{
char c;

c = getc();
putc(c);

}

//==========================
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

while(1);
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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