linux与arduino的串行通信

9udxz4iz  于 2023-06-05  发布在  Linux
关注(0)|答案(1)|浏览(258)

我正试图使一个命令行,从我的电脑到ESP-32,我不想依赖于Arduino串行监视器的互动,所以我正试图写一个小的应用程序的通信.但它不起作用,我基于这个教程进行了沟通:https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/但是,我没有看到任何输出从董事会。这是我当前的代码:

#include <fcntl.h>    //
#include <errno.h>    // THESE ARE THE LIBRARIES THAT WILL BE USED
#include <termios.h>  // FOR THE TERMINAL COMMUNICATION WITH SERIAL PORTS
#include <unistd.h>   //

#include "auxiliar.h"

std::string _OUT [28];

class _SERIAL_TERM_ {
    public:
        int _SERIAL_PORT_;
        int _drw_pointer = 0;
        struct termios tty;
        _SERIAL_TERM_(int); // INITIALIZE
        void fire_confg();  // CREATE CONFIG
        void fire_Print(std::string _msg);
        void fire_input(std::string _inp);
};

_SERIAL_TERM_ :: _SERIAL_TERM_(int _s){
    _SERIAL_PORT_ = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(_SERIAL_PORT_ < 0){
        fire_Print("Could not connect ignite monitor to /dev/ttyUSB0");
        printf("Error %i from open: %s\n", errno, strerror(errno));
    }
    if(tcgetattr(_SERIAL_PORT_, &tty) != 0) {
        fire_Print("Serial communication failed on tcgetattr config.");
        printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
    }
    fire_confg();
}

void _SERIAL_TERM_ :: fire_confg(){
  /*
   THIS IS THE TERMIOS BASIC CONFIGURATION
   I'D LIKE TO THANK mbedded.ninja FOR HIS ARTICLE
   TEACHING HOW TO CONFIGURATE THIS, IT WAS LITERALLY PAIN
   AND I COULDN'T FIND A GOOD INFORMATION SOURCE
   https://blog.mbedded.ninja/ <- visit his website
  */
  tty.c_cflag &= ~PARENB;
  tty.c_cflag &= ~CSTOPB; 
  tty.c_cflag &= ~CSIZE; 
  tty.c_cflag |= CS8; 
  tty.c_cflag &= ~CRTSCTS; 
  tty.c_cflag |= CREAD | CLOCAL; 

  tty.c_lflag &= ~ICANON;
  tty.c_lflag &= ~ECHO; 
  tty.c_lflag &= ~ECHOE; 
  tty.c_lflag &= ~ECHONL; 
  tty.c_lflag &= ~ISIG;
  tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
  tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);

  tty.c_oflag &= ~OPOST;
  tty.c_oflag &= ~ONLCR; 

  tty.c_cc[VTIME] = 0;  
  tty.c_cc[VMIN] = 0;

  cfsetispeed(&tty, B9600);
  cfsetospeed(&tty, B9600);
  if (tcsetattr(_SERIAL_PORT_, TCSANOW, &tty) != 0) {
    fire_Print("Termios failed to configure basic settings :(");
    printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
  }
}

void _SERIAL_TERM_ :: fire_Print(std::string _msg){
    _OUT[_drw_pointer] =  _msg;
    _drw_pointer++;
    //std::cout<<"draw pointer"<<_drw_pointer<<std::endl;
    if(_drw_pointer >= 28){
        for(int i = 0; i < 28; i++){
            _OUT[i] = "";
        }
        _drw_pointer = 0;
    }
}

void _SERIAL_TERM_ :: fire_input(std::string _inp){
    unsigned char msg[256];                 // INITIALLIZE OUR BUFFER TO SEND THE DATA
    strcpy( (char*) msg, _inp.c_str() ); // COPY OUR COMMAND INTO THE BUFFER
    printf("{INPUT} write bytes. sent message: %s\n", msg);
    write(_SERIAL_PORT_, msg, sizeof(msg)); // WRITE TO THE SERIAL PORT (AS A FILE)
    memset(&msg, '\0', sizeof(msg));        // CLEAN MEMORY
    char _output[1024];                     // INITIALIZE OUTPUT BUFFER
    memset(&_output, '\0', sizeof(_output));// CLEAN OUTPUT BUFFER
    int num_bytes = read(_SERIAL_PORT_, &_output, sizeof(_output));  // READ THE BUFFER OUTPUT
    if (num_bytes < 0) {                                             // IF THERE ARE 0 BYTES IN OUTPUT
      fire_Print("ERROR: could not read output from serial port...");// PRINT ERROR
      printf("Error reading: %s", strerror(errno));                  // LOG ERR MESSAGE
    }
    std::string _out = atos(_output);
    printf("{OUTPUT} Read %i bytes. Received message: %s\n", num_bytes, _output);
    fire_Print(_out);
    //fire_Print(_inp);                       // PRINT OUTPUT
}

_SERIAL_TERM_ *_term = new _SERIAL_TERM_(9600);

std::string _my_input = "";
void FIRE_INPUT_KEYBOARD (unsigned char key, int x, int y){
    if(key != 13){
        _my_input += key;
    }else{
        _term->fire_input(_my_input);
        _my_input = "";
    }
}

我的ESP 32代码是这样的:

int _RTOS_SHELL_UPDATE_ (){
    last_data = "";
    data = Serial.readStringUntil('\r\n');
    if(data.length() == 0){
        last_data = "";
    }else{
        last_data = _RTOS_CORE_EXECUTE_ (data);
        Serial.println("(Input command) root@phoenix>> " + last_data + " size: " + data.length());
    }
    return _RTOS_SUCCESS_; 
}

每当我执行代码时,我得到:

{INPUT} write bytes. sent message: kjknj
{OUTPUT} Read 0 bytes. Received message:

每当我尝试使用终端写入或读取文件时,它都保持为空
我已经尝试使用以下命令拦截该消息:

while true; do cat /dev/ttyUSB0; done

(it肯定是usb 0,我用arduino IDE测试过)
edit:如果你需要测试和编译这些东西,这里是当前版本的github repo:
https://github.com/Chocobonis/phoenix-OS

7cjasjjr

7cjasjjr1#

我将你的程序简化为最小的端口初始化和简单的读取:

#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(int argc, char **argv)
{
    const char *device = "/dev/ttyUSB0";
    if (argv[1]) {
        device = argv[1];
    }

    int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        fprintf(stderr, "open(%s): %s\n", device, strerror(errno));
        return 1;
    }

    struct termios tty;

    if (tcgetattr(fd, &tty) != 0)
    {
        fprintf(stderr, "tcgetattr(%s): %s\n", device, strerror(errno));
        return 1;
    }

    tty.c_cflag &= ~PARENB;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    tty.c_cflag &= ~CRTSCTS;
    tty.c_cflag |= CREAD | CLOCAL;

    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO;
    tty.c_lflag &= ~ECHOE;
    tty.c_lflag &= ~ECHONL;
    tty.c_lflag &= ~ISIG;
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);

    tty.c_oflag &= ~OPOST;
    tty.c_oflag &= ~ONLCR;

    tty.c_cc[VTIME] = 0;
    tty.c_cc[VMIN] = 0;

    cfsetispeed(&tty, B9600);
    cfsetospeed(&tty, B9600);

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        fprintf(stderr, "tcgetattr(%s): %s\n", device, strerror(errno));
        return 1;
    }

    unsigned char buffer[1024];

    for (;;) {
        ssize_t num_bytes = read(fd, &buffer, sizeof(buffer));
        if (num_bytes == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                continue;
            }
            fprintf(stderr, "read(%s): %s\n", device, strerror(errno));
            break;
        }
        if (num_bytes > 0) {
            printf("%zi bytes received:\n", num_bytes);

            for (ssize_t i = 0; i < num_bytes; ++i)
                printf(" %02X", buffer[i]);

            printf(" (");
            for (ssize_t i = 0; i < num_bytes; ++i)
                printf(" %c", isprint(buffer[i]) ? buffer[i] : '?' );

            printf(")\n");
        }
    }

    close(fd);

    return 0;
}

在设备上运行最小草图:

void setup()
{
  Serial.begin(9600);
  Serial.println("Hello World!");
}

void loop()
{
}

设备启动后的输出:
这只是一个概念的证明。先试着复制一下。
当然,程序在轮询读取时消耗100%的CPU。减少CPU消耗的最简单方法是从open()标志中删除O_NDELAY,并将VTIME设置为1。

相关问题