This looks like something we used for reading some data on the uart. It is basically how you would set up for uart. I just grab an older project and tweak it for the job. It takes a some time to get it dialed in when doing it from scratch. For the most part its c with a little c++.
#include <iostream>
#include <iomanip> // For std::hex and std::setw
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include <unistd.h> // UNIX standard function definitions
#include <cstring> // C standard library definitions
#include <vector>
int main() {
// Open the serial port
int serial_port = open("/dev/ttyUSB0", O_RDWR);
// Check for errors
if (serial_port < 0) {
std::cerr << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << std::endl;
return 1;
}
// Create new termios struct, we call it 'tty' for convention
struct termios tty;
// Read in existing settings, and handle any error
if(tcgetattr(serial_port, &tty) != 0) {
std::cerr << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
return 1;
}
// Set Baud Rate to 115200
cfsetispeed(&tty, B115200);
cfsetospeed(&tty, B115200);
// Set other port settings
tty.c_cflag &= ~PARENB; // No parity bit
tty.c_cflag &= ~CSTOPB; // One stop bit
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; // 8 bits per byte
tty.c_cflag &= ~CRTSCTS; // No hardware flow control
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines
// Set input settings
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable special handling of received bytes
// Set output settings
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
// Set blocking settings
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
// Apply the settings to the port
if(tcsetattr(serial_port, TCSANOW, &tty) != 0) {
std::cerr << "Error " << errno << " from tcsetattr: " << strerror(errno) << std::endl;
return 1;
}
// Allocate memory for read buffer
char read_buf[256];
std::vector<unsigned char> message_buffer;
// Read data from the serial port
while(true) {
int num_bytes = read(serial_port, &read_buf, sizeof(read_buf));
// Check for errors
if (num_bytes < 0) {
std::cerr << "Error reading: " << strerror(errno) << std::endl;
break;
}
// Add the read bytes to the message buffer
for (int i = 0; i < num_bytes; ++i) {
message_buffer.push_back(static_cast<unsigned char>(read_buf[i]));
size_t len = message_buffer.size();
// Check if the buffer ends with 0xFF 0xFF 0xFF
if (len >= 3 && message_buffer[len-1] == 0xFF && message_buffer[len-2] == 0xFF && message_buffer[len-3] == 0xFF) {
// Print the message in hexadecimal format
std::cout << "Received message: ";
for (unsigned char c : message_buffer) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c) << " ";
}
std::cout << std::endl;
// Clear the message buffer for the next message
message_buffer.clear();
}
}
// Clear the read buffer for the next read
memset(&read_buf, '\0', sizeof(read_buf));
}
// Close the serial port
close(serial_port);
return 0;
}
cmake_minimum_required(VERSION 3.28)
project(read_usb)
set(CMAKE_CXX_STANDARD 20)
add_executable(read_usb main.cpp)