PIC24EP UART RX INTERRUPT - Page 1
Forum section: electronics / general

author: Adom
author_rank: Newbie
timestamp: April 05, 2016, 06:45:47 am
content: void __attribute__((interrupt, shadow, no_auto_psv)) _U1RXInterrupt(void){IFS0bits.U1RXIF = 0;while(DataRdyUART1()){char tmp = ReadUART1();if(tmp == '\n'){packet_flag = true;rx_buffer = '\0';position = 0;}else{if(position == (MAX_BUFFER_SIZE - 1)){position = 0;}WriteUART1(tmp);rx_buffer[position++] = tmp;}}}Please the above interrupt routine is supposed to receive data via uart and echo back whatever it receives while storing the data in a buffer. I have tried the code with realterm and coolterm and I am not getting back what I send. I also send data in the main routine at regular time intervals. The microcontroller is able to send this correctly and I see the data on realterm and coolterm but the receiver interrupt is echoing back wrong characters. Please can anybody help me with this?

author: JPortici
author_rank: Super Contributor
timestamp: April 05, 2016, 07:08:35 am
content: you shouldn't call functions inside an interrupt routine. IR initialization and return code become veeeeery messy"while(DataRdyUART1())"Are you checking the URXDA bit? You are already in the interrupt because you have data available. And if you clear the bit but you still have enaugh data (depending on the value of URXISEL) on the buffer it will be set again."char tmp = ReadUART1();"is this variable created every time you run the while cycle? not good. declare it anyway as you WILL have data when you enter the routineor better yet make it a global variable"ReadUART1" can be as simple as "tmp = U1RXREG" as you seem to handle the data after anywaysame as "WriteUART1" can just be U1TXREG = tmpThen check with the debugger to see if the character you receive is correct and start from there

author: bookaboo
author_rank: Frequent Contributor
timestamp: April 05, 2016, 08:48:32 am
content: Yep agree why not just read the U1RXREG directYou dont seem to have EOL charterers enabled in realterm.Also not sure if the compiler takes care of this anyway but I like to addIEC0bits.U1RXIE = 0;Then re-enable the interrupt once all the handling is finished. Thats a belt and braces approach I have from previous experience with other micros calling interrupts inside themselves.

author: Adom
author_rank: Newbie
timestamp: April 05, 2016, 09:28:09 am
content: void __attribute__((interrupt, shadow, no_auto_psv)) _U1RXInterrupt(void){IFS0bits.U1RXIF = 0;IEC0bits.U1RXIE = 0;//while(DataRdyUART1()){//char tmp = ReadUART1();tmp = U1RXREG;if(tmp == '\n'){packet_flag = true;rx_buffer = '\0';position = 0;}else{if(position == (MAX_BUFFER_SIZE - 1)){position = 0;}//WriteUART3(tmp);U1TXREG = tmp;rx_buffer[position++] = tmp;}//}IEC0bits.U1RXIE = 1;}Please I have modified the interrupt routine as shown above with the variable tmp being declared as a global variable. The problem still persists.This is how I open the UART;OpenUART1(UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE &\UART_MODE_SIMPLEX & UART_UEN_00 & UART_DIS_WAKE &\UART_DIS_LOOPBACK & UART_DIS_ABAUD &UART_NO_PAR_8BIT &\UART_BRGH_SIXTEEN & UART_1STOPBIT,UART_INT_TX_BUF_EMPTY & UART_IrDA_POL_INV_ZERO &\UART_SYNC_BREAK_DISABLED & UART_TX_ENABLE &\UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR,259);I don't know if any of the above configurations could cause such an error.

author: JPortici
author_rank: Super Contributor
timestamp: April 05, 2016, 10:09:09 am
content: Quote from: bookabooyeah that can happen if interrupt nesting is active.. i would rather investigate the reasons why the interrupt happens again, if it's expected or nothave you hooked up the debugger and seen if you receive the expected character? I suppose that there is indeed an error in the receiver configuration, a you say you can transmit other data successfully.. Seems fine though

author: bookaboo
author_rank: Frequent Contributor
timestamp: April 05, 2016, 10:14:07 am
content: I put :IFS0bits.U1RXIF = 0;At the end of the interrupt as I think that flag gets set regardless of whether you have the interupt enabled or not (i.e. it will get set before you exit the interrupt), again I'm not 100% sure if it matters but it works for me.Also I prefer to putIEC0bits.U1RXIE = 1In my main loop after I've processed the received string, set a flag or bool to indicate to the main loop that it a received string to process, once it's done clear the flag and re-enable the interupt.If that all still fails check tris registers, make sure ports are digital not analog, check pin mapping.

author: dannyf
author_rank: Super Contributor
timestamp: April 05, 2016, 11:03:17 am
content: The codes flow seems to make sense, with the exception of the while loop. Your description isn't too clear on what you are getting and how it differed from what you were expecting.It is OK to call routines from the isr and the declaration of that tmp variable is OK too.

author: Adom
author_rank: Newbie
timestamp: April 05, 2016, 11:31:14 am
content: Please what is happening is that the interrupt gets called fine when it receives data. I know this because it echoes whatever character it received back to the UART which I can see via realterm. So when I send one character all I see on the terminal is one character as expected. But I don't see the character I sent. I see something else, for example when I send "a" I receive an "O" in the terminal. That is the problem I am facing.

author: Buriedcode
author_rank: Super Contributor
timestamp: April 05, 2016, 01:44:50 pm
content: Strip it down to the basics.You could use built-in libraries, or set the registers for the UART yourself. Make sure you set the correct baud for your oscilllator, and strip down your interrupt to do the following:clear the recieve flag. (U1RXIF)read in byte to tmp register.Send tmp into the tx register.That is a simple loopback which will test your baud, pin settings etc.. and will pretty much cover the specifics to your chip. Any more functionality is almost independent of the device (assuming its set up correctly) so you can google for other serial interrupt routines to see how others deal with EOL characters, buffers, etc..

author: macboy
author_rank: Super Contributor
timestamp: April 05, 2016, 03:28:40 pm
content: Use a debugger to stop the PIC and look at the character received by the PIC to be sure that it is the one that you sent. Or if you have an extra port, set an 8-bit port to the character every time you receive one, and use LEDs to visually see the last character received. I suspect a baud rate issue. Even if the baud rate is wrong, your UART will receive something, just not the right thing. You should consider checking for framing errors.

author: Adom
author_rank: Newbie
timestamp: April 05, 2016, 09:01:11 pm
content: Hello guys, please I followed macboy's advice and displayed the data received on PORTB with leds connected. What I am receiving from the UART is exactly what I am sending to the terminal program. About the baud rate issue, I am successfully sending data to the terminal at a rate of 9600.void __attribute__((interrupt, shadow, no_auto_psv)) _U1RXInterrupt(void){IFS0bits.U1RXIF = 0;tmp = ReadUART1();LATB = tmp;WriteUART1(tmp);}int main(void) {uint8_t i;System_Init();EnableIntU1RX;//DisableIntU1RX;while(1){for(i = 0; i < 4; i++){DelayMs(500);}putsUART1("Hello There!\r\n");}}"Hello There" appears correctly on the terminal display but when I send a character from the terminal I receive a different value as shown by the LEDs and that same value is sent back to the terminal display. It appears there is a problem with "ReadUART1()".So when I send an "a" I receive "O", when I send "b" I receive " ' " when I send "C" I receive "N" and so on.Please can anyone help me with this?

author: Adom
author_rank: Newbie
timestamp: April 05, 2016, 09:41:34 pm
content: Hello guys,I managed to find and solve the problem. The problem was an rx polarity inversion bit. I found this forum post on the microchip forum very useful.In case anyone runs into this same problem. Here is the linkhttp://www.microchip.com/forums/m409473.aspx

author: JPortici
author_rank: Super Contributor
timestamp: April 06, 2016, 07:44:59 am
content: what i suspected.and that is why i told you to use the debugger and look at the received data in the variables view. no led out bullshit, because you saw the correct number of high/low bits but not the right polarity. variables view in the debugger would have shown you the actual "char", or even by looking at the bits it would have been immediate.If you don't have a programmer with a debugger put aside whatever you use and buy one, like the pickit3. clones are cheaper these days and it works just fine if you remain in windows. (can't make mine work in osx since Mavericks, don't know why. Original ones work, though)About calling routines inside ISR..http://www.microchip.com/forums/m775681.aspxNot using this to prove my point, as it becomes a discussion about pros and cons..but what come out of this is that it is fine, if you know the limitations.I strongly advice against calling routines inside the ISR, because the init code becomes much messier as you have to save -again- a whole set of register.. to do what? copy one buffer? not worth it. double the latency for one instruction.And if you have to work with 24E/33E family, which has a much greater interrupt latency, greater return from call latency and 2 clock cycles for rms instructions to non-sfr memory* (in this case, saving and loading sets to software stack, push and pop shadow registers might not be enough)you certainly don't want to do this, unless it's very important to be as much abstract as you can (like in the CAN example)*yes, i know it sounds bad, but in 33e you get more than double the MIPS and very advanced peripherals.. so when you're not moving around stuff to from/to ram you really have improved performances

author: diyaudio
author_rank: Frequent Contributor
timestamp: April 06, 2016, 12:43:14 pm
content: Quote from: JPortici on April 06, 2016, 07:44:59 amIts better to just do things the right way, irrespective if you spoiled with doubling of MIPS in the end, the pattern of thought remains consistent across smaller resource limited micro`s.