header.h
#include <iostream>
#include <thread>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include "com_port.c"
short int ArduinoPort = serialport_init("/dev/ttyUSB0", 9600);
int serialport_read_until(int fd, char* buf, char until);
int serialport_write(short int &fd, const char* str);
com_port.c
int serialport_write(short int &fd, const char* str){ // Пишем данные в порт ардуинки
static int LastTime = 0;
int NowTime = time(NULL);
if((NowTime - LastTime) <= 1) // Если после прошлого выхова прошло меньше секунды - делаем паузу
std::this_thread::sleep_for (std::chrono::milliseconds(1400));
LastTime = time(NULL); // Сохраняем метку для следующего вызова
int len = strlen(str);
int n = write(fd, str, len);
if(n!=len)
return -1;
return 0;
}
int serialport_read_until(int fd, char* buf, char until){ // Читаем данные из порта ардуинки
char b[1];
int i=0;
do {
int n = read(fd, b, 1); // Читываем по символу за раз
if(n == -1)
return -1; // Если чтение не удалось - завераем работу
if(n == 0){
usleep( 10 * 1000 ); // ждём 10 милисекунд и повторяем попытку
continue;
}
buf[i] = b[0];
i++;
} while( b[0] != until);
buf[i] = 0; // Завершаем строку
return 0;
}
// принимает строковое имя последовательного порта (например, "/dev/tty.usbserial","COM 1")
// и скорость передачи данных в бодах (bps) и подключается к этому порту с такой скоростью и 8N1.
// открывает порт в полностью необработанном режиме, чтобы вы могли отправлять двоичные данные.
// возвращает допустимый fd или -1 при ошибке
int serialport_init(const char* serialport, int baud){
struct termios toptions;
int fd;
//fprintf(stderr,"init_serialport: opening port %s @ %d bps\n",
// serialport,baud);
fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("init_serialport: Unable to open port ");
return -1;
}
if (tcgetattr(fd, &toptions) < 0) {
perror("init_serialport: Couldn't get term attributes");
return -1;
}
speed_t brate = baud; // let you override switch below if needed
switch(baud) {
case 4800: brate=B4800; break;
case 9600: brate=B9600; break;
#ifdef B14400
case 14400: brate=B14400; break;
#endif
case 19200: brate=B19200; break;
#ifdef B28800
case 28800: brate=B28800; break;
#endif
case 38400: brate=B38400; break;
case 57600: brate=B57600; break;
case 115200: brate=B115200; break;
}
cfsetispeed(&toptions, brate);
cfsetospeed(&toptions, brate);
// 8N1
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
// no flow control
toptions.c_cflag &= ~CRTSCTS;
toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
toptions.c_oflag &= ~OPOST; // make raw
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 20;
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("init_serialport: Couldn't set term attributes");
return -1;
}
return fd;
}
main.cpp
#include "cpp/header.h"
using namespace std;
int main(int argc, const char *argv[]){
setlocale(LC_ALL, "ru");
char buf[256];
int LastSend = 0;
char res = '1';
while(LastSend >= 0){
res = (res == '1') ? '0' : '1'; // Меняем единичку и нолик местами, чтоб зажигать и выключать светодиод
LastSend = serialport_write(ArduinoPort, (res + "cdwd"s).c_str()); // Отправялем строку ардуинке
this_thread::sleep_for (chrono::milliseconds(1000)); // Ждём одну секунду
serialport_read_until(ArduinoPort, buf, '\n'); // Читаем ответ
cout << "Получили ответ: " << buf << endl;
}
return 0;
}