首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux串行端口-无法接收某些控制字符

Linux串行端口-无法接收某些控制字符
EN

Stack Overflow用户
提问于 2016-11-18 21:06:19
回答 1查看 630关注 0票数 2

我有一个开发板,它使用USB-Serial适配器连接到我的PC。从电路板上,我发送了8个字节的IEEE mac地址,但由于某种原因,我没有接收到某些字节。

在我的PC上,我有一个守护进程在运行,它监视串行端口,并在终端上打印收到的字符。

由于某种原因,未接收到值0x12 (DC2 (设备控制2))。我知道它是由我的开发板发送的,因为我正在嗅探其中的串行输出,我可以看到发送的是0x12。

我对linux没有足够的经验,但我感觉这可能是我在C代码中初始化串行端口的方式(假设跳过的字符是控制字符)。

我也尝试了发送0x11 (DC1),我可以成功地接收到。

我的代码是

代码语言:javascript
复制
serial_fd serial_open(char* serial_tty_path)
{
        //OPEN SERIAL PORT SPECIFIED BY THE ARGUMENT
        //AND RETURN HANDLE

        int32_t fd = open(serial_tty_path, O_RDONLY | O_NOCTTY);
        return (serial_fd)fd;
}

int8_t serial_setup(serial_fd fd, uint32_t serial_baud)
{
        //SET THE SPECIFIED SPEED, LENGTH, PARITY NAND STOP BIT
        //PARAMETERS FOR THE SUPPLIED SERIAL HANDLE

        struct termios serial_settings;
        uint32_t baudrate = B9600;

        switch(serial_baud)
        {
                case 2400:
                        baudrate = B2400;
                        break;
                case 4800:
                        baudrate = B4800;
                        break;
                case 9600:
                        baudrate = B9600;
                        break;
                case 115200:
                        baudrate = B115200;
                        break;
                default:
                        //invalid baudrate
                        return -1;
        };

        tcgetattr(fd, &serial_settings);

        //set the same input & output serial speed
        cfsetispeed(&serial_settings, baudrate);
        cfsetospeed(&serial_settings, baudrate);

        //seup serial for 8N1
        //no parity
        serial_settings.c_cflag &= ~PARENB;
        //stop bits = 1
        serial_settings.c_cflag &= ~CSTOPB;
        //data length = 8
        serial_settings.c_cflag &= ~CSIZE;
        serial_settings.c_cflag |= CS8;

        //set other serial control options
        //turn hardware flow control off
        serial_settings.c_cflag &= ~CRTSCTS;
        //turn software flow control off
        serial_settings.c_iflag &= ~(IXON | IXOFF | IXANY);
        //turn on the receiver on serial port
        serial_settings.c_cflag |= (CREAD | CLOCAL);

        //set the serial port mode of operation to NON CANONICAL
        //data available to program as soon as it's types
        //serial_settings.c_iflag &= ~(ICANON | ECHO | ECHO | ISIG);

        //set the minimum character to read from port to 1
        serial_settings.c_cc[VMIN] = 1;

        //set read timeout to 0.1 second (1 decisecond)
        serial_settings.c_cc[VTIME] = 2;

        //apply the settings to the serial port
        tcsetattr(fd, TCSANOW, &serial_settings);
}

int8_t serial_getc(serial_fd fd, uint8_t* c)
{
        //GET ONE CHAR FROM THE SERIAL RX BUFFER
        //RETURN -1 ON ERROR
        //ASCII CHARACTER RETURNED IN SUPPLIED CHARACTER POINTER

    uint8_t d=0;
    if(read(fd, &d, 1)<1)
    {
        perror("msg ");
        return -1;
    }
    *c = d;
    if(d == 0x12)
    {
        printf("hola !\n");
    }
    return 0;
}

    uint8_t serial_readline(serial_fd fd, uint8_t* buffer)
{
        //READ INCOMING SERIAL CHARACTERS INTO THE SPECIFIED BUFFER
        //TILL LF(\n) RECEIVED
        //RETURN : BYTES READ TILL \n (including \n)

        uint8_t read_char;
        int8_t status;
        uint32_t counter = 0;

        status = serial_getc(fd, &read_char);
        if(status != -1)
        {
                while(read_char != '\n')
                {
                        buffer[counter] = read_char;
                        counter++;

                        while(serial_getc(fd, &read_char) == -1){};
                }
                buffer[counter] = '\n';
                return counter;
        }
        return 0;
}

这是我的主程序

代码语言:javascript
复制
while(1)
        {   

                if((l = serial_readline(serial_handle, &serial_buffer[0])) != 0)
                {
                        //ACTUAL LINE READ FROM SERIAL
                        if(serial_buffer[0] == '#')
                        {
                                printf("l = %d\n", l);
                //SENSOR MESSAGE
                printf("*** received sensor message\n-*** Sending data to backend\n");
                printf("%s\n", serial_buffer);

                for(m=1; m<=21; m++)
                {
                    printf("data : %c, %02X\n", serial_buffer[m], serial_buffer[m]);
                }

                //populate the json request buffer
                //sensor mac address (8 bytes)
                //note sprintf adds a null terminated char after its output. need to replace
                //it manually !
                sprintf(&rpc_request_buffer[87], "%02X", serial_buffer[1]);
                rpc_request_buffer[89] = ':';
                sprintf(&rpc_request_buffer[90], "%02X", serial_buffer[2]);
                rpc_request_buffer[92] = ':';
                sprintf(&rpc_request_buffer[93], "%02X", serial_buffer[3]);
                rpc_request_buffer[95] = ':';
                sprintf(&rpc_request_buffer[96], "%02X", serial_buffer[4]);
                rpc_request_buffer[98] = ':';
                sprintf(&rpc_request_buffer[99], "%02X", serial_buffer[5]);
                rpc_request_buffer[101] = ':';
                sprintf(&rpc_request_buffer[102], "%02X", serial_buffer[6]);
                rpc_request_buffer[104] = ':';
                sprintf(&rpc_request_buffer[105], "%02X", serial_buffer[7]);
                rpc_request_buffer[107] = ':';
                sprintf(&rpc_request_buffer[108], "%02X", serial_buffer[8]);
                rpc_request_buffer[110] = '\"';

                //amr readings
                sprintf(&rpc_request_buffer[136], "%05u", util_8_bit_to_16_bit_unsigned(serial_buffer[9], serial_buffer[10]));
                rpc_request_buffer[141] = '-';
                sprintf(&rpc_request_buffer[142], "%05u", util_8_bit_to_16_bit_unsigned(serial_buffer[11], serial_buffer[12]));
                rpc_request_buffer[147] = '-';
                sprintf(&rpc_request_buffer[148], "%05u", util_8_bit_to_16_bit_unsigned(serial_buffer[13], serial_buffer[14]));
                rpc_request_buffer[153] = '-';
                sprintf(&rpc_request_buffer[154], "%05u", util_8_bit_to_16_bit_unsigned(serial_buffer[15], serial_buffer[16]));
                rpc_request_buffer[159] = '-';
                sprintf(&rpc_request_buffer[160], "%05u", util_8_bit_to_16_bit_unsigned(serial_buffer[17], serial_buffer[18]));
                rpc_request_buffer[165] = '-';
                sprintf(&rpc_request_buffer[166], "%05u", util_8_bit_to_16_bit_unsigned(serial_buffer[19], serial_buffer[20]));
                rpc_request_buffer[171] = '\"';

                //occupied filed
                rpc_request_buffer[186] = serial_buffer[21] + 48;
                rpc_request_buffer[187] = '\"';

                printf("json request\n");
                printf("%s\n", rpc_request_buffer);


                                struct curl_fetch_st* curl_handle = (struct curl_fetch_st*)malloc(sizeof(struct curl_fetch_st));
                curl_send_data_get_reply(curl_handle, rpc_request_buffer, rpc_reply_buffer);

                //sensordb_add(sensordb_16From8(&serial_buffer[1]), sensordb_16From8(&serial_buffer[3]));
                                //sensordb_printSerial();
                        }
                        else
                        {
                                //DEBUG MESSAGE
                //IGNORE THE DEBUG MESSAGES FOR NOW
                                //printf("%s", serial_buffer);
                        }
        }

}

这就是我得到的

代码语言:javascript
复制
root@ankit-ThinkPad-W530:/media/ankit/work/projects/parkmon/parkmon_gateway# l = 21
*** received sensor message
-*** Sending data to backend
#
data : , 00
data : K, 4B
data : , 00
data :, 08
data : �, FB
data : $, 24
data : �, 85
data : , 00
data : z, 7A
data : , 01
data : �, F1
data :  , 09
data : �, 9F
data : , 07
data : 2, 32
data : , 06
data :, 08
data : , 06
data : �, 86
data : , 01
data : 
, 0A
json request
{"src": "5A:D6:34:5E:1C:D8","time": 1468409465,"messages": [{"type": "status?","src": "00:4B:00:08:FB:24:85:00","id": 9,"amr_reading": "31233-61705-40711-12806-02054-34305","occupied": ":"}],"auth":""}
CURL Returned: 
1,1479472678,
status,00:4B:00:08:FB:24:85:00,9,1

数据为0x00 - 0x12 - 0x4B。但是,如输出所示,0x12被完全跳过。

不确定这可能是什么原因。

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2020-12-18 20:36:44

你有没有试着像Nominal提到的那样取消设置ICANON和IEXTEN并禁用一些控制字符?

我无法在我的串行端口上接收一些字节,并且禁用每个c_cc,只保留VMIN为1解决了这个问题。

代码语言:javascript
复制
//Right after open...
termios ios;
::tcgetattr(fd, &ios);
ios.c_lflag &= ~(ICANON | IEXTEN);
for(int i = 0; i < NCCS; i++)
{
    ios.c_cc[i] = i==VMIN ? 1 : 0;
}
::tcsetattr(fd, TCSANOW, &ios);

对于那些使用boost_asio的用户,将fd替换为port->native_handle()也可能解决这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40677904

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档