0

I have been trying to find a solution for UART receive interrupt for my UNO board and I came across a possible solution in : PCInt

I did a small editing in the following portion of the code to make it work for UART.(code works like a loop-back test)

void RXint(void) {
char k;
if(Serial.available()>0)
{
k=Serial.read();
Serial.print(k);
}}
void setup()
{
Serial.begin(9600);
PCattachInterrupt(0, RXint, FALLING);
}
void loop() 
{}

The code works pretty well with one big drawback. The character displayed is having one char delay, what i mean is that for the following input

qwerty

output is

qwert

That means if I enter the 5th char,the output will be 4th one. When the first input is given, it doesn't show output till the second input is entered.

Can someone help me out with this

(This is only a test code, the interrupt part is to be used in a larger code where the loop() carries out different tasks and interrupt is to be raised when data is received via UART) .

  • 1
    Forget about interrupts and rename RXintloop. It should work like a charm. Serial already handles the UART interrupt pretty well. Trying to manage the incoming data in an interrupt is misguided. – Edgar Bonet Jun 23 '17 at 9:17
  • @EdgarBonet Actually this is only a testing code. The real code is a long one consisting of other connected devices and in that code I need to add interrupt for UART as the data is to b stored to a RAM. I cant use Serial.event() as it checks only at the ending of loop. – Sreez.. Jun 23 '17 at 9:26
  • 1
    I need to add interrupt for UART as the data is to be stored to a RAM”. The Serial object already provides an interrupt that does exactly what you want: it stores the incoming data in a RAM buffer. It makes little sense to add a second buffering layer of your own. “I cant use Serial.event() as it checks only at the ending of loop”. Checking at the end of loop() is fine, unless your loop() is too slow. If this is the case, then your real problem is: too many blocking calls. It's not a problem about serial interrupts at all. – Edgar Bonet Jun 23 '17 at 9:36
  • Here the working is like, the data is received in a sequence and the received data is stored into an External RAM(from where further processing is done). Of course the loop() is slow as it needs to be reading RTC and pushing data to other devices and I cant miss a character in sequence that I am receiving. Cause of these reasons I am trying to implement interrupt. – Sreez.. Jun 23 '17 at 9:46
1

Your interrupt is happening at the same time the START bit of the next frame is arriving in the hardware. As a result you don't have that data yet, because it's still to arrive. All you have is what has gone before. You won't get the new character until the frame has finished arriving and the UART RX interrupt fires and the byte gets copied out of the RX FIFO and placed into the Arduino receive buffer.

The way you are doing it is completely wrong. The data is already being captured using an interrupt and placed in a buffer for you to deal with as you see fit at a time that suits you (as long as it is before the buffer overflows).

If you can't read it fast enough using your main loop (or variations thereon) then you need to rethink how you are doing your main loop.

  • are there no USART interrupts in arduino? – Sreez.. Jun 23 '17 at 10:31
  • You mean besides the one I already mentioned that the API already uses to receive the incoming bytes...? – Majenko Jun 23 '17 at 10:32
  • I am a little new to this. It would be much helpful if you could show me a way how to do this without an interrupt. I tried Serial.event(), but my main loop() is too long i guess, so its not working as expected. – Sreez.. Jun 23 '17 at 10:39
  • 2
    So make your main loop() shorter. Get rid of delays, while loops, etc. You don't want to write blocking code on an Arduino or you find you can't do much. – Majenko Jun 23 '17 at 10:44
0

As other have emphasized, make sure your loop runs freely, without delays or blocking while loops. It would be very unusual to have a loop that really takes > 64ms (the input buffer overflow time @ 9600).

However, there is one case where a frequently-used library is blocked for 150ms or more: SDfat. If you are logging data, the library may have to wait for the SD card to accept more data. It is an indeterminate length of time, and it is specific to the individual card. In this case, you have two choices:

  • process the RX characters as they arrive, during the RX character interrupt; or

  • add a yield call to the offending SDFat method.

For the former solution, I have posted modified versions of the most commonly-used Arduino serial port libraries. They all have a new attachInterrupt method that allows your function to be called for each RX character. See NeoHWSerial (a modified HardwareSerial), NeoICSerial (a modified AltSoftSerial) and NeoSWSerial (a more-efficient alternative to SoftwareSeriall).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.