USART interrupt example

General discussion on mikroC.
Author
Message
drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

USART interrupt example

#1 Post by drdoug » 14 Apr 2009 16:11

Since someone seems to be asking for an example every week, I am posting a USART example with interrupt. The example stores the incoming data into an array and can then be manipulated once the flag is received.
Feel free to make comments or correct inefficiencies. The code is tested and works as far as I can tell but I'm no professional.

Code: Select all

// *******************************************************
// This code will read in the UART data and store the result
// in an array.
//  written in mE C; Default priject settings
//  Tested with EP4 Board and 16F877A 8Mhz
//
//  and a USB-serial adapter.
//  Use at your own risk!!!!
// ********************************************************

 const short n = 20;
 char rxchar, i = 0, flag = 0; // Variable for storing the data from UART and array counter
 unsigned char rxarray[n];   // array to store the received charaters

void interrupt () {
  if (PIR1.RCIF) {          // test the interrupt for uart rx
    rxchar = Usart_Read();  //
    rxarray[i] = rxchar;
    i++;
    // ******************************************************
    // Only select one of the following statements
    if (rxchar == 36) {  // select this if looking for a terminating character
    //if (i == n) (         // select this if looking for a number of characters
      flag = 1;
      } // end if (rxchar == "$")
    } // end  if (PIR1.RCIF)
  } // end interrupt
  
  
void main () {
unsigned short j;

 INTCON.GIE = 1;
 INTCON.PEIE = 1;
 PIE1.RCIE = 1; //enable interrupt.
 Usart_Init(9600);
 
 while(1) {   // Begin endless loop
  // This section is where you tell the program what to do with the data once it
  // has all arrived
  if (flag ==1) {
    j = 0;
    while(j < i) {
     Usart_Write(rxarray[j]);
     j++;
     } // end while(rxarray[i])
    i = 0;
    flag = 0;
  } // end if (flag)
  //************************
  // You can place other things to do in your program here
  // i.e. ADC_readings, turn on outputs, etc.
  // ***********************
  
 } // end while
} // end main

Nick101
Posts: 339
Joined: 06 Aug 2006 15:32
Location: Texas
Contact:

#2 Post by Nick101 » 18 Apr 2009 19:00

Additional example.

Code: Select all

/*
 * Project name:
     UART example using interrupt
 * Copyright:
   
 * Description:
      initial UART using Usart_init(), enable RCIE for interrupt
      store incoming data in Rx_buff (maximim 31 characters)
      ,no error check,inside ISR untill timeout occur then send 
      it back from main()
 * Test configuration:
     MCU:             PIC16F886
     Dev.Board:       -
     Oscillator:      HS, 16.0000 MHz
     Ext. Modules:    -
     SW:              mikroC v8.2.0.0
 * NOTES:

*/
char Rx_buff[32];
char New_Flag = 0;
char *Rx_buff_ptr;
void interrupt(){
     char i = 0;
     unsigned timeOut = 0;
     if (PIR1.RCIF) {
         while (timeOut < 20000){
              if (Usart_Data_Ready()){
                 Rx_buff[i] = Usart_Read();
                 i++;
                 Rx_buff[i] = 0; // Add NULL
                 timeOut = 0;    // reset timeout
              }
              timeOut++;
              }
         New_Flag = 1;
     }
}



void main(){
     TRISB = 0;
     PORTB = 0;
     ANSELH = 0;
     INTCON.GIE = 1;
     INTCON.PEIE = 1;
     PIE1.RCIE=1;    //enable receive interrupt
     Usart_init(9600);
     while(1){
          if(New_Flag){
               New_Flag = 0;
               Rx_buff_ptr = &Rx_buff[0];
               while(*Rx_buff_ptr) {
               Usart_Write(*Rx_buff_ptr);
               Rx_buff_ptr++;
               }
          }
     }
}
Nick
[url]http://www.pic_examples.byethost3.com/[/url]

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#3 Post by drdoug » 19 Apr 2009 03:40

Thanks for posting a reply.
Why have a timeout in the interrupt?
Doesn't the Usart_DataReady() cause a re-entrancy problem?

Nick101
Posts: 339
Joined: 06 Aug 2006 15:32
Location: Texas
Contact:

#4 Post by Nick101 » 19 Apr 2009 04:53

Hi,
drdoug wrote: Why have a timeout in the interrupt?
Simplicity, the timeout loop check can be move to somewhere else.
drdoug wrote:Doesn't the Usart_DataReady() cause a re-entrancy problem?
No, re-entrancy occurs when a function [Usart_DataReady(),in this case] is also called from somewhere else beside ISR.
Nick
[url]http://www.pic_examples.byethost3.com/[/url]

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

#5 Post by zristic » 19 Apr 2009 09:17

The examples are missing check agianst buffer overflow and framing errors. In the case of any of the two the USART module will stop receiving bytes.

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#6 Post by drdoug » 19 Apr 2009 12:26

Excellent suggestion, I try to make the additions. Or someone else can feel free to beat me to it.

mcu_chip
Posts: 53
Joined: 02 Mar 2009 17:52

#7 Post by mcu_chip » 21 Apr 2009 22:14

When do you send it?

Mince-n-Tatties
Posts: 2780
Joined: 25 Dec 2008 15:22
Location: Scotland

#8 Post by Mince-n-Tatties » 22 Apr 2009 20:26

i would do it this way round

PIE1.RCIE=1;
INTCON.PEIE = 1;
INTCON.GIE = 1; //

i would always enable GIE bit last.

tongbram
Posts: 66
Joined: 08 Dec 2008 10:16

#9 Post by tongbram » 19 Jun 2009 06:26

hi Nick101.....please can you send me the complete folder for the above code. i tried it but no luck. i think i m doing some thing wrong in the configuration setting. but the same configuration setting is working in another compiler.....my e-mail is t_manibabu@yahoo.com

Nick101
Posts: 339
Joined: 06 Aug 2006 15:32
Location: Texas
Contact:

#10 Post by Nick101 » 19 Jun 2009 16:59

Hi,
I assume you've got compiler errors. The code is not for "PRO" version. If you use "PRO" version, you need a bit change on all USART routines. If you're not use 16F886, ANSELH should be removed. In fact, PORTB is not use, so you can remove all PORTB set up -- PORTB, TRISB and ANSELH.
Regards,
Nick
[url]http://www.pic_examples.byethost3.com/[/url]

Hamda binte Ajmal
Posts: 2
Joined: 20 May 2011 20:01

Re: USART interrupt example

#11 Post by Hamda binte Ajmal » 20 May 2011 20:16

Hey,
MCU = pic18f452

I wrote a code, where the program keeps on reading data from Soft_UART, but when an interrupt occurs i.e if (PIR1.RCIF) (Data is ready on UART1 ) it shoukd read this data and take necessary action ! When i compile this code, i gives me reentrancy errors for LCD usage and UART1_Write_Text.
I understand these errors, but have to use UART1_Read_Text on other places in code as well, can anyone suggest me how to avoid this ?
here a piece of code

Code: Select all

void interrupt() {
/*if(timer==1)
  {cnt++;}               // Increment value of cnt on every interrupt
  TMR0L  = 96;
  INTCON = 0x20;       // Set T0IE, clear T0IF*/
   if (PIR1.RCIF)
   {
  if(UART1_Data_Ready())
{
UART1_Read_Text(junk,"\r\n",255);
//Lcd_Chr_Cp('a');
UART1_Read_Text(header, "\r\n",255);
//Lcd_Chr_Cp('b');
UART1_Read_Text(message, "\r\n",255);
//Lcd_Chr_Cp('c');
Lcd_Out(2,12,header);
 Lcd_Out(3,12,message);
 if(header[0]=='+' && header[1]=='C' && header[2]=='M' && header[3]=='T')
 {
 Lcd_Out(1,10,"new message");
 new_message=1;
 }
 else
     {
     new_message=0;
     }
 }
 }
}
void main()
{ 
Lcd_Init();
Lcd_Cmd(_Lcd_CLEAR);
Lcd_Cmd(_Lcd_CURSOR_OFF);
i=Soft_UART_Init(&PORTC, 4,5,4800,0);
UART1_Init(9600);
UART1_Write_Text("AT+cmgf=1");
delay_ms(1000);
UART1_Write(13);
while(!UART1_Data_Ready())
{}
if(UART1_Data_Ready())
{

UART1_Read_Text(junk,"OK\r\n",255);

}

UART1_Write_Text("AT+ cnmi=0,2,2,1");
delay_ms(1000);
UART1_Write(13);
while(!UART1_Data_Ready())
{}
if(UART1_Data_Ready())
{
UART1_Read_Text(junk,"OK\r\n",255);
}
while(1)
{
 while(!UART1_Data_Ready())   //read from GPS
 {
 Rx = Soft_UART_Read(&error); 
//now process this data, no prob here
}
} 
}


Now the problem is, whereever i use UART1_Read_Text other than ISR, i get reentrancy error, since im new to hardware programming, i need some serious help

User avatar
filip
mikroElektronika team
Posts: 11874
Joined: 25 Jan 2008 09:56

Re: USART interrupt example

#12 Post by filip » 23 May 2011 09:18

Hi,

I believe we have the same conversation on our support desk, so we will continue there.

Regards,
Filip.

keaster
Posts: 13
Joined: 20 Jun 2011 21:42

Re: USART interrupt example

#13 Post by keaster » 18 Dec 2011 21:01

I Im trying to receive data from one PIC to another through the hardware UART and have used a the code in the first example and Im having a small problem
first off im using a PIC16F887 not the 877 but I checked both data sheets and the registers are the same
The problem Im having is that it seem like the flag bit is set and all the data is received the program stops. I display the received data on a lcd to show me what has been received but its really suppose to output it to a port expander and it does. The only way to change the received data is to reset the pic

Any ideas as to where the program is stopping?

dummy_c
Posts: 32
Joined: 07 Feb 2011 10:27

Re: USART interrupt example

#14 Post by dummy_c » 20 Dec 2011 16:26

^ I made it work using PIC16F887 and mikroC V4.6. By the way thank you so much for these thread. I will base my SMS parsing with these.

Code: Select all

unsigned cnt, cnt1;
char rxchar, i = 0, flag = 0; // Variable for storing the data from UART and array counter
unsigned char rxarray[80];   // array to store the received charaters
unsigned short j;

  void interrupt() {
  if (PIR1.RCIF) {          // test the interrupt for uart rx
    rxchar = Uart1_Read();  //
    rxarray[i] = rxchar;
    i++;
    // ******************************************************
    // Only select one of the following statements
    if (rxchar == 36) {  // select this if looking for a terminating character
      flag = 1;
      } // end if (rxchar == "$")
    PIR1.RCIF = 0;       // clear RCIF
    } // end  if (PIR1.RCIF)

  }


void main() {
  ANSEL  = 0;                     // Configure AN pins as digital
  ANSELH = 0;
  UART1_Init(9600);
  Delay_ms(500);          // Wait for UART module to stabilize
  PIE1.RCIE = 1;            //enable USART receiver interrupt bit
  INTCON.PEIE = 1;          //enable peripheral interrupt bit
  INTCON.GIE = 1;           //enable global interrupt bit

  while (1) {  
   if (flag ==1) {
    j = 0;
    while(j < i) {
     Uart1_Write(rxarray[j]);
     j++;
     } // end while(rxarray[i])
    i = 0;
    flag = 0;
  } // end if (flag)


  }
}

code
Posts: 2
Joined: 14 Nov 2012 17:01

Re: USART interrupt example

#15 Post by code » 14 Nov 2012 17:12

guys..please help me..i am using wavecom fastrack gsm modem and
https://www.olimex.com/Products/PIC/Development/PIC-IO/ relay board and pic16f28a..the problem the pic cannot receive the sms that i will send..when i will test it to hyperterminal it's working..but when i connect it to pic i didnt work.. :( what is the problem?is there any corrections of my code?

this is my code..

the relay 1 is connected to ra3, relay 2 is connected to ra2, relay3 is connected to ra1 and 4 is ra0..

Code: Select all

unsigned char datarx[];

void main(){

     UART1_Init(9620);
     Delay_100ms;
            TRISA = 0x00;
            TRISB = 0x00;
            PORTB = 0xFF;
           while(1){
       if(!UART1_DATA_READY()){}
       else{
                  TRISA = 0x00;        //port a as output
                  TRISB = 0x00;        //port b as output
                  UART1_WRITE("AT") ;
                  UART1_WRITE("AT+CMGF?") ;
                  UART1_WRITE("AT+CMGR=1") ;
                   datarx = UART1_Read();      // reads the sms
            if(datarx == 0x41){    // "A"

             UART1_WRITE("AT+CMGF?") ;
             UART1_WRITE("AT+CMGR=1") ;
             UART1_WRITE("R1 - ON") ;
             UART1_WRITE("AT+CMGS=\"09163233890\"");
             PORTA = 1;  }         // for relay 2
            else if(datarx == 0x42) {  //"B"
             UART1_WRITE("AT") ;
             UART1_WRITE("AT+CMGF?");
             UART1_WRITE("AT+CMGR=1");
             UART1_WRITE("R2 - ON") ;
             UART1_WRITE("AT+CMGS=\"09163233890\"");
             PORTA = 2; }          //for relay 1
            else if(datarx == 0x43) {  //"C"
             UART1_WRITE("AT") ;
             UART1_WRITE("AT+CMGF?") ;
             UART1_WRITE("AT+CMGR=1") ;
             UART1_WRITE("R3 - ON") ;
             UART1_WRITE("AT+CMGS=\"09163233890\"");
             PORTA = 4; }          //for relay 1
            else if(datarx == 0x44) {  //"D"
             UART1_WRITE("AT+CMGF?") ;
             UART1_WRITE("AT+CMGR=1") ;
             UART1_WRITE("R4 - ON") ;
             UART1_WRITE("AT+CMGS=\"09163233890\"") ;
             UART1_WRITE("AT") ;
             PORTA = 8;      }     //for relay 1
            else{UART1_WRITE_TEXT("TANGA") ;}
       }
    }


}

corrections is highly appreciated..

Post Reply

Return to “mikroC General”