Writing C library using serial communication in Arduino

I am not familiar with C++. It is understood that Arduino is using cpp instead of c (according to my understanding).

Since, I need to use a C library from a controller which need to implement the Serial Connection in the given C library. Therefore, I try to make a simple C library to access the Serial Port. However, failed. Here is what I have done:

For the core .ino program:

#include <SC_Clib.h>
void setup()
{
  //com.setupHD();
  Serial.begin(57600);
}

void loop()
{
  sendMsg(&Serial);
  delay(500);
}

Here I have created the C library (SC_Clib.h and SC_Clib.c)

// ensure this library description is only included once
#ifndef _SC_CLIB_H_
#define _SC_CLIB_H_

#if ARDUINO >= 100
 #include "Arduino.h"
 #include "stdio.h"
#else
 #include "WProgram.h"
#endif

#ifdef __cplusplus
extern "C"{
#endif

/* C library */

void setup_HD();

void sendMsg(Stream* inport);

/* TODO Wrap all c function */


#ifdef __cplusplus
}
#endif

#endif

For the SC_Clib.c:

#include <SC_Clib.h>


void setup_HD(){
}


void sendMsg(Stream* inport){
	inport->println("This is a test");
}

The serial port part is following the following website:
http://allgood38.io/tag/arduino.html

However, I am not familiar with C++. As far as I know, the Serial port library is written in cpp. The library file can be found in "arduino-1.6.5-r2\hardware\arduino\avr\cores\arduino".

Now, I have been trapped here and stopped here. I failed to go further. Please give me some hints what should I do in order to access the Serial Port from the Standard-C library.

Many thanks :slight_smile:

Just after brief look. Why Stream* parameter in sendMsg function? "HardwareSerial* inport" should be there.

Dear Budvar10,

Thanks for your reply.

I follow the suggestion from this blog:
http://allgood38.io/tag/arduino.html


However, I have tried to use HardwareSerial* also.

Following is the error obtained during compilation:

error: unknown type name 'HardwareSerial'
void sendMsg(HardwareSerial* inport);

I guess I need to overcome the following problem

Call / access the Cpp library from the self-created C library.

Why do you need a Serial library in the first place ? Why not use the Arduino Serial library and use that in a normal way ?
I assume there is an existing C library for a controller, which controller and which library is that ?

Arduino uses the gcc compiler, that is for normal 'c' and also 'c++'. It's both.

Which Arduino board are you using and for which serial port ?

error: unknown type name 'HardwareSerial'
void sendMsg(HardwareSerial* inport);

It is because the compiler cannot find HardwareSerial.h file. The #include could solve this.

Budvar10:
Just after brief look. Why Stream* parameter in sendMsg function? "HardwareSerial* inport" should be there.

While Serial on most Arduinos derives from HardwareSerial, Serial on the Leonardo derives from a different base class that derives from Stream, as does HardwareSerial and SoftwareSerial. So, Stream IS the proper class to use.

Mixing C and C++ is possible, IF you know how to do it. There is little point in INSISTING that the file extension be .c, though, especially since it does not appear that you know how to make C and C++ play together. Make life easier for yourself and make the extension .cpp.

Thanks all of your suggestions and comments.

To Koepel:

Since I need to drive a hardware which provided an API written in C. And I need to implement the serial connection in the provided API. You can find the library I am talking about here:
http://www.meerstetter.ch/category/35-latest-communication-protocols

MeComAPI

As I have to use the library, so, I have no choice to work around with CPP serial library provided by Arduino with the MeComAPI library.

To Budvar10:

I have already included the HardwareSerial.h. The error obtained is with this #include.

To PaulS:

Of course, if there is another better way, I don't want to do mixing C and C++ especially I am not an expert in programming. However, I am not dared to touch the MeComAPI. Or do you mean that I can just change the extension of the MeComAPI from .c to .cpp can solve the problem? The MeComAPI is written in pure C.

Again, many thanks for all of you ~~

To Koepel:

I am using UNO and MEGA at the moment. I use hardware serial0 for the communication.

Since I need to drive a hardware which provided an API written in C.

The hardware does not know that the API was written with C. It won't care if you use C++ instead to send it data.

Calling functions written in .C files is possible. The problem is that C++ allows overloading functions. The HardwareSerial class has several methods called print(). The way that the compiler handles this is with a process called name-mangling, where the simple print() name that we see and call is actually mangled into a complex name that is based on the type of the calling arguments and the method name.

The C compiler does not do name mangling, since, in general it is not necessary. The print() function would have one set of arguments. If you needed to print an int and a float, you'd have two functions, printInt(int whatToPrint) and printFloat(float whatToPrint).

By adding some statements to the header file, you can tell the C compiler that it needs to mangle the names so that they can be called by a C++ program.

Put this:

#ifdef __cplusplus
 extern "C" {
#endif

before any function(s) that need to be called from the C++ code, and put this:

#ifdef __cplusplus
}
#endif

after the function(s).

Then, just call the C functions from your C++ (.ino, for instance) code.

Dear PaulS,

Thanks for your advice.

I have already included the

#ifdef __cplusplus
 extern "C" {
#endif

If you refer to the "SC_Clib.h", you will see I have used the code for the .ino to call the c library (self-created c library, SC_Clib.h).

The problem I am facing is to use the "Serial" in the SC_Clib C library. Why I need to use the "Serial"in the SC_Clib because eventually, I will use the MeComAPI instead of the SC_Clib (this one is for my test only). The MeComAPI has some function need to send "message" to the controller (the hardware I need to control) via the serial port. Therefore, I need to "embed" the serail code inside the C written MeComAPI.

So, in order to put things simple, I created a SC_Clib in C and would like to see if I can use the Serial in this SC_Clib.

Many thanks for your help :slight_smile:

The problem I am facing is to use the "Serial" in the SC_Clib C library.

Since Serial is an instance of the HardwareSerial class, and C knows nothing about classes or instances, that is going to prove challenging.

I can't think of any reason to make SC_Clib a .C file. Make it a .cpp file, and you will be able to overcome those unstated problems.

The picture of the MeComAPI shows that it uses a CRC and some kind of software handshake protocol.
But I still don't understand why you want to make a library. Perhaps you want to make a library that every one can use for every possible serial port for every Arduino board. Then you must have some knowledge about c++.

If you just want to make it work for an Arduino Uno for example, then use the normal Serial.write and Serial.read for the Serial library in a sketch. The Serial library is just another input-buffer and output-buffer, but the MeComAPI protocol allows buffering and delays.

Dear Koepel,

Many thanks for your reply.

Do you mean that I can use the MeComAPI in the sketch?

Since the MePort.c has "MePort_SendByte" function, I need to use the Serial.write inside this function. That is why I want to make a library for testing first.

Following is what I eventually want:

[Sketch - write the core program to control a system and the controller is one of them]----linked----[MeComAPI - to control the specific controller]

My problem faced:
I do not know how to define the the comport function in the MeComAPI. In the API, they use

#include "../ComPort/ComPort.h"

But that is for Linux. So, it is necessary to use the one with Arduino. But Arduino is in Cpp where the MeComAPI is in Pure C.

Sorry to make you guys confuse. I hope this above can describe what I am facing. Many thanks~

I would do it like this:
In a Arduino project, you can add *.cpp and *.h files. Use the drop-down menu in the upper-right corner of the Arduino IDE.
It is also possible to copy them into the folder of the project (after closing the Arduino IDE). Once the Arduino IDE is started, they will appear in the tabs.
When the code is good and everyting is working, the *.cpp and *.h files can be converted in a library.

You have no other way than to check the low level API files line by line. It is not only the COM port, it is also "printf" (stdio) and the timing.
Keep both the linux and Windows version next to each other. I think the Windows version is easier to understand.

The "MePort_SendByte" should use a call to Serial.write(). The comment tells that it can contain just a single write for a MCU (like the Arduino).
The "MePort_ReceiveByte" should be a call to Serial.read() probably with Serial.available().
The comment says that for an MCU the function could be modified to receive a single byte.

Does that mean that the whole API is written for a 'demo' mode ?
That is confusing. I also don't understand the "in" to retrieve a byte.

All the higher level functions with 'memset' will work on Arduino as they are.
I think also the CRC function will work on the 8-bit Arduino Uno as it is. The large CRC16_table_C should be put into PROGMEM memory. The float conversions should also work on a Arduino Uno.

The hardest part will be to understand the 'demo' mode and replace that with something real :confused:

For the most part, C++ is a superset of C, which means you should be able to take a C library, rename the .c files to .cpp, and compile it with a c++ compiler. This will also enable it to call C++ class methods, so that the ComPort_Send() becomes a Serial.write() instead.

Dear Koepel,

Thousands thanks for your help. I will try the ".cpp" and ".h" suggestion.

As far as I know, the API is not only for demonstration but for people to embed the controller into their project (like what I am doing). As they have their own communication protocol, so, we need to use the API to control the device.

So, they allow us to edit the MePort.c to "fit" the com-port communication depends on different platform.

For the CRC, if UNO is not good enough, I still have Mega to play around with. I will try this out.

Dear Westfw,

Thanks for your suggestion. I will try to change the .c to .cpp. Just wanna ask if I still need

#ifdef __cplusplus
extern "C"{
#endif

The Mega is just like the Uno :wink: with more ram and flash. It's the same 8-bit family of microcontrollers. But the compiler is awesome and very good and does all the 32-bit things.

The Arduino Due and Arduino Zero are 32 bit ARM processors.

For local files in your project, you don't need the ifdef _cplusplus.
You probably need the define to be sure that a *.h file will be included just once. I mean the #ifndef xxxx_H, #define xxxx_H

Thousands thanks all of you ~~

The problem solved a lot. Changing the C library from .c to .cpp does help :slight_smile:

Many thanks ~ :slight_smile:

Hello Do you mind sharing if you were able to get the API working with your arduino?