简体   繁体   English

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

[英]Linux Serial Port - Unable To Receive Certain Control Characters

I have a development board that is connected to my PC using a USB-Serial adapter.我有一个使用 USB 串行适配器连接到我的 PC 的开发板。 From the board, I am sending 8 bytes IEEE mac address, but for some reason I am not receiving certain bytes.从板上,我正在发送 8 个字节的 IEEE mac 地址,但由于某种原因,我没有收到某些字节。

On my PC, I have a daemon running that monitors the serial port and simple prints the received characters on the terminal.在我的 PC 上,我有一个守护进程在运行,它监视串行端口并在终端上简单地打印接收到的字符。

For some reason,value 0x12 (DC2 (device control 2)) is not being received.由于某种原因,未收到值 0x12(DC2(设备控制 2))。 I know it is being sent by my development board as I am sniffing the serial output from that and I can see 0x12 being sent.我知道它是由我的开发板发送的,因为我正在嗅探它的串行输出,我可以看到 0x12 正在发送。

I am not experienced enough with linux, but it feels like it could be something in the way I have initialized the serial port in my C code (given that the character being skipped is a control character).我对 linux 的经验不足,但感觉这可能是我在 C 代码中初始化串行端口的方式(假设被跳过的字符是控制字符)。

I also tried sending 0x11 (DC1) which I am able to receive successfully.我还尝试发送我能够成功接收的 0x11 (DC1)。

my code is我的代码是

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

This is my in my main routine这是我的主要例行程序

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

}

And this is what i get这就是我得到的

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

The data is 0x00 - 0x12 - 0x4B.数据为 0x00 - 0x12 - 0x4B。 However as seen in the output, 0x12 gets completely skipped.然而,如输出所示,0x12 被完全跳过。

Not sure what could be the reason for this.不知道这可能是什么原因。

Thanks!谢谢!

Have you tried to unset the ICANON and IEXTEN as mentioned by Nominal Animal and disable some control characters?您是否尝试取消 Nominal Animal 提到的 ICANON 和 IEXTEN 并禁用一些控制字符?

I has unable to receive some bytes on my serial port and disabling every c_cc only keeping VMIN as 1 solved the problem.我无法在我的串行端口上接收一些字节并禁用每个 c_cc 仅将 VMIN 保持为 1 解决了问题。

//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);

for those using boost_asio, replacing fd for port->native_handle() may solve the problem as well.对于使用 boost_asio 的用户,将 fd 替换为 port->native_handle() 也可以解决问题。

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

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