c++ - 将十六进制发送到 xbee radio 模块

标签 c++ linux serial-port xbee

我目前正在尝试将十六进制命令发送到 xbee radio 模块(API 模式)。

这是我的代码:

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

using namespace std;

int main()
{

   int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);


   if (fd < 0 ){
       cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl;
   }    
   else
   {
       struct termios tty;
       struct termios tty_old;
       memset (&tty, 0, sizeof tty);

       if (tcgetattr (fd, &tty) != 0){
           cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl;
       }

       tty_old = tty;

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

       tty.c_cflag &= ~PARENB;
       tty.c_cflag &= ~CSTOPB;
       tty.c_cflag &= ~CSIZE;
       tty.c_cflag |= CS8;
       tty.c_cflag &= ~CRTSCTS;
       tty.c_lflag = 0;
       tty.c_oflag = 0;
       tty.c_cc[VMIN] = 1;
       tty.c_cc[VTIME] = 50;

       tty.c_cflag |= CREAD | CLOCAL;

       cfmakeraw(&tty);

       tcflush(fd, TCIFLUSH);

       if (tcsetattr(fd, TCSANOW, &tty) != 0) {
           cout << "Error " << errno << " from tcsetattr" << endl;
       }

       unsigned char cmd1[] = {"\0x7E\0x00\0x04\0x08\0x69\0x43\0x54\0xF7"};

       sleep(1);
       int wr1 = write(fd, cmd1, 8);
       sleep(1);

       int rd;
       int spot = 0;
       char buff = '\0';


       char resp[128];
       memset(resp, '\0', sizeof(resp));

       do {
           rd = read(fd, &buff, 1);
           sprintf(&resp[spot], "%c", buff);
           spot += rd;
       } while (buff != '\r' && rd > 0);
       if (rd<0){
           cout << "Error reading: " << strerror(errno) << endl;
       }
       else if (rd==0) {
           cout << "Read nothing!" << endl;
       }
       else {
           cout << "Read: " << resp << endl;
       }

       close(fd);

    }
    return 0;
}

我也试过这样的:

    unsigned char cmd1[8];

    cmd1[0] = 0X7E;
    cmd1[1] = 0X00;
    cmd1[2] = 0X04;
    cmd1[3] = 0X08;
    cmd1[4] = 0X69;
    cmd1[5] = 0X43;
    cmd1[6] = 0X54;
    cmd1[7] = 0XF7;


    sleep(1);
    int wr1 = write(fd, cmd1, 8);

当我使用 AT 命令模式时,它工作得非常好,这是在 AT 命令模式下完全相同的代码(询问蜜蜂在“+++”之后在命令模式下持续多长时间):

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

using namespace std;

int main()
{

int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);


if (fd < 0 ){
    cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl;
}   
else
{
    struct termios tty;
    struct termios tty_old;
    memset (&tty, 0, sizeof tty);

    if (tcgetattr (fd, &tty) != 0){
        cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl;
    }

    tty_old = tty;

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

    tty.c_cflag &= ~PARENB;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    tty.c_cflag &= ~CRTSCTS;
    tty.c_lflag = 0;
    tty.c_oflag = 0;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 50;

    tty.c_cflag |= CREAD | CLOCAL;

    cfmakeraw(&tty);

    tcflush(fd, TCIFLUSH);

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        cout << "Error " << errno << " from tcsetattr" << endl;
    }

    unsigned char cmd1[] = {"+++"};
    sleep(1);
    int wr1 = write(fd, cmd1, sizeof(cmd1) -1);
    sleep(1);
    //printf("%d \n", wr1);
    unsigned char cmd2[] = {"ATCT\r"};

    int rd;
    int spot = 0;
    char buff = '\0';

    char resp[32];
    memset(resp, '\0', sizeof(resp));

    do {
        rd = read(fd, &buff, 1);
        sprintf(&resp[spot], "%c", buff);
        spot += rd;
    } while (buff != '\r' && rd > 0);
    if (rd<0){
        cout << "Error reading: " << strerror(errno) << endl;
    }
    else if (rd==0) {
        cout << "Read nothing!" << endl;
    }
    else {
        cout << "Read: " << resp << endl;
    }


    int wr2 = write(fd, cmd2, sizeof(cmd2) -1);
    //printf("%d \n", wr2);

    spot = 0;
    buff = '\0';


    sleep(1);
    do {
        rd = read(fd, &buff, 1);
        sprintf(&resp[spot], "%c", buff);
        spot += rd;
    } while (buff != '\r' && rd > 0);
    if (rd<0){
        cout << "Error reading: " << strerror(errno) << endl;
    }
    else if (rd==0) {
        cout << "Read nothing!" << endl;
    }
    else {
        cout << "Read: " << resp << endl;
    }
    close(fd);

    }
    return 0;
}

我得到的错误是

"Error reading: Resource temporarily unavailable".

我确定该设备没有被其他东西使用,因为使用 AT 命令的代码工作正常......就好像 Xbee 无法理解十六进制......

我希望其他人已经遇到过这个问题......

最佳答案

好吧,这有点笨……

我试图阅读以\r 结尾的答案,但真正的答案并没有以它结尾...

我改变了:

do {
    rd = read(fd, &buff, 1);
    sprintf(&resp[spot], "%c", buff);
    spot += rd;
} while (buff != 0x13 && rd > 0);

现在它工作正常。它只是试图读取不存在的字符。

编辑:

@VenushkaT 就这段代码中的一些问题问了我一个问题。因为我做了一些现在运行良好的事情,所以我发布了我的新代码:

void R1logger::listenPort()
{
// Creation of a buffer to store data from radio module

fill_n(buff, 2048, '\0');

this->ind = 0;

while(this->fd > 0)
{
    // Creation of a buffer that stores data from serial port
    char mes[1024];
    fill_n(mes, 1024, '0');
    // read is a blocking call so this function will not return until it effectively reads some data or if there is a problem
    int rd = read(this->fd, &mes, sizeof(mes));

    /*struct timeval tv;
    gettimeofday(&tv, NULL);
    unsigned long long check1 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;*/
    if (rd > 0)
    {
        storeInBuff(mes, rd);
        fill_n(mes, 1024, '0');

        // If some data are read, we can have only a part of the frame so we call "poll" to wait for the rest of the data with a 10ms timeout
        struct pollfd fds;
        fds.fd = this->fd;
        fds.events = POLLIN | POLLPRI;
        int slct = 1;

        while (slct > 0)
        {
            slct = poll(&fds, 1, 10);
            if (slct > 0)
            {
                rd = read(this->fd, &mes, sizeof(mes));
                if (rd > 0)
                {
                    storeInBuff(mes, rd);
                }
                else
                {
                    close(this->fd);
                    serialConfig();
                }
            }
        }

        /*gettimeofday(&tv, NULL);
        unsigned long long check2 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
        unsigned long tmps = check2 - check1;
        cout << "Temps de lecture : " << tmps << endl;*/

        /*gettimeofday(&tv, NULL);
        check1 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;*/

        // Once the message is entirely read, we extract the radio frames
        findFrame(0);

        /*gettimeofday(&tv, NULL);
        check2 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
        tmps = check2 - check1;
        cout << "Temps calcul + ecriture sur disque : " << tmps << endl;*/


        this->ind = 0;
        fill_n(buff, 2048, '\0');
    }
    else
    {
        close(this->fd);
        serialConfig();
    }
}
}

此代码使用较少的 CPU,因为有阻塞调用(读取、选择),并且没有设置 O_NONBLOCKING 选项。 我也考虑了读取失败的情况。

在另一篇文章中,一些人向我提出了有关串行配置的建议(某些选项存在一些错误,他们给了我更多 POSIX 兼容的建议,所以这里是:

void R1logger::serialConfig()
{

// Open Serial Port

this->fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);

if (this->fd < 0 )
{
    cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl;
}
else
{
    //Configure Serial Port
    struct termios tty;

    if (tcgetattr (this->fd, &tty) != 0)
    {
        cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl;
    }

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

    tty.c_cflag &= ~PARENB;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 50;

    tty.c_cflag |= CREAD | CLOCAL;

    cfmakeraw(&tty);

    tcflush(this->fd, TCIFLUSH);

    if (tcsetattr(this->fd, TCSANOW, &tty) != 0) 
    {
        cout << "Error " << errno << " from tcsetattr" << endl;
    }
}
}

关于c++ - 将十六进制发送到 xbee radio 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37134896/

相关文章:

c++ - Swig + tcl + c++(内存管理)

c++ - 使用从字符串中提取的参数调用函数

ruby-on-rails - 尝试将 Passenger/Nginx 用于我的 Rails 生产服务器,出现 403 错误

计算 posix read() 接收到的字节数

c++ - 如何在 Mac 插件中使用 ioctl() 设置 RTS?

c++ - C++ 中的默认函数参数必须保持不变吗?

c++ - OpenCV 2.4.3 中的阴影去除

linux - Git 部署回滚工作流程

linux - 将内核模块添加到 Debian

python-2.7 - Python 2.7 : serial. serialutil.SerialException : Port is already open. 如何关闭此端口?