我有一个使用USB串行适配器连接到我的PC的开发板。从电路板上,我发送8字节的IEEE mac地址,但由于某种原因,我没有收到某些字节。
在我的电脑上,我有一个监控串口的守护进程,简单打印终端上收到的字符。
由于某种原因,未接收到值0x12(DC2(设备控制2))。我知道它是由我的开发板发送的,因为我正在嗅探串行输出,我可以看到0x12被发送。
我对linux没有足够的经验,但感觉它可能是我在C代码中初始化串口的方式(假设被跳过的字符是控制字符)。
我也尝试发送0x11(DC1),我能够成功接收。
我的代码是
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;
}
这是我的主要常规
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);
}
}
}
这就是我得到的
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完全被跳过。
不确定是什么原因造成的。
谢谢!
答案 0 :(得分:0)
您是否尝试过取消名义动物提到的ICANON和IEXTEN并禁用某些控制字符?
我无法在串行端口上接收到一些字节,并且仅将VMIN保持为1即可禁用每个c_cc来解决问题。
//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()也可以解决该问题。