将十六进制发送到xbee无线电模块

Sending Hexadecimal to a xbee radio module

本文关键字:xbee 无线电 模块 十六进制      更新时间:2023-10-16

我当前正在尝试将十六进制命令发送到xbee无线电模块(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[] = {"x7Ex00x04x08x69x43x54xF7"};
       sleep(1);
       int wr1 = write(fd, cmd1, 8);
       sleep(1);
       int rd;
       int spot = 0;
       char buff = '';

       char resp[128];
       memset(resp, '', 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[] = {"ATCTr"};
    int rd;
    int spot = 0;
    char buff = '';
    char resp[32];
    memset(resp, '', 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 = '';

    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;
}

我得到的错误是

"读取时出错:资源暂时不可用"。

我确信这个设备没有被其他人使用,因为使用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, '');
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, '');
    }
    else
    {
        close(this->fd);
        serialConfig();
    }
}
}

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

在另一篇文章中,一些人向我提出了串行配置的建议(有些选项上有一些错误,他们建议我更符合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;
    }
}
}