【问题标题】:How do I change the baud rate for a LoRa device?如何更改 LoRa 设备的波特率?
【发布时间】:2020-04-16 05:52:52
【问题描述】:

我有一个 LoRa 设备,它在树莓派的 USB 端口上使用默认波特率 57600。我想尝试更快的串行波特率。从设备睡眠状态返回后更改波特率的说明如下:

我有一个主要问题是我不知道串行端口通信中的“中断”代码是什么。我尝试了各种方法,包括以下(其中 usb_port 是打开端口的文件描述符):

ioctl(usb_port, TCSBRK, 0);

std::string msg;
msg="0X00";
write(usb_port, msg.c_str(), msg.size());

一切都没有运气。谁能看看这个 c++ 函数并告诉我哪里出错了?

在文档的其他地方,表明写入“0x55”会在从睡眠状态返回时触发自动波特率检测设置。

注意:“/dev/ttyUSBPort1”的无线电设备文件描述符是对使用 udev 串行规则设置的 /dev/ttyUSB0 的引用。

const char* radiodevice = "/dev/ttyUSBPort1";
int openPort(void) {
    struct termios tty;
    memset(&tty, 0, sizeof tty);
    if ((usb_port = open(radiodevice, O_RDWR | O_NOCTTY | O_SYNC))>=0) {// | O_NOCTTY | O_SYNC
        std::cout << "DEVICE OPENED: " << radiodevice << " handle number: " << usb_port << std::endl;
    } else {
        fprintf(stderr, "unable to open serial radiodevice");
        return -1;
    }
    if(tcgetattr(usb_port, &tty) != 0) {
        printf("Error %i \n", errno);
    }
    cfsetispeed(&tty, B57600);
    cfsetospeed(&tty, B57600);
    tty.c_cflag     &=  ~PARENB;            // Make 8n1
    tty.c_cflag     &=  ~CSTOPB;
    tty.c_cflag     &=  ~CSIZE;
    tty.c_cflag     |=  CS8;
    tty.c_cflag     &=  ~CRTSCTS;           // no flow control
    tty.c_cc[VMIN]   =  0;                  // read doesn't block
    tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
    tty.c_iflag &= ~ISTRIP;
    tty.c_iflag &= ~INLCR;
    tty.c_iflag &= ~IGNCR;
    tty.c_iflag &= ~ICRNL;
    tty.c_oflag &= OPOST;
    tty.c_lflag &= ICANON;
    tcflush(usb_port,TCIOFLUSH);
    usleep(10000);
    if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
        printf("Error %i\n", errno);
    }

    //FLASH UNIT LED LIGHTS TO CONFIRM INITIAL CONNECTION
    std::string msg="sys set pindig GPIO11 1\r\n";
    write(usb_port, msg.c_str(), msg.size());
    usleep(1000000);
    msg="sys set pindig GPIO11 0\r\n";
    write(usb_port, msg.c_str(), msg.size());
    usleep(10000);

    //WRITE SLEEP COMMAND TO DEVICE FOR 0.5 SECONDS
    std::cout << "WRITING SLEEP COMMAND" << std::endl;
    msg="sys sleep 5000\r\n";//
    write(usb_port, msg.c_str(), msg.size());
    usleep(100000);

    //ATTEMPT TO SEND BREAK COMMAND
    ioctl(usb_port, TCSBRK, 0);
    usleep(500000);

    //RESET SERIAL BAUD RATE
    cfsetispeed(&tty, B115200);
    cfsetospeed(&tty, B115200);

    //SET DEVICE TO AUTO-BAUD RATE DETECTION
    std::cout << "SENDING 0x55" << std::endl;
    msg="0x55";
    write(usb_port, msg.c_str(), msg.size());
    usleep(2000000);

    //FLASH UNIT LED LIGHTS TO CONFIRM FINAL CONNECTION AT NEW BAUD RATE
    std::cout << "BLINKING LIGHTS" << std::endl;
    msg="sys set pindig GPIO11 1\r\n";
    write(usb_port, msg.c_str(), msg.size());
    usleep(1000000);
    msg="sys set pindig GPIO11 0\r\n";
    write(usb_port, msg.c_str(), msg.size());

    return usb_port;
}

【问题讨论】:

  • 在一个字符时间段内将数据线拉到与起始位相同的电压,可能更长......在 57600 波特下,这将是 200 微秒或更长时间
  • @jsotola ,您所说的代码方面是什么意思?那么用什么来代替 ioctl(usb_port, TCSBRK, 0);?
  • 我没有看代码...我只是说串行通信中的中断... LoRa设备实际上可能具有中断字符序列,就像旧调制解调器一样有 ... 对于调制解调器,休息时间是 +++ ... 尝试一下不会有什么坏处
  • 是的,有一个单独的参考将 UART_RX 引脚拉低,我认为这就是您所说的。但是,该引脚无法在固件中拉低……这很奇怪。根据文档可用的管脚有 GPIO0-GPIO13, UART_CTS, UART_RTS, TEST0, TEST1
  • Break 是一个条件,而不是一个字符。它是 UART 的传输能力,可通过串行终端 ioctl() 和 POSIX 函数访问。

标签: c++ serial-port baud-rate


【解决方案1】:

对于那些可能正在寻找此解决方案的人,这是我完成将 LoRa 设备设置为自动波特率模式并以新的波特率打开端口的任务的方法:

    int openPort(void) {
        struct termios tty;
        memset(&tty, 0, sizeof tty);
        //OPEN PORT WITH DEFAULT BAUD RATE 57600
        if ((usb_port = open(radiodevice, O_RDWR | O_NOCTTY | O_SYNC))>=0) {// | O_NOCTTY | O_SYNC
            std::cout << "DEVICE OPENED: " << radiodevice << " handle number: " << usb_port << std::endl;
        } else {
            fprintf(stderr, "unable to open serial radiodevice");
            return -1;
        }
        if(tcgetattr(usb_port, &tty) != 0) {
            printf("Error %i \n", errno);
        }
        cfsetispeed(&tty, B57600);
        cfsetospeed(&tty, B57600);
        tty.c_cflag     &=  ~PARENB;            // Make 8n1
        tty.c_cflag     &=  ~CSTOPB;
        tty.c_cflag     &=  ~CSIZE;
        tty.c_cflag     |=  CS8;
        tty.c_cflag     &=  ~CRTSCTS;           // no flow control
        tty.c_cc[VMIN]   =  0;                  // read doesn't block
        tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
        tty.c_iflag &= ~ISTRIP;
        tty.c_iflag &= ~INLCR;
        tty.c_iflag &= ~IGNCR;
        tty.c_iflag &= ~ICRNL;
        tty.c_oflag &= OPOST;
        tty.c_lflag &= ICANON;
        tcflush(usb_port,TCIOFLUSH);
        //usleep(10000);
        if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
            printf("Error %i\n", errno);
        }

        //FLASH UNIT LED LIGHTS TO CONFIRM INITIAL CONNECTION
        std::string msg="sys set pindig GPIO11 1\r\n";
        write(usb_port, msg.c_str(), msg.size());
        usleep(1000000);
        msg="sys set pindig GPIO11 0\r\n";
        write(usb_port, msg.c_str(), msg.size());
        usleep(10000);

        //WRITE SLEEP COMMAND TO DEVICE FOR 0.5 SECONDS
        std::cout << "WRITING SLEEP COMMAND" << std::endl;
        msg="sys sleep 5000\r\n";
        write(usb_port, msg.c_str(), msg.size());
        usleep(100000);

        close(usb_port);

        //OPEN PORT AT NEW BAUD RATE
        if ((usb_port = open(radiodevice, O_RDWR | O_NOCTTY | O_SYNC))>=0) {// | O_NOCTTY | O_SYNC
            std::cout << "DEVICE OPENED: " << radiodevice << " handle number: " << usb_port << std::endl;
        } else {
            fprintf(stderr, "unable to open serial radiodevice");
            return -1;
        }
        if(tcgetattr(usb_port, &tty) != 0) {
            printf("Error %i \n", errno);
        }

        //RESET SERIAL BAUD RATE
        cfsetispeed(&tty, B230400);<---SET NEW BAUD RATE VALUE
        cfsetospeed(&tty, B230400);<---SET NEW BAUD RATE VALUE
        tty.c_cflag     &=  ~PARENB;            // Make 8n1
        tty.c_cflag     &=  ~CSTOPB;
        tty.c_cflag     &=  ~CSIZE;
        tty.c_cflag     |=  CS8;
        tty.c_cflag     &=  ~CRTSCTS;           // no flow control
        tty.c_cc[VMIN]   =  0;                  // read doesn't block
        tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
        tty.c_iflag &= ~ISTRIP;
        tty.c_iflag &= ~INLCR;
        tty.c_iflag &= ~IGNCR;
        tty.c_iflag &= ~ICRNL;
        tty.c_oflag &= OPOST;
        tty.c_lflag &= ICANON;
        tcflush(usb_port,TCIOFLUSH);
        usleep(10000);
        if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
            printf("Error %i\n", errno);
        }

        //SEND BREAK COMMAND
        std::cout << "SENDING BREAK COMMAND" << std::endl;
        tcsendbreak(usb_port, 0);
        usleep(10000);

        //SET DEVICE TO AUTO-BAUD RATE DETECTION
        msg = "U";//CORRESPONDS TO DOCUMENTED CHARACTER 0x55
        write(usb_port, msg.c_str(), msg.size());

        //FLASH UNIT LED LIGHTS TO CONFIRM FINAL CONNECTION AT NEW BAUD RATE
        std::cout << "BLINKING LIGHTS" << std::endl;
        msg="sys set pindig GPIO11 1\r\n";
        write(usb_port, msg.c_str(), msg.size());
        usleep(1000000);
        msg="sys set pindig GPIO11 0\r\n";
        write(usb_port, msg.c_str(), msg.size());

        return usb_port;
    }

【讨论】:

  • 您的 termios 设置毫无意义。 tty.c_oflag &amp;= OPOSTtty.c_lflag &amp;= ICANON; 真的是你想要的吗?既不设置也不清除规范模式;这只保留了已经存在的任何模式。 VMIN 和 VTIME 值仅在(输入)非规范模式下有意义。您正在使用什么模式,或者更确切地说打算使用什么模式?
  • @sawdust 老实说,我不知道。它有效,但我相信它可以大大改进。您是否建议完全删除 ICANON 标志?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-15
  • 2011-07-31
  • 1970-01-01
  • 2021-11-14
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多