Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] Serial Communication Interrupt Flag in PIC18f4520 and mikrocpro for PIC

Status
Not open for further replies.
Hello brian,
Clock frequency is 20Mhz. I tried range of values from 33 to 25. But no result. 'Test' is Pin no 19. No relation with UART pins. Either UART1_init(9600) or manual settings is used. MAnual settings part is commented.
 

If the Bauds rate was wrong it wouldn't transmit or receive the expected character to/from another device but the RCIF would still work as expected anyway.

How exactly are you checking RCIF when you say it is set all the time? If simulating and using a breakpoint to freeze the program you must do it at the right place to see the RCIF operating. Which simulator and settings are you using?

Brian.
 

hello,


it seems some flag init are missing .. to valide the interrupt
see FIGURE 9-1: PIC18 INTERRUPT LOGIC on the datasheet

Nota: i don't know if a test on RCREG is enough to clear this register
so it is better to READ RCREG to be sure to erase RCIF flag.
you can not do RCIF_bit=0; Read only register

sdat must be volatile if used into the main...


test this

Code:
#include <math.h>
#define adjust 1000//500,1000
#define bright 1
#define MAX_CONTROL   PORTC.B5
#define TIMER_START_VALUE   250   //230,200,255,500
#define TIMER_START_VALUE_1 250  //210,160,254,255

[B]volatile[/B] unsigned char index,sdat=0,read=0,write=0;
volatile unsigned char input_string[12];
char FND_0=1,FND_1=2;

/*********************************************************/
void interrupt(){

   void Interrupts() iv 0x0008 ics ICS_AUTO
{
//UART1
           if((RC1IF_bit==1) && (RC1IE_bit==1))  if(PIR1.RCIF==1)
             {
                  Test=~Test;
                   if(RCSTA.OERR)
                 {
                   RCSTA.CREN=0;
                   Nop();
                   RCSTA.CREN=1;
                   }
                   if(RCSTA.FERR)
                   {
                    //FERR: Framing Error bit
                    //1 = Framing error (can be updated by reading RCREG register and receiving next valid byte)
                    sdat=RCREG;
                    }
                    MAX_CONTROL =1;
                    UART1_Write(RCREG);
                   MAX_CONTROL =0;
                  [B]  sdat=RCREG;  [/B]       // be sure to read RCREG register
                   if(sdat==64)
                    {
                                read=1;
                                MAX_CONTROL =1;
                                UART1_Write(FND_0);
                                MAX_CONTROL =0;
                        }
                         else
                            {
                                        write=1;
                                     MAX_CONTROL =1;
                                     UART1_Write(FND_1);
                                     MAX_CONTROL =0;
                                }
     }
           if(INTCON.TMR0IF){
                    TMR0L = TIMER_START_VALUE;
                    TMR0H = TIMER_START_VALUE_1;
                    TMR0IF_bit = 0;
                    }


}


void main() {

     TRISD = 0x00;            /*//PortD as output*/
     PORTD = 0x00;            /*//Initial value*/
     TRISC = 0b10000000;
     TRISB = 0x55;             //0 as o/p, 1 as i/p
     PORTB = 0x00;
     INTCON =0b11100000 ;           /*//0xc0;0xa0*/

     TMR0ON_bit = 0;          /*//Stop timer 0 during set up*/
     T08BIT_bit = 0;      /*// Enable 16 bit timer*/
     T0CS_bit = 0;        /*// use internal clock to trigger timer to count*/
     PSA_bit = 0;         /*// Use the prescaler to slow the timer down*/

     // prescaler
     
     T0PS0_bit = 0; //1             /*//for 16 bit timer 1/4 of clock freq   001*/
     T0PS1_bit = 1; //0
     T0PS2_bit = 0; //0

     TMR0L = TIMER_START_VALUE;
     TMR0H = TIMER_START_VALUE_1;

    /*TXSTA  = 0b00100000;
     RCSTA = 0b10010000;

     BAUDCON.BRG16 = 0;
     TXSTA.BRGH    = 0;
     //SPBRGH:SPBRG = 129;   //for 20MHz crystal
     SPBRG = 25;   //for 20MHz crystal*/


     UART1_Init(9600);
     Delay_ms(200);
     PIR1.RCIF=0;
     RCREG=0;

     PIE1 = 0b00100000;  //RCIE_bit=1    enabled RX it
     MAX_CONTROL=0;
     TMR0ON_bit = 1;       //start the timer
      
   [B]   RCIP_bit=1;    // see IPR1
        IPEN_bit=1;  // enable high priority see RCON
       GIE_bit=1;[/B]

         while(1){
                  
         };

}


if you want to see a printable caractere on your terminal
it is better to init like:

Code:
char FND_0='1',FND_1='2';
 
Last edited:

Don't write to the PORT registers (which you have hidden behind the MAX_CONTROL preprocessor name). When the processor supports them (as yours does) the rule is "read from the PORT, write to the LAT" to avoid RMW issues.
I would recommend that you do NOT put a potentially blocking function (UART1_Write) call into your ISR.
While it might work with this processor, in general I suggest that you read from the RCREG once and save the value into a local variable. You can then user that value as often as you like. Reading the RCREG multiple times *may* give you the last received value each time but it can also return the value the first time and anything it likes after that. (For other Microchip devices where there is a FIFO this is certainly true and so it is a good habit to get in to.)
Looking at the details of the RCIF bit in the PIR1 register, the data sheet shows it as "R-0" which means that the bit is 'read only' and therefore, writing to it will be a waste of time. However, it is cleared by the hardware when you read the RCREG which therefore reinforces my comment above.
I'd like to reinforce the comments from others that we really need to know how you are checking the RCIF bit to know that it is always high. Is the ISR being called when there are no characters sent to the UART?
Also, when I made my previous suggestion of writing a small program, I was thinking of something MUCH smaller than your latest version - more along the lines of something that didn't use interrupts (or timers or anything else) and simply initialised the oscillator and UART and used the RCIF to detect when a value is received which you can read. Using the debugger with a simple program like that you can easily see what the various bits and values are doing. When that works, then start adding the complications such as the interrupt processing and make sure that it is working...
Susan
 

Hi,
Clock frequency is 20Mhz. Test is pin no 19, no connection with UART. I tried values from 35 to 25, but no result. Either UART_init(9600) or manual settings has been used, to verify which one is working. When i look for single character using RCREG register sent through serial port, it works fine. But when i try to send string and try to collect them in an array and check for the single character i get garbage values and sometimes required values.
 

That information helps. Working reliably when a single character arrives but not a stream suggests your software is unable to 'unload' the RCREG before the next byte has arrived. It can also be caused by a Baud rate mismatch but I'm assuming we can eliminate that for now.

Remove all your code and just write a 'tight' loop to process the arriving data to see what happens. I do not use MikroC but I wonder if the delay routines are 'blocking', in other words they use software loops to waste time. They could delay the processor enough that it can not process the data and be ready for the next incoming byte before it arrives. It is good you added code to check and clear any framing and overrun error but that just resets the UART to clear the error condition, it doesn't actually fix the error.

You only seem to be using one interupt level so do you want to enable of disable the priority system.?
You don't need the delay after initializing the UART, I'm not sure why MikroC shows that in their examples. Even if you added a delay, it only has to be long enough for queued bytes to clear the UART transmit chain so ~2mS is more than enough. In your program it shouldn't matter though as you do not change the speed dynamically.

It might help if you stopped the simulation after a few characters have arrived and tell us the values in ALL the UART related registers. We can then see if the configuration looks OK while it is showing the fault symptoms.

Brian.
 

Code:
#include <math.h>
#define MAX_CONTROL   PORTC.B5
#define Test          PORTD.B0  //Pin 19

volatile unsigned char index=0,sdat=0,read=0,write=0;
volatile unsigned char input_string[12];
char FND_0='1',FND_1='2';

/*********************************************************/
void interrupt(){

     if(PIR1.RCIF==1){
            Test=~Test;

                   if(RCSTA.OERR){
                   RCSTA.CREN=0;
                   Nop();
                   Nop();
                   RCSTA.CREN=1;
                   }
                   /*if(RCSTA.FERR){
                   RCSTA.SPEN=0;
                   Nop();
                   Nop();
                   RCSTA.SPEN=1;
                   }*/
                        
                      else{
                      input_string[index]=RCREG;
                                                MAX_CONTROL =1;
                                                UART1_Write(input_string[index]);
                                                MAX_CONTROL =0;
                      if(index==10) index=0;
                      }
                                

     //PIR1.RCIF=0;
     }
}


void main() {

     TRISD = 0x00;            /*//PortD as output*/
     PORTD = 0x00;            /*//Initial value*/
     TRISC = 0b10000000;
     TRISB = 0x55;             //0 as o/p, 1 as i/p
     PORTB = 0x00;
     INTCON =0b11100000 ;           /*//0xc0;0xa0*/



     TXSTA  = 0b00100000;
     RCSTA = 0b10010000;

     BAUDCON.BRG16 = 0;
     TXSTA.BRGH    = 0;
     //SPBRGH:SPBRG = 129;   //for 20MHz crystal
     SPBRG = 32;   //for 20MHz crystal


     //UART1_Init(9600);
     //Delay_ms(200);
     PIR1.RCIF=0;
     RCREG=0;
     PIE1 = 0b00100000;  //RCIE bit enabled
     PIR1.RCIF=0;
     IPR1.RCIP = 1;
     IPR1.TXIP = 1;
     RCON.IPEN = 1;
     PIE1 = 0b00100000;  //RCIE bit enabled

     MAX_CONTROL=0;
     index=0;

         while(1){

         };

}
Now only serial interrupt i am checking in interrupt routine. No timer interrupt. And suggested IPR1 and RCON bits set. I am toggling the 'Test' bit to check if interrupt is occurring or not. So when interrupt occurs, voltage on Test pin is 2.5V, that means interrupt is occurring(if i am not wrong). IN above code, when i comment framing error portion, there is some output on serial window. If i uncomment 'if(RCSTA.FERR)' portion there is no output on serial window.
Another instance showing that RCIF bit is continuously high is when 'UART1_Write(RCREG)' and framing error portion commented, continuous garbage value is there. If i save RCREG in an array and then write 'UART1_Write(input_string[index])' same garbage value appears but with some delay, not continuous. What must be the issue now?

- - - Updated - - -

Here is the screen shot of serial window. Please look at it. At the left bottom corner you can see a green dot, showing it is connected and operating.
serial_window2.png

- - - Updated - - -

@paulfjujo

Pardon me Paul, however i didn't find RC1IF and RC1IE bits in datasheet. Where they resides?

- - - Updated - - -

@paulfjujo
shall i take it as RCIF and RCIE bits

- - - Updated - - -

I am sorry, i forgot to increment 'index' variable in the 'else' part in interrupt routine. I did that and checked the code. THis time no value came on serial window. Again commented that part in which RCREG is getting stored in an array and directly displayed the RCREG values. Still same garbage values.:bang:

- - - Updated - - -

In case of code provided by Paul, it is always printing 2.
serial_window3.png
 

hello

shall i take it as RCIF and RCIE bits

Yes... i used mikroC pro version 6.62
it is more easy to use this syntaxe , else you must add the register name before the bit name.

In case of code provided by Paul, it is always printing 2.
What char or string do you send ?
because ,as you coded ,(in post #23) except char value =64,it will allways print '2'

in case of FERR you must read RCEG, to RAZ FERR flag.

UART1_Write(input_string[index]);
you can replace this by
TXREG1=(input_string[index]);
 

Hi paul,
2 is getting printed without any input. Means 'else ' part is always getting executed .

- - - Updated - - -

@paul,
you also must have USART terminal in mikroc right, are u getting same result using this code??
 

hello,

i don't have a PIC18F4520 but i did this test on 18F45K22
and it is working with my terminal . ( not the standart UART terminal, but PC side USB <-> trough FTDI <-> PIC UART1
so like direct UART1..
same external behavior .

put #define PIC18F45K22 as a comment , to test with your MCU...
and take care about all remarks inside the source code..

another remark:
if you want to use the input_string .... a string must have a zero terminator !
you can use a special caractere to define end of message sended by the keyboard terminal
most ofen CR is used as validation or end of message..
the in RX interrupt test sdat==CR to store 0 indo the table input_string instead of CR..
then you can use it as a "normal string"
lke UART1_Write_Text(input_string);



Code:
 // choice of MCU
#define PIC18F45K22

#include <built_in.h>
#include <math.h>

// use LAT instead PORT for output on PIC18F
#ifdef PIC18F45K22
#define Test          LATD.B0  // on my board
#define MAX_CONTROL   LATD.B1
#else
#define Test          LATD.B0  //Pin 19
#define MAX_CONTROL   LATC.B5
#endif


volatile unsigned char index=0,sdat=0,read=0,write=0;
volatile unsigned char input_string[12];
// char FND_0='1',FND_1='2';

// high level of interrupt
void Interrupts() iv 0x0008 ics ICS_AUTO
{
    // if you have more than one interrupt
    // it is better to check also the corresponding  Autoristaion bit
    if((RC1IF_bit==1) && (RC1IE_bit==1))
    {
        Test=~Test;
        if(RCSTA1.OERR)
        {
            RCSTA1.CREN=0;
            _asm Nop;   // usefull ??
            _asm Nop;
            RCSTA1.CREN=1;
          }
          if(RCSTA1.FERR)
          {
           // don't touch SPEN_bit !
           //  bit 7 SPEN: Serial Port Enable bit
           //    1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
           sdat=RCREG1;   // to erase  FERR flag
           }
           // read RCREG , so RCIF will be cleared abd you get the content of RCREG
          sdat=RCREG1;
          MAX_CONTROL =1;
          TXREG1=sdat;      // echo receiveid char to TX UART
          input_string[index]=sdat; // store the reading char
          index++;
          MAX_CONTROL =0;
          index=0;
     }
}


void main()
 {
   // conditional Hardware config
   #ifdef PIC18F45K22
     ANSELB  = 0;
     C1ON_bit = 0;               // Disable comparators
     C2ON_bit = 0;
     PORTB = 0x00;           // set PORTB to FF
     TRISB = 0;           // designate portb pins as output
     PORTA = 0xFF;
     TRISA=0b11101111 ;   // RA4 as output  RA0,1,2,3,5=input
     ANSELA=1;   // RA0 as analog
     TRISE=0;
     PORTE=0xFF;
     TRISD=0x00; // all outputs
     ADCON0 =1 ;
     ADCON1 = 0x8D  ;    //B'10001101'
     PORTC = 0xFE;       // set PORTC to $FF
     TRISC=0b10111101 ; //RC1 as output
     #else
     // with your PIC
     TRISD = 0x00;            /*//PortD as output*/
     PORTD = 0x00;            /*//Initial value*/
     TRISC = 0b10000000;
     TRISB = 0x55;             //0 as o/p, 1 as i/p
     PORTB = 0x00;
   #endif
     //INTON 
     //GIE/GIEH  PEIE/GIEL  TMR0IE  INT0IE  RBIE  TMR0IF  INT0IF  RBIF
     INTCON =0;
     TMR0IE_bit=0;   // timer0 IT not used here

     //let's MikroC UART library do the job !
     UART1_Init(9600);
     
     #ifdef PIC18F45K22
       UART1_Write_Text("\r\nTest with PIC18F45K22\r\n");
     #else
     UART1_Write_Text("\r\nTest with PIC18F4520\r\n");
     #endif

     //  PIR1.RCIF=0;  //  you can NOT ERASE this bit !
     sdat=RCREG;  // here you erase RCIF bit !
     //   RCREG=0;  // you can not eras it, read only register !
     PIR1.RCIF=0;
     IPR1.RCIP = 1;
    // don't arme interrupt TX UART if not used
    //   IPR1.TXIP = 1;   interrupt for transmit not used here !
     RCON.IPEN = 1;
     MAX_CONTROL=0;
     index=0;
     RCIE_bit=1;    // idem as PIE1.RCIE=1;  bit enabled
     GIE_bit=1;    // idem as INTCON.B7=1;

      while(1)
         {
    
         };
}


Test_UART.jpg
 
Last edited:

Hi paul,
Here is the code with little modification
Code:
#include <math.h>
#define MAX_CONTROL   PORTC.B5
#define Test          PORTD.B0  //Pin 19

volatile unsigned char index=0,sdat=0,read=0,write=0,garbage=0;
volatile unsigned char input_string[12],*string;
char FND_0='1',FND_1=2;

/*********************************************************/
//void interrupt(){
void Interrupts() iv 0x0008 ics ICS_AUTO{

  if((RCIF_bit==1) && (RCIE_bit==1)) {

                      Test=~Test;
                      if(RCSTA.OERR)
                      {
                      RCSTA.CREN=0;
                      _asm Nop;   
                      _asm Nop;
                      RCSTA.CREN=1;
                      garbage=RCREG;
                      }
                      if(RCSTA.FERR)
                      {
                      
                      sdat=RCREG;   
                      }
                      
                      sdat=RCREG;
                      
          MAX_CONTROL =1;
          TXREG = sdat;     
          input_string[index]=sdat; 
          TXREG=input_string[index];
                  /*if(sdat==64) read=1;
                  if(sdat==63) write=1;*/
          index++;
          MAX_CONTROL =0;
          //if (index==5)
          index=0;
      }

}


void main() {

     TRISD = 0x00;            /*//PortD as output*/
     PORTD = 0x00;            /*//Initial value*/
     TRISC = 0b10000000;
     TRISB = 0x55;             //0 as o/p, 1 as i/p
     PORTB = 0x00;
     INTCON =0b11000000 ;           /*//0xc0;0xa0*/



    /*TXSTA  = 0b00100000;
     RCSTA = 0b10010000;

     BAUDCON.BRG16 = 0;
     TXSTA.BRGH    = 0;
     //SPBRGH:SPBRG = 129;   //for 20MHz crystal
     SPBRG = 31;   //for 20MHz crystal*/


     UART1_Init(9600);
     Delay_ms(2);
     //PIR1.RCIF=0;
     sdat=RCREG;
     PIE1 = 0b00100000;  //RCIE bit enabled
     PIR1.RCIF=0;
     IPR1.RCIP = 1;
     //IPR1.TXIP = 1;
     RCON.IPEN = 1;
     PIE1 = 0b00100000;  //RCIE bit enabled
     INTCON.GIE=1;
     MAX_CONTROL=0;
     index=0;

         while(1){
                      if(read==1){
                                MAX_CONTROL =1;

                                UART1_Write_Text("\r\nTest with PIC18F4520\r\n");

                                MAX_CONTROL =0;
                      read=0;
                      }
                      if(write==1){
                                MAX_CONTROL =1;
                                UART1_Write_Text("\r\nMay be wrking\r\n");
                                MAX_CONTROL =0;
                      write=0;
                      }


         };

}
Observations are as below.

- - - Updated - - -

1) In interrupt routine, any character sent should reproduce on UART window. However it is not.:bang:
2) In interrupt routine ,if i uncomment matching 'sdat' with 64 and 63, '@' or '?' are getting printed with relative statement getting printed on serial window two times for each character sent once.
3) If 'sdat' matching part is commented, even '@' and '?' won't get printed.
Why such a strange behavior.:roll:
 

Zip and post your complete mikroC PRO project file. If you have Proteus file then zip and post also that. I will fix the code and post it here.
 

Have you tried by connecting a pullup resistor on to RX pin. it will prevent the pin from floating. Try to add some extra code to check overrun error and framing error. One more suggestion, add a line at the start of ISR to disable the interrupt like GIE=0, which will prevent another interrupt event before the previous one is completely processed. Then enable interrupt again at the end of ISR.
 

statement getting printed on serial window two times for each character sent once.

Code:
  TXREG = sdat;     
  input_string[index]=sdat; 
   [B][COLOR=#FF0000]TXREG=input_string[index];[/COLOR][/B]

here you print out 2 times the result of RCREG..
remove TXREG=input_string[index];

maybe you can add, a test on Empty situation for transmit buffer
but i thing not necessary when sending char by char
it is only a good rule..

Code:
//  TRMT: Transmit Shift Register Status bit// 1 = TSR empty   0 = TSR full
 while l(TXSTA.TMRT==0) ; // wait until empty register
 TXREG = sdat;     
  input_string[index]=sdat;  // echo on terminal
 
Last edited:

Hi paul,
Ok 'TXREG=input_string[index]' was to check if array has some value or not. So it does. But when i increment the array for each successive received character, and send it on UART, nothing is getting printed. Only for the '0' th index values gets printed. And no successive values.

- - - Updated - - -

@pic programmer
The code posted above is the one to test serial communication. Do u want me to post complete code?

- - - Updated - - -

@Mukesh,
I will try to make changes u suggested.

- - - Updated - - -

I thought it's only to store the incoming string characters in an array at every serial interrupt and check if it is the desired one or not. But it's not as simple as that. I couldn't understand the behavior of serial interrupt and it's associated registers. They are behaving very strange. I am not getting where is the bug in software??
 

add a line at the start of ISR to disable the interrupt like GIE=0, which will prevent another interrupt event before the previous one is completely processed. Then enable interrupt again at the end of ISR.

if using High level interrupt only , it is not necaissairy, when inside the interrupt , GIE will return to 1 state
after end of interrupt .. automatic behavior.

- - - Updated - - -

Hi paul,
But when i increment the array for each successive received character, and send it on UART, nothing is getting printed. Only for the '0' th index values gets printed. And no successive values.[/COLOR]
Code:
[B][COLOR=#0000FF] index++[/COLOR][/B];
          MAX_CONTROL =0;
          //if (index==5)
         [COLOR=#FF0000] index=0;[/COLOR]

because you RAZ index after incrementing..

How do you check the content of the array ?
Code:
  if(write==1){
                                MAX_CONTROL =1;
                                UART1_Write_Text("\r\nMay be working\r\n");
                             [B][COLOR=#0000CD]  for (i=0;i<index,i++) UART1_Write (input_string[i];[/COLOR][/B]
                              UART1_Write('\r');UART1_Write('\n'); // next line
                                MAX_CONTROL =0;
                      write=0;
                      }
 

For my education as I do not use MikroC, does the "UART1_Write()" function wait for the transmit buffer to be empty or does it just blindly pass the parameter to the TXREG?
Code:
for (i=0;i<index,i++) UART1_Write (input_string[i];
is missing a closing bracket after the ']'.

djc - in normal expected operation, what would a typical serial input string look like? Would it have a fixed length and would it have a character to mark the start and/or end of the string?

Did a quick check here and a 38,400 serial link running over a cable length of >50 metres (using RS422 and CAT-5 cable) has transfered more than 2^10 bytes without any errors using an 18F46J11 at one end and a 16F628A at the other so it CAN be done. Both ends use similar but not identical serial routines to yours and both ends also run other tasks at the same time.

Brian.
 

Hi paul,
i commented if(i==5) later, first i checked with incremented value of index and did 'TXREG=input_string[index]', sent various charaters and string of characters. But only those acters for which sdat was compared and its associated statements in main were printed and no other charaters or string values were getting printed even though 'if(i==5)' was uncommented.
serial_window4.png

- - - Updated - - -

Hi paul,
i commented if(i==5) later, first i checked with incremented value of index and did 'TXREG=input_string[index]', sent various charaters and string of characters. But only those acters for which sdat was compared and its associated statements in main were printed and no other charaters or string values were getting printed even though 'if(i==5)' was uncommented.
serial_window4.png

- - - Updated - - -

Hi brian,
String to be sent is 10 characters. first 2 alphabets, then 2 digits , then 2 alphabets and then 4 numbers. Like
'WA12MH1234 '. Yes start and stop bits will be incorporated with it. It's my choice which start and stop bits to be choose. That's where the issue is. Able to receive single character but not whole string. And even that single character is getting printed when sdat compairing is there.:thinker:
 

This is the code I wrote and it works fine in Proteus. It is not tested in hardware.

Code:
#define MAX_CONTROL   PORTC.B5
#define Test          PORTD.B0

char input_string[12];
char index = 0;

void interrupt() {
    if(RCIF_bit) {
        if(OERR_bit) {
            CREN_bit = 0;
            CREN_bit = 1;
            OERR_bit = 0;
        }

        input_string[index] = UART1_Read();
        UART1_Write(input_string[index]);
        index++;
        input_string[index] = '\0';


        RCIF_bit = 0;

        if(index >= 12)index = 0;

        MAX_CONTROL = 0;
    }
}

void main() {

    TRISA = 0xC0;
    TRISC = 0xC0;
    PORTC = 0x00;
    LATC = 0x00;
    
    UART1_Init(9600);
    Delay_ms(200);

    RCIE_bit = 1;
    RCIF_bit = 0;

    INTCON = 0xC0;

    while(1) {



    }
}
 

Start and stop bits are always present in async data streams otherwise it would be impossible to frame the data bits. A serial character is typically 10 bits long, one start bit, 8 data bits then one stop bit. Sorry if my question was misleading, what I meant was "has each string got a start and end character"? For example, my strings are sent like this <ASCII STX><1 to 32 ASCII characters><ASCII CR>. If you do not use at least one reserved character to mark a position in the string it can be difficult to know where one string ends and the next starts.
Here is an extract from my code, it will not work as a substitute for yours but it will demonstrate how I capture strings. It is called when the ISR sets a byte to say data is in the UART receive register and the WaitRx() function retrieves the character that arrived.
Code:
//*******************************************************************************
// Called when a byte from the host is received by the UART
void ByteFromBus()
{
	BusRx = WaitRx();
	
	if(BusRx == STX) //start of a new transmission block?
	{
		BusRxPtr = 0;
		*BusRxBuffer = 0;
		return;
	}
	
	if(BusRx ==	CR) //end of a transmission block	
	{
		if(BusRxBuffer[0] == GATEBOX_ID)  // check if for this module
		{
			switch(BusRxBuffer[1])
			{
				case 'Q': SendResponse();
									break;
				case 'I': IDResponse();
									break;
				case 'L': if(BusRxBuffer[2] == '1') GATE_LED = 1;
									    else GATE_LED = 0;
									break;
				case 'U': if(BusRxBuffer[2] == '1')
									{
										UNLOCK = 1;
										RelockTimer = RELOCK_TENTH_SECONDS;
									}
									else
									{
										UNLOCK = 0;
										RelockTimer = 0;
									}
									break;
				case 'B': Beeper();
									break;
				case 'G': if(BusRxBuffer[2] == '1') GreenLEDEnabled = 1;
									else GreenLEDEnabled = 0;
									break;
				case 'R': if(BusRxBuffer[2] == '1') RedLEDEnabled = 1;
									else RedLEDEnabled = 0;
			}
		}
				
		BusRxPtr = 0;
		BusRxBuffer[0] = 0;
	}
		
	if(BusRxPtr < BUS_RXBUFFER_SIZE) // prevent buffer overflow
	{
		BusRxBuffer[BusRxPtr++] = BusRx;
		BusRxBuffer[BusRxPtr] = 0;
	}
		
}
it works like this: each character arriving is checked see if it is an ASCII STX (0x02), if it is the "BusRxBuffer" is cleared by writing a zero terminator in it's first location and a pointer to the current buffer address offset is set to zero. If it wasn't STX, it is then checked for ASCII CR (0x12) which would indcate the end of the string had been found. If it was CR, the first character of the string is checked for a particular ID number, this is because in my application there are several of these modules sharing the same data stream and only one should respond when it's ID matches. The following characters are used to call different functons. If the character wasn't STX or CR, it must be part of the serial data so it is added to the next location in BusRxBuffer and the pointer to the buffer is incremented. Finally, a zero is appended to the end of the data in BusRxBuffer so the standard 'C' string functions will work with it. (C strings always end with a zero).

The editor in my compiler is set to use indents of 2 characters so the Edaboard formatting may make it wider that it should be - sorry there's nothing much I can do about that.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top