How to receive string using uart on pic18

Status
Not open for further replies.

nick703

Advanced Member level 1
Joined
Oct 17, 2011
Messages
422
Helped
21
Reputation
44
Reaction score
22
Trophy points
1,298
Location
surat
Visit site
Activity points
3,987
hello friends i have using pic18f4431 and c18 microchip library . now i want to receive string and particular char from pc via serial port ok . so here is my receive and transmit function
Code:
#pragma code IntrruptPriorityHigh = 0x08

void IntrruptPriorityHigh(void){
_asm goto IntrruptHandleHigh _endasm
}
#pragma code

#pragma	interrupt IntrruptHandleHigh
void IntrruptHandleHigh(void){	

	if(PIR1bits.RCIF == 1)
		{
			PORTAbits.RA1 = 0;		          	//Communication LED  ON 
			C[i] = RCREG;						//ReadUSART();
			i++;
			if(i > 15)
			{i = 0;j = 0;}
			PIR1bits.RCIF = 0;		
		}
}
#pragma code IntrruptPriorityLow = 0x18

void IntrruptPriorityLow(void){}

void Transmit(char* pstring)
{
	a = 0;
	i = 0;
	j = 0;
	
	while(*pstring  != '\0')
	{	
		while(!(TXSTA & 0x02));
			TXREG = *pstring;
	        pstring ++;
			C[a] = 0;
			a++;
			C[a] = 0;
			a++;
	}
	
	
}


void initial_all(void)
{
	

    BAUDCTL = 0x08; 	//Baud rate control bits
	SPBRG = 0x03;       //load Baud Rate Generator Registers
	SPBRGH = 0x01;
 	TXSTA = 0xA4;      	//Initialize USART Async. transmitter	
	RCSTA = 0x90;       //initialize USART Async. receiver

	

	T1CON = 0x00;     //TIMER 1 CONTROL REGISTER SET

	TMR1H =  0xC5 ;              //TIMER0_HIGH;
	TMR1L =  0x62  ;              // TIMER0_LOW;

	T0CON = 0x08;

	TMR0H = 0x3D;         // TIMER 0 LOAD FOR 10 mS
	TMR0L = 0xCD;	

    TRISC = 0x89;

	TRISD = 0x01;

	

	

	PTCON1bits.PTEN  = TRUE;
}

void initial_intrrupt(void){

	RCONbits.IPEN   = 1;
	INTCONbits.GIE  = 1;
	INTCONbits.PEIE = 1;

//	PIE1bits.ADIE = TRUE;       //ADC INTRUPT ENABLE
//	IPR1bits.ADIP = 0;

	PIE1bits.RCIE = TRUE;        //Enable receiver intrrupt
	IPR1bits.RCIP = 1;

	PIE1bits.TMR1IE = TRUE;            //TIMER INTRRUPT ENABLE
	IPR1bits.TMR1IP = 0;            //PRIORITY LOW

	INTCONbits.TMR0IE = 1;         //TIMER 0 INTRRUPT ENABLE
	INTCON2bits.TMR0IP = 0;        //PRIORITY LOW

}

char PowerOn[9] = {"[TEST]"};
unsigned char C[15];

void main()
{	
	initial_all();
	initial_intrrupt();
	initial_start();
	

	T0CONbits.TMR0ON = TRUE;        // TIMER 0 ON

	
		Transmit(PowerOn);

	
      while(1)
      {
                
      }
}

SO how to receive string using serial port ? any code may be help ?
 

Re: HOW to receive string using uart on pic18

I am also facing the same problem Nick ,
I have to get the response from SIm900 to LCD like and response "OK" etc , etc ,
I have also set the register bit tried with HIGH PRIORITY INTERRUPT vector address also ,,
I have done it using AVR uart receive interrupt but in PIC I don't know !!
 

Re: HOW to receive string using uart on pic18

u receive fully string in avr ? then please post some code i will try
 

Re: HOW to receive string using uart on pic18

Ok The ISR Function is

I declared volatile variable

Code:
unsigned char index;
volatile unsigned char mydata[50]= "";
ISR(USART1_RX_vect)
{
	mydata[index] = UDR1;
	if(inData[0] == '0')  //Like in that I would give AT Commands whose response comes with '0' as first Character
	index++;
}

then I parsed the array
void getdata()
{
unsigned char *getdata ; 
getdata = &mydata[0] ;   //Getting 1st element and stores in the base address of Pointer

while(*getdata ! = '\0')
{
send_char_uart(*getdata);
getdata++ ; 
}
}
Nick in this I know whatever I write in the ISR Code that will run but in PIC I am confuse how to do interrupts as there is" "RCIF" flag register and it is read only then what's the purpose of putting the logic like if(PIR1bits.RCIF == 1 ),,
I also get to know that If that becomes high Interrupt Occurs but still I am confused in the Receive_UART Interrupts in PIC
 

Re: HOW to receive string using uart on pic18

Nick have you done something based on that ??
 

Re: HOW to receive string using uart on pic18

i didn't get anything to receive full string . but if suppose when my PC side send me a like {START THE MACHINE} fully string that time i received particular char . i am still trying bro!!
 

Re: HOW to receive string using uart on pic18

Hello nick,
I'm not sure what is your problem, are you able to receive a character? or not able to receive anything? Your code seems fine to me, except that I don't see a definition for the i and j and also any variable that is being used in the interrupt should be declared as volatile. One more thing, the RCIF is a read only bit and is cleared automatically when the RCREG is read so you do not need the line "PIR1bits.RCIF = 0;".
As for the receiving side, sometimes when you have a loopback on the UART port, when you transmit the receiver buffer is overflowed and the reception is stopped so you need to check the overflow bit and cleared it if it is set.
embRTS, the RCIF flag can generate an interrupt if the receive interrupt is enabled, but there can be more interrupts in the software. So when you enter the interrupt routine, you need to check for the cause of the interrupt and you do it by checking the interrupts flag "if(PIR1bits.RCIF == 1 )".
I hope I helped a bit, and if not, let me know
Yaniv
 

Re: HOW to receive string using uart on pic18

yes i am receive char . but not able to receive full string as i mentioned above . so i want to create simple receive char function and simple receive string function .
 

Re: HOW to receive string using uart on pic18

Hai nick703,

What I understood from the post is that you want to receive a string through Uart, but you don't know the length of the incoming string or they are coming randomly. If the string doesn't ends with a particular character such as CR or LF, you may try this method.

Start a timer with a short time period (with timer interrupt enabled) when the first byte is received.
If the timer interrupt occurs before uart Rx interrupt, we can assume that there are no incoming bytes, and a string is received.
When bytes are receiving continuously, receive interrupt occurs before the timer interrupt, so clear the timer interrupt when a byte is received.

Hope this helps,
 

Re: HOW to receive string using uart on pic18

@yaniv : That I understood with your post thet RCIF Flag bit is checked to find the occurrence of Interrupt ,
Now I am saying that
Suppose I have a String "embRTS" , now i wish to display it

now what to do
i will think like that i have to write in the ISR function
Code:
volatile unsigned char mydata[10] = "" ; unsigned char i;
// Interrupt Functions
if(PIR1bits.RCIF == 1)   //If an Interrupt Occurs then execute block
{
mydata[i] = RCREG ;    //  Get the data in RCREG Register 
if(mydata[0] != NULL )  /*Suppose there is some data in the First element of the array */
i++ ;                       // Increments i variable 
}
//Interrupt Code ends

void get_data()
{
unsigned char *getdata ; 
getdata = &mydata[0] ;    //Storing the 1st element in Base address

// NO i will print whatever be the content of Pointer 

send_char(*getdata) ; // This will give me Character 'M' 

//In the same way I append the remaining but not working in PIC Mcu 
}
Now my doubt is suppose the first character 'e' i get in the RCREG register I am also able to print that in LCD or Hyper terminal ,

Now what about the remaining Characters of that string "embRTS",
Like I wanted to know "PIR1bits.RCIF" flag will be set each time for every characters ,

or any other mechanism ??
but what about the other characters
 

Re: HOW to receive string using uart on pic18

Hi,
As ponnus suggested you can start a timer, but in a simpler way you can just wait for a timeout, for example, you can set a flag in the interrupt routine that will execute the following code:
Code:
.
.
.
                 stop_rx = 0;
                 i = 0;
                 while (stop_rx == 0)
                 {
                    temp =  wait_for_byte_with_to();
                    if (temp == 0x01)   // if timeout
                    {
                        stop_rx ++;
                        continue;
                    }

                    C[i] = RCREG;
                    // check the stop condition, if there is any
                    if (C[i]== 0xff)
                        stop_rx++;
                    else
                        stop_rx = 0;

                    i ++;
                 }
.
.
.
/* wait for a uart byte with  timeout*/
char  wait_for_byte_with_to () {
    int i;
   
    for (i = 0; i < 8000; i++ ){ // set the timeout as you see fit
        if (PIR1bits.RCIF == 1) // check if a new byte was received
        {
            return 0x00;
        }
    }
    return 0x01;
}

Update: I forgot to mention, that the interrupts for the RCIF should be disabled before this code and after the message was finished (timeout) then the interrupts can be enabled again.
 
Last edited:

Re: HOW to receive string using uart on pic18

hi embRTC u know which string send your pc to microcontroller or not?
if no then simple my code u directly write C[j] variable like below code.

Code:
#pragma code IntrruptPriorityHigh = 0x08

void IntrruptPriorityHigh(void){
_asm goto IntrruptHandleHigh _endasm
}
#pragma code

#pragma	interrupt IntrruptHandleHigh
void IntrruptHandleHigh(void){	

	if(PIR1bits.RCIF == 1)
		{
			PORTAbits.RA1 = 0;		          	//Communication LED  ON 
			C[i] = RCREG;						//ReadUSART();
			i++;
			if(i > 15)
			{i = 0;j = 0;}
			PIR1bits.RCIF = 0;		
		}
}
#pragma code IntrruptPriorityLow = 0x18

void IntrruptPriorityLow(void){}

void Transmit(char* pstring)
{
	a = 0;
	i = 0;
	j = 0;
	
	while(*pstring  != '\0')
	{	
		while(!(TXSTA & 0x02));
			TXREG = *pstring;
	        pstring ++;
			C[a] = 0;
			a++;
			C[a] = 0;
			a++;
	}
	
	
}


void initial_all(void)
{
	

    BAUDCTL = 0x08; 	//Baud rate control bits
	SPBRG = 0x03;       //load Baud Rate Generator Registers
	SPBRGH = 0x01;
 	TXSTA = 0xA4;      	//Initialize USART Async. transmitter	
	RCSTA = 0x90;       //initialize USART Async. receiver

	

	T1CON = 0x00;     //TIMER 1 CONTROL REGISTER SET

	TMR1H =  0xC5 ;              //TIMER0_HIGH;
	TMR1L =  0x62  ;              // TIMER0_LOW;

	T0CON = 0x08;

	TMR0H = 0x3D;         // TIMER 0 LOAD FOR 10 mS
	TMR0L = 0xCD;	

    TRISC = 0x89;

	TRISD = 0x01;

	

	

	PTCON1bits.PTEN  = TRUE;
}

void initial_intrrupt(void){

	RCONbits.IPEN   = 1;
	INTCONbits.GIE  = 1;
	INTCONbits.PEIE = 1;

//	PIE1bits.ADIE = TRUE;       //ADC INTRUPT ENABLE
//	IPR1bits.ADIP = 0;

	PIE1bits.RCIE = TRUE;        //Enable receiver intrrupt
	IPR1bits.RCIP = 1;

	PIE1bits.TMR1IE = TRUE;            //TIMER INTRRUPT ENABLE
	IPR1bits.TMR1IP = 0;            //PRIORITY LOW

	INTCONbits.TMR0IE = 1;         //TIMER 0 INTRRUPT ENABLE
	INTCON2bits.TMR0IP = 0;        //PRIORITY LOW

}

char PowerOn[9] = {"[TEST]"};
unsigned char C[15],j;

void main()
{	
	initial_all();
	initial_intrrupt();
	initial_start();
	

	T0CONbits.TMR0ON = TRUE;        // TIMER 0 ON

	
		Transmit(PowerOn);

	
      while(1)
      {
                Transmit(C[j]);
      }
}

and suppose your command pattern like 4 to 5 word and u know specific command then compare variable C[j] to those command and get result.

but actually still i want some receiving full string function.

above method is just receive any thing as we can send from PC.
 

Re: HOW to receive string using uart on pic18

hello,

i think J is always zero value ..every time you enter in the loop J=0
so you will only get first car of the string..
it's like char by char ..

because
Code:
C[a]=0; // raz the 1srt car pointed
a++ ; 
C[a]=0; terminator of string ?  so  pstring point to zero and go out of while .. loop 
a++

Code:
  while(1)
      {
                Transmit(C[j]);  // how can evoluate j ?
      }

see similar post
PIC16F887 DS1307 I2C Serial Communication Automation post#11
 

Re: HOW to receive string using uart on pic18

SORRY paulfjujo i didn't understand your code please clear me just receive string code.

please explain me bro .
 

Re: HOW to receive string using uart on pic18

this code explain how to update a DS1307 RTC...
with a terminal PC via UART..
or more generaly, how to receive a string

So interrupt is used to receive char and store each char into the buffer.
To detect end of a string emited by the terminal, a test is made on char<CR> and char <LF>
means end of the string..

nota: you can use alse define other terminateur like "\0" or "EOT" or len of string...
in this example max len of string is 64 cars

so a flag is set
DataReady1 = 1;

and in the main programme , into a loop
just test this flag to detect string arrival...
you can also combine other test with car allready stored into the buffer to recognize a special sequence
to do an action...
example with a string wich must begin with letter U and terminate with letter # and sequence <CR><LF>
and a given lenght, to uptage date and time for the RTC
example with RAZ<CR><LF> to do another action

if you only want todisplay it,
just display without test other than the flag
Code:
if(DataReady1 == 1)
{
  printf(" %s",buffer);
//or Lcdwrite_texte(buffer);
  DataReady1 =0; // raz the flag
 buffer[0]=0;   // raz buffer origine
 PIE1bits.RCIE = 1;// re enabled  receiving interupt  
}
 

Hi PaulFijujo,

So suppose I know my String first char and last char so
I can set the logic like

Code:
volatile unsigned char in_data[100] = "" , my_flag_rx;
unsigned char index ;
if(PIR1bits.RCIF==1)
{
in_data[index] = RCREG ;
if(in_data[0] == '+' )  // As '+ ' is always the first character
index++ ; 
if(RCREG == 'K') {  // As 'K' is always the last Character
my_flag_rx = 1 ;  }
}

So the logic is like that first a byte is received in in_data[0th element] variable then it is checked whether it is '+' or not then if it is '+',
then receive next byte also in index,

and if the (index) reached till 'K' then the Flag is set which will act as signal in MAIN function for Interrupt ocurrance and we will do further Procedure in Main Function ?

- - - Updated - - -

`Sorry for this VERY VERY late Reply
 

Hello,

... and if the (index) reached till 'K' then the Flag is set which will act as signal in MAIN function
for Interrupt ocurrance and we will do further Procedure in Main Function ?

Yes, it is the idea.... but you will loose some char before to be synchronised with the first car '+'

When you receive the terminator K, you must clear the index , into the interrupt or into the main
and index must be declared as volatile to be visible inside the main..
Code:
volatile unsigned char in_data[100] = "" , my_flag_rx;
volatile unsigned char index ;


if(PIR1bits.RCIF==1)
{
in_data[index] = RCREG ;
if(in_data[0] == '+' )  // As '+ ' is always the first character
index++;
if(RCREG == 'K') {  // As 'K' is always the last Character
my_flag_rx = 1 ;
index=0;
}
}
or if you need to know the index value (=Nb of car into the buffer)
in the main program, use anther car index in interrupt
also ,if you want to treat your table in_data as a string, put Zero value at this end
.
Code:
//inside interrupt function
static int i1; // locale variable for storage index 
if(PIR1bits.RCIF==1)
{
in_data[i1] = RCREG ;
if (in_data[i1]=='+')
{
 i1=0;
 Index=0;
 in_data[0]='+'; // to store first car '+' or ignore it with i1=-1;
} 
if(in_data[i1] == 'K')   // As 'K' is always the last Character
{
   my_flag_rx = 1 ;
   in_data[i1+1]=0; // terminator string after last car 'K'  or ignore it by doing in_data[i1]=0;
   index=i1;// last index keept 
   i1=-1; 
   // optional
   // if you want to treat the result without overwritting the buffer and put again RCEN=1 in the main
   RCEN=0;  
}
i1++;
}

i agree that other soluce could be a circular buffer, just a little bit more complicated..
 

Yes I forgot to write the

""index = 0 ""

as I wrote the code last night and done this index clearance modification four hours before
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…