繁体   English   中英

分割从串口接收的字符串

[英]Segmenting the strings received from serial port

我正在使用Xbee模块通过串行端口接收传感器数据。 传感器已连接到Arduino,并且正在将数据发送到连接到我的笔记本电脑的zigbee。 这是我用来显示接收到的数据的代码。

#include <fcntl.h>
#include <stdio.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>

/* Change to the baud rate of the port B2400, B9600, B19200 etc as per Arduino board is sending */
#define SPEED B9600

/* Change to the serial port you want to use /dev/ttyUSB0, /dev/ttyS0, etc. */
#define PORT "/dev/ttyS1"


/* Sensor raw datas */
int accLowX, accLowY, accLowZ;
int accHighX, accHighY, accHighZ;


int main( ){
    int fd = open( PORT, O_RDONLY | O_NOCTTY );
    if (fd <0) {perror(PORT); exit(-1); }
    struct termios options;

    bzero(&options, sizeof(options));
    options.c_cflag = SPEED | CS8 | CLOCAL | CREAD | IGNPAR;
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &options);

    int r;
    char buf[255];
    char sensorDatas[255];

    while( 1 ){

        r = read( fd, buf, 255 );
        buf[r]=0;
        memcpy(sensorDatas, buf, strlen(buf)+1);
        printf( "%s", sensorDatas);

        // separate the strings for sensor datas




        //




    }


}

我收到的数据输出为:

56-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:341 AHZ:421
57-ALX:350 ALY:349 ALZ:351 AHX:354 AHY:341 AHZ:422
58-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
59-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
60-ALX:350 ALY:349 ALZ:351 AHX:352 AHY:342 AHZ:422
61-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:421
62-ALX:350 ALY:349 ALZ:351 AHX:354 AHY:342 AHZ:422
63-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
64-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
65-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:421
66-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:421
67-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
68-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
69-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:341 AHZ:421
70-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
71-ALX:350 ALY:349 ALZ:351 AHX:352 AHY:342 AHZ:422
72-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
73-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
74-ALX:350 ALY:349 ALZ:351 AHX:352 AHY:342 AHZ:422
75-ALX:350 ALY:349 ALZ:351 AHX:352 AHY:342 AHZ:422
76-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
77-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
78-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:421
79-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
80-ALX:350 ALY:350 ALZ:351 AHX:353 AHY:343 AHZ:422
81-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422
82-ALX:350 ALY:349 ALZ:351 AHX:353 AHY:342 AHZ:422

在这里我不能使用strlen函数,因为r设为zo时,它给我输出0。 在不知道字符串长度的情况下,我无法继续对其进行分段以获取以下数据。 考虑接收到的字符串56,我想在每次迭代中将以下值存储在以下变量中

accLowX = 350, accLowY = 349, accLowZ=351
accHighX =353, accHighY = 341, accHighZ =421;

我该怎么做?

您可以使用sscanf ,像这样-

if(sscanf(s,"%*[^:]:%d %*[^:]:%d %*[^:]:%d %*[^:]:%d %*[^:]:%d %*[^:]:%d"
                   ,&accLowX,&accLowY,&accLowZ,&accHighX,&accHighY,&accHighZ))==6){
       // do something 
 }

我将从创建一个字符串数组开始,然后将每行放入其中(可能带有getline ?),然后,您可以使用boost的split函数并使用空格作为定界符。 然后,将所有这些放入一个临时数组中。 http://www.cplusplus.com/faq/sequences/strings/split/- > Boost字符串算法:拆分

之后,只需使用findhttp://www.cplusplus.com/reference/string/string/find/ )来识别每个参数,并为每个参数使用开关大小写。 或者,使用数组并直接使用它,因为所有位置都相同(例如:[0] = ALX:(Number),[1] = ALY:(Number),等等)。 希望能有所帮助。

经过您的宝贵建议,我找到了解决问题的方法。 此代码受此CodeSource的启发

修改后的代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BAUDRATE B9600  /* baudrate settings are defined in <asm/termbits.h>, which is included by <termios.h> */
#define MODEMDEVICE "/dev/ttyS1" /* change this definition for the correct port */
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE; 

int main()
{
    int fd,c, res;
    struct termios oldtio,newtio;
    char buf[255];
    char sensorDatas[255];
    /* Sensor raw datas */
    int accLowX, accLowY, accLowZ;
    int accHighX, accHighY, accHighZ;
    /* 
    Open modem device for reading and writing and not as controlling tty
    because we don't want to get killed if linenoise sends CTRL-C.
    */
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
    if(fd <0) {
        perror(MODEMDEVICE); 
        exit(-1); 
        }

    tcgetattr(fd,&oldtio); /* save current serial port settings */
    //bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

    /* 
    BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
    CRTSCTS : output hardware flow control (only used if the cable has
            all necessary lines. See sect. 7 of Serial-HOWTO)
    CS8     : 8n1 (8bit,no parity,1 stopbit)
    CLOCAL  : local connection, no modem contol
    CREAD   : enable receiving characters
    */
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

    /*
    IGNPAR  : ignore bytes with parity errors
    ICRNL   : map CR to NL (otherwise a CR input on the other computer
            will not terminate input)
    otherwise make device raw (no other input processing)
    */
    newtio.c_iflag = IGNPAR | ICRNL;

    /*
    Raw output.
    */
    newtio.c_oflag = 0;

    /*
    ICANON  : enable canonical input
    disable all echo functionality, and don't send signals to calling program
    */
    newtio.c_lflag = ICANON;

    /* 
    initialize all control characters 
    default values can be found in /usr/include/termios.h, and are given
    in the comments, but we don't need them here
    */
    newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
    newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
    newtio.c_cc[VERASE]   = 0;     /* del */
    newtio.c_cc[VKILL]    = 0;     /* @ */
    newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
    newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
    newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
    newtio.c_cc[VSWTC]    = 0;     /* '\0' */
    newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
    newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
    newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
    newtio.c_cc[VEOL]     = 0;     /* '\0' */
    newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
    newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
    newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
    newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
    newtio.c_cc[VEOL2]    = 0;     /* '\0' */

    /* 
    now clean the modem line and activate the settings for the port
    */
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);

    /*
    terminal settings done, now handle input
    In this example, inputting a 'z' at the beginning of a line will 
    exit the program.
    */
    while (STOP==FALSE) {     /* loop until we have a terminating condition */
    /* read blocks program execution until a line terminating character is 
    input, even if more than 255 chars are input. If the number
    of characters read is smaller than the number of chars available,
    subsequent reads will return the remaining chars. res will be set
    to the actual number of characters actually read */
    res = read(fd,buf,255); 
    memcpy(sensorDatas, buf, strlen(buf)+1);
    buf[res]=0;             /* set end of string, so we can printf */
    sensorDatas[res]=0;
    printf("%s", sensorDatas);

    /* Segmentation of Datas received from Arduino  */
    if(sscanf(sensorDatas,"%*[^:]:%d %*[^:]:%d %*[^:]:%d %*[^:]:%d %*[^:]:%d %*[^:]:%d"
                   ,&accLowX,&accLowY,&accLowZ,&accHighX,&accHighY,&accHighZ)==6) {
        // do something 

        printf( "accLowX : %d\n", accLowX);
        printf( "accLowY : %d\n", accLowY);
        printf( "accLowZ : %d\n", accLowZ);

    }


    }
    /* restore the old port settings */
    tcsetattr(fd,TCSANOW,&oldtio);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM