细分从串行端口

时间:2015-10-29 14:14:15

标签: c++ c arrays string

我使用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函数,因为它给出了输出0,因为r设置为零。在不知道字符串长度的情况下,我无法对其进行分段以获取以下数据。 考虑接收到的字符串56,我想在下面的变量

中的每次迭代中存储以下值
accLowX = 350, accLowY = 349, accLowZ=351
accHighX =353, accHighY = 341, accHighZ =421;

我该怎么办?

3 个答案:

答案 0 :(得分:0)

您可以使用sscanf,类似这样的内容 -

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

答案 1 :(得分:0)

我首先创建一个字符串数组并将每一行放入其中(可能使用getline?)然后,您可以使用boost的split函数并使用空格作为分隔符。然后,将所有这些放在一个临时数组中。 http://www.cplusplus.com/faq/sequences/strings/split/ - &gt;提升字符串算法:拆分

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

答案 2 :(得分:0)

在您提出宝贵意见后,我找到了解决问题的方法。此代码的灵感来自此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);
}