c++wiringpi

C++ not writing whole data to UART port


I have been testing UART communication in C++ with wiringPi.

The problem:

It seems that C++ isn't outputting whole data into the UART port /dev/ttyAMA0. Perhaps I'm doing it the wrong way?

Investigations:

Note : I am using minicom, minicom --baudrate 57600 --noinit --displayhex --device /dev/ttyAMA0 to check the received data.

Also! The UART port, RX & TX pins are shorted together.

The python code worked perfectly however when I tried to implement it in C++, the data received is different.

The expected received data should be: ef 01 ff ff ff ff 01 00 07 13 00 00 00 00 00 1b.

Received Data Comparison:

Language Used Data Received from Minicom
Python ef 01 ff ff ff ff 01 00 07 13 00 00 00 00 00 1b
C++ ef 01 ff ff ff ff 01

Code used

Python:

import serial
from time import sleep

uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1)

packet = [239, 1, 255, 255, 255, 255, 1, 0, 7, 19, 0, 0, 0, 0, 0, 27]

uart.write(bytearray(packet))

C++:

Note: Code compiled with g++ -Wall -O3 -o test hello.cpp -lwiringPi

#include <iostream>
#include <string.h>
#include <wiringPi.h>
#include <wiringSerial.h>

using namespace std;

int main()
{

      int serial_port;

      if (wiringPiSetup() == -1)
            exit(1);

      if ((serial_port = serialOpen("/dev/ttyAMA0", 57600)) < 0)
      {
            fprintf(stderr, "Unable to open serial device: %s\n", strerror(errno));
            return 1;
      }

      cout << "Sending data to UART" << std::endl;

      serialPuts(serial_port, "\xef\x01\xff\xff\xff\xff\x01\x00\x07\x13\x00\x00\x00\x00\x00\x1b");

      return 0;
}

Solution

  • You can't use serialPuts to send the null terminator. As with all similar functions, it will stop when the null terminator is encountered in the string. In this case I think your best option is to add a function that uses the ordinary write function that is used internally by WiringPi's own functions.

    You could make a wrapper function to make it look similar to the other calls:

    #include <cstddef>
    
    void serialWrite(const int fd, const char* data, size_t length) {
        write(fd, data, length);
    }
    

    and perhaps a function template to not have to count the length of the data in the fixed data arrays manually:

    template<size_t N>
    void serialWrite(const int fd, const char(&data)[N], bool strip_last = true) {
        serialWrite(fd, data, N - strip_last);
    }
    

    You can now use it like so:

    serialWrite(serial_port, "\xef\x01\xff\xff\xff\xff\x01\x00\x07\x13\x00\x00\x00\x00\x00\x1b");
    

    Note: There is a pull request to add a similar function (called serialPut) to the WiringPi library that you could download instead of using the official version from the master branch version if you don't want to make your own function.