Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 2 months ago.
How can i 'relocate' serial functions to a new .cpp and still use them from within the main?
Hello kind Sirs,
It has been a long time since I tried my hand at coding and I am moving from C to C++. Consequently I am having a little trouble separating and passing information between my functions if they are declared in separate cpp files. I understand that it is likely due to my poor understanding of how classes and other OO features work, any help would be much appreciated.
Anyway, here is the gig... I have a main.cpp which has 4 functions (plus main) and the purpose is to create a serial object which allows the user to type and receive any number of characters (not exceeding the buffer). I managed to do this when all of the functions reside within the main.
here is the code for this:
main.cpp
#include "mbed.h" // Example that prints to the screen and recieves input string from the PC via UART // use SPRINTF(tx_line,'message') to input a string to the buffer, send line function then sends the buffer over UART // readline will wait (for interrupts) until enter has been input, then it copys it to 'rx_line'. Serial device(USBTX, USBRX); DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); void Tx_interrupt(); // prototypes void Rx_interrupt(); void send_line(); void read_line(); const int buffer_size = 255; // Circular buffers for serial TX and RX data - used by interrupt routines char tx_buffer[buffer_size+1]; // Circular buffer pointers char rx_buffer[buffer_size+1]; volatile int tx_in=0; // volatile makes read-modify-write atomic volatile int tx_out=0; volatile int rx_in=0; volatile int rx_out=0; char tx_line[80]; // Line buffers for sprintf and sscanf char rx_line[80]; int main() { device.baud(9600); device.attach(&Rx_interrupt, Serial::RxIrq); // Setup a serial interrupt function to receive data device.attach(&Tx_interrupt, Serial::TxIrq); // Setup a serial interrupt function to transmit data while (1) { sprintf(tx_line,"This text is copied into txline \n\r"); //Txline is used by 'send line' send_line(); // Copy tx line buffer to large tx buffer for tx interrupt routine read_line(); // Read line filles the RXBuffer (upto an enter) and copies to rx line device.printf("\n\r '%s' \n\r ",rx_line); } } void read_line() // Read a line from the large rx buffer from rx interrupt routine { int i = 0; NVIC_DisableIRQ(UART1_IRQn); // Start Critical Section - don't interrupt while changing global buffer variables while ((i==0) || (rx_line[i-1] != 0x0d)) // Loop reading rx buffer characters until end of line character { if (rx_in == rx_out) // Wait if buffer empty { NVIC_EnableIRQ(UART1_IRQn); // End Critical Section - need to allow rx interrupt to get new characters for buffer while (rx_in == rx_out) { } NVIC_DisableIRQ(UART1_IRQn); // Start Critical Section - don't interrupt while changing global buffer variables } rx_line[i] = rx_buffer[rx_out]; i++; rx_out = (rx_out + 1); //% buffer_size; } NVIC_EnableIRQ(UART1_IRQn); // End Critical Section rx_line[i-1] = 0; return; } void Rx_interrupt() { led1=1; while ((device.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) // Loop just in case more than one character is in UART's receive FIFO buffer,Stop if buffer full { rx_buffer[rx_in] = device.getc(); device.putc(rx_buffer[rx_in]); rx_in = (rx_in + 1); //% buffer_size; } led1=0; return; } void send_line() // Copy tx line buffer to large tx buffer for tx interrupt routine { int i = 0; char temp_char; bool empty; NVIC_DisableIRQ(UART1_IRQn); // Start Critical Section - don't interrupt while changing global buffer variables empty = (tx_in == tx_out); while ((i==0) || (tx_line[i-1] != 0x0d)) // do atleast once and while carage return is not detected) Wait if buffer full { if (((tx_in + 1) % buffer_size) == tx_out) // End Critical Section - need to let interrupt routine empty buffer by sending { NVIC_EnableIRQ(UART1_IRQn); while (((tx_in + 1) % buffer_size) == tx_out) { } NVIC_DisableIRQ(UART1_IRQn); // Start Critical Section - don't interrupt while changing global buffer variables } tx_buffer[tx_in] = tx_line[i]; //copy the characters from txline to tx buffer i++; // increment line counter tx_in = (tx_in + 1) % buffer_size; // increment buffer counter } if (device.writeable() && (empty)) { temp_char = tx_buffer[tx_out]; //take current character into a temp tx_out = (tx_out + 1) % buffer_size; //increment 'out' pointer device.putc(temp_char); //send character } NVIC_EnableIRQ(UART1_IRQn); // End Critical Section return; } void Tx_interrupt() { led2=1; while ((device.writeable()) && (tx_in != tx_out)) // Loop to fill more than one character in UART's transmit FIFO buffer,Stop if buffer empty { device.putc(tx_buffer[tx_out]); tx_out = (tx_out + 1) % buffer_size; } led2=0; return; }
However, I have tried to move all of the serial functions to a separate cpp and things are getting confusing. How do I create an instance of serial in the main and then read/write/use/manipulate from within another function inside a different CPP file?
Essentially, how do I declare external functions to take a serial object (or a pointer to) created in the main.
Thanks
2 Answers
9 years, 2 months ago.
There are no classes or objects involved in that code which means this is really just c code rather than c++, you can do it exactly the same way in c++ as you would in c.
Create two new files, serial.h and serial.cpp
serial.h contains the function prototypes e.g.
void Tx_interrupt(); // prototypes void Rx_interrupt(); void send_line(); void read_line();
And then in serial.cpp you start with #include "Serial.h" and the rest of your code for the serial port.
In main.cpp just include the seril.h file at the start and those functions will be available to you but all of their internal workings will be hidden.
The c++ way would be to define a class that inherited Serial and added the extra functionality required to the base class. You'd split the files in much the same way but the way you'd access things would be a little different. If you only need one serial port then the way you have it works fine, the c++ method would be cleaner if you wanted to have multiple serial ports with the same added functionality.