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] dsPIC30F UART Receive Interrupt Problem

Status
Not open for further replies.

helmi_mjd

Member level 2
Joined
Feb 20, 2011
Messages
45
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Activity points
1,668
Hi guys!
I would like to receive string through UART RX using interrupt. I have trouble in receiving the string. Below is my code. Please if anybody could pointed out the problem in my codes.

Thanks in advance.:-?

Code:
void uart1a_initialize(void)
{
   // Set the Baud Rate.
   U1BRG = 129;                  //((Fosc/4)/(16 * Baud rate)) - 1
                                         //129 = 9600bps baudrate for  
                                         //10MHz crystal with 8xPLL  
                                
   U1MODEbits.ALTIO = 1;      //1 = Communicate using                                    //U1ATX and U1ARX pins (alternative).
                                    
   U1STAbits.URXISEL = 0;           //Interrupt flag bit is set                                              //for every character received.
   IPC2bits.U1RXIP   = 4;           //UART1 Receive Interrupt //Priority = 4.
   U1STAbits.OERR    = 0;           //Clear the Receive //Overflow Flag.
   IFS0bits.U1RXIF   = 0;           //Clear the UART1 Receive //Interrupt flag.
   IEC0bits.U1RXIE   = 1;           //Disable UART1 Receive //Interrupt
   U1MODEbits.UARTEN = 1;           //Enable UART1.
   U1STAbits.UTXEN = 0;             //Enable UART1 Transmit*

}

void __attribute__((__interrupt__, no_auto_psv)) _U1RXInterrupt(void)
{
	#define RX_BUFF 64
	static char rxstr[RX_BUFF];
	static char* temp;
	temp = rxstr;

	// Clear the overflow bit to recieve data
	if(U1STAbits.OERR ==1){
		U1STAbits.OERR ==0;
	}
	else if ((U1STAbits.FERR ==0) && (U1STAbits.PERR ==0)){
		while((*temp = U1RXREG) != '\n'){
			++temp;
		}
	}

	//Host setup timestamp for recording
	if(rxstr[0]=='&'){
		yrs = atoi(&rxstr[1]);
		mon = atoi(&rxstr[2]);
		day = atoi(&rxstr[3]);
		hrs = atoi(&rxstr[4]);
		min = atoi(&rxstr[5]);
		sec = atoi(&rxstr[6]);
	}
	
	//Host would like to setup new threshold value
	if(rxstr[0] == '@'){
		dB_thres = atoi(&rxstr[1]);
	}
	
	//Host request for data transmission
	if(rxstr[0]=='#'){
		transmitFlag = 1;
	}

	//Reset the receive buffer
	int n;
	for(n = 0;n<RX_BUFF;n++){
		rxstr[n] = 0;
	}
	//Clear RX interrupt flag
	IFS0bits.U1RXIF = 0;
}
 

I think when you get a receive interrupt you are getting into the while loop
Code:
	else if ((U1STAbits.FERR ==0) && (U1STAbits.PERR ==0)){
		while((*temp = U1RXREG) != '\n'){
			++temp;
and never exit ? or perhaps you run out of memory? what happens?

rather than having a receive buffer in the interrupt routine I would use a global ring buffer (it is not a good idea to have complex processing in an interrupt routine)
as characters are received they are put into the buffer
the main() function can monitor the buffer waiting for \n then process the buffer data

e.g. this code is for dsPIC33FJ256GP710
Code:
#include "hardware.h"
#include "uart2.h"
#include "libpic30.h"			// to change default printf output, see __C30_UART below

#define BRGH2           0

// buffer and pointers for received data
static unsigned char U2rxBuffer[100]={0};
static int U2rxIn=0, U2rxOut=0;


// Function:UART2Init -  sets up theUART2 module to baud rate
void UART2Init(long int baudRate)
{
    long int baudRateCheck;
     __C30_UART=2;			// set for printf output to this UART
    // calculate baud rate counter  - add 0.5 to round to nearest integer
    U2BRG= (int) (((SYSCLK/2)/(16.0*baudRate) - 1)+0.5); 	// set up baud rate register
    baudRateCheck=((SYSCLK/2)/(16*(U2BRG+1)));
    if(((baudRateCheck-baudRate)*100/baudRate) > 4)
      printf("UART2 baudrate required %lu was %lu, error %d\n", baudRate, baudRateCheck, (int) ((baudRateCheck-baudRate)*100/baudRate));
    U2MODE = 0;					// clear mode register
    U2MODEbits.BRGH = 0;  		//divider is 16
    U2STA = 0;					// clear status
    U2MODEbits.UARTEN = 1;		// enable UART
    U2STAbits.UTXEN = 1;		// enable reansmit
    IFS1bits.U2RXIF = 0;		// clear interrupt flag
    IEC1bits.U2RXIE = 1;		// enable receive interrupts
}

/* This is UART2 receive ISR */
void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
	IFS1bits.U2RXIF = 0;			// clear interrupt flag
    U2rxBuffer[U2rxIn++]=U2RXREG;	// read character
    if(U2rxIn == 100) U2rxIn=0;		// check for end of buffer
}


//Function:UART2IsPressed - return true if there is a new byte in UART reception buffer.
char UART2IsPressed()
{
    return  U2rxIn != U2rxOut;		// pointers different - if so characters in buffer
}


//Function:UART2GetChar : waits for a byte to be received.  It then returns that byte.
char UART2GetChar()
{
    char Temp;
    while(U2rxIn == U2rxOut);		// wait for character
    Temp = U2rxBuffer[U2rxOut++];	// return it
    if(U2rxOut==100) U2rxOut=0;		// check for end of buffer
    return Temp;
}
 

Besides the points that have been mentioned by horace1, I notice that you are continuing erroneous string handling as shown in your previous thread. Apparently you don't correct previous faults, or don't remember it.
Code:
   yrs = atoi(&rxstr[1]);
   mon = atoi(&rxstr[2]);
   day = atoi(&rxstr[3]);
...
I think it's time to learn C programming bottom up.
 

I notice that you are continuing erroneous string handling as shown in your previous thread. Apparently you don't correct previous faults, or don't remember it.
Actually I already solve the string transmission problem as suggested by you in my previous thread. Thanks for your help. Now my problem is i have to receive command from host controller for three commands including setting time stamp:
string format --> #,2014,06,23,10,30,35,$
which represent <command character><year><month><day><hours><minutes><sec><termination character>. How can i read this value from uart? I'm not sure how is this thread similar to the previous one.

- - - Updated - - -

I think when you get a receive interrupt you are getting into the while loop
and never exit ? or perhaps you run out of memory? what happens?

Code:
while((*temp = U1RXREG) != '\n')
In my though, this while loop will exit once the null terminated string is reach. My problem is how could i read string using uart RX like:
#,2014,06,23,10,30,35,$
The <#> represent a symbol for an operation, <2014,06,23,10,30,35> is the data for this operation (time stamp) and finally <$> is the symbol to indicate end of data. How could i do it. By the way, thanks for your suggestion. I will work on it based on your posted code.
 

Code:
while((*temp = U1RXREG) != '\n')
In my though, this while loop will exit once the null terminated string is reach. My problem is how could i read string using uart RX like:
#,2014,06,23,10,30,35,$
The <#> represent a symbol for an operation, <2014,06,23,10,30,35> is the data for this operation (time stamp) and finally <$> is the symbol to indicate end of data. How could i do it. By the way, thanks for your suggestion. I will work on it based on your posted code.
in main() you could have a while() loop storing characters until \n is received then process the line of data, e.g.
Code:
int main()
 {
      char rxstr[100]={0};
      int i=0;
      UART2Init(56700);
      // read characters until \n
      while((rxstr[i++]=UART2GetChar()) != '\n'); 
      // now process the line of text in rxstr[]
	//Host setup timestamp for recording
	if(rxstr[0]=='&'){
		yrs = atoi(&rxstr[1]);
		mon = atoi(&rxstr[2]);
		day = atoi(&rxstr[3]);
		hrs = atoi(&rxstr[4]);
		min = atoi(&rxstr[5]);
		sec = atoi(&rxstr[6]);
	}
	
	//Host would like to setup new threshold value
	if(rxstr[0] == '@'){
		dB_thres = atoi(&rxstr[1]);
	}
etc
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top