5 years, 2 months ago.

How to receive serial message over 16 chars in length?

I have the following code for serial interface:

serial example

#include "mbed.h"
#include "common.h"

int main() {
    
   Test.attach(&newCommand);          //interrupt to catch input

   while(1) { }
}

void newCommand() {
    unsigned char i = 0;
    static char inputBuff[32];
    static char inputBuffStr[32];           //use static to initilize elements to 0 

    
    FILE* WriteTo = fopen("/local/log1.txt", "a");
    
    while (Test.readable()) {
        //signal readable
        inputBuff[i] = Test.getc(); 
        
        for (int j = 7; j >= 0; j--) {
            fprintf(WriteTo, "%d", (inputBuff[i] >> j) & 1 ? 1: 0);
        }
        i++;
    }
    
    fprintf(WriteTo, "\n\r");
    fwrite(inputBuff, sizeof(char), sizeof(inputBuff), WriteTo);
    fprintf(WriteTo," Read input once.\n\r");

    fclose(WriteTo);  
}

When I try to send a message over 16 bits long I don't receive the full message, like so:

00000000000100000010001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

# Read input once.

Then when I send it again after restarting the mbed:

0000000000010000001000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

# Read input once.

0000000000000000000000000000000000110011

3 Read input once.

I suspect this is because the message is more than 16 bytes long, but I don't know how to take in a message which is more than 16 chars into the mbed. I tried to put another while(Test.readable()) after the first one, to no wain, even if it would be a rather rough way to do it.

How can I take in a message that is more than 16bytes long?

I noticed that some questions noted that I could use Buffered Serial... however, is this compatible with OS5? Do I have to use OS 2 for this library, or is there an OS5 version?

2 Answers

5 years, 2 months ago.

You are trying to do far too much in the interrupt routine newCommand(). Opening a file, decoding a char into 0s and 1s, writing these chars, closing the file (over and over again...) takes a lot of time. All that work should be done in main(), where some of it needs to be done only once in fact. The interrupt code should only get the char and store it in the inputBuff. Because of the relatively long time it takes for newCommand to finish you will probably see that new data arrives before finishing the newCommand interrupt routine and so the 16 byte hardware fifo buffer on the serial port gets flooded. Note that the actual size of the fifo buffer may depend on your mbed platform type.

Buffered serial lib will do something like filling a buffer on an interrupt and returning a byte from that buffer (rather than directly from the serial port) when you read a char.

5 years, 2 months ago.

Hello,

I suggest only catch chars into buffer in interrupt function make a volitelie variable like interruptComplete = true.

Then check that variable in your while loop (not in interrupt, in a while loop in main)

No need line 19 in interrupt.

A basic example for interrupt catch which reads until '\r'

void rf_rx_isr()
{
    rf_buffer_char = nodeRF.getc();

    if (rf_buffer_char != '\r') {

        rfRxBuffer[node.rfRxBufferCounter] = rf_buffer_char;
        rfRxBufferCounter++;

    } else if (rf_buffer_char == '\r') {

        nodeRF.attach(NULL, Serial::RxIrq);
        rfRxBufferCounter = 0;
        rfInterruptComplete = true;

    }
}

Now rfRxBuffer holds your data... Manage it in main program by checking rfInterruptComplete not in interrupt.

main() {
while(1){

if (rfInterruptComplete) {
rfInterruptComplete  = false;

// Do whatever you should do :)
}

}



}