更新1:
短版:當串口設備發送時0x23 0x0 0x3b 0xa,我的程式可以讀取所有4個位元組(serial_getBiaststatus示例)。當串行設備將第二個位元組發送為0x3時,我的設備僅接收最后 2 個位元組(0x3b 0xa例如serial_getLedstatus)
長版 我有一個串行設備,可以回答一些命令來設定和回傳一些選項的狀態,其中一個選項是 LED。要設定選項,我必須發送:
0xFF, 0x55, 0x<ADDR>, 0x<DATA>
(設備在 SET 命令后不回傳任何內容)
要閱讀此選項,我必須發送:
0xFF, 0xAA, 0x<ADDR>, 0xFF
設備將回傳:
0x23, 0x<VALUE>, 0x3B, 0x0A
除了這些選項,設備將不斷發送以換行結束的資料。所以我需要禁用這些資料,發送一個特殊的暫存器(地址 0x9)來禁用這個log資料,否則我將無法從 LED 或其他設備選項讀取狀態。
好的,我的問題是:當我將 LED 狀態設定為 3 (0x3) 時,我無法從設備讀取狀態!我的程式只從設備中讀取 2 個位元組,而不是 4 個位元組。如果我使用0或1值,則正確回傳狀態!(4位元組)。我確信設備正在發送正確的值(在這種情況下為 4 個位元組,0x23, 0x03, 0x3B, 0x0A因為我已經在 Windows 中使用 YAT 終端程式對其進行了測驗,并且這些值是正確的.....所以這不是設備問題,而是我的程式.
到目前為止,這是我的代碼。我正在將與串行設備的連接設定為非規范模式以設定/讀取設備選項(特別是因為“設定”不回傳任何內容,所以我無法讀取()并設定超時)......在設定選項之后,我將設備連接設定為規范模式并獲取必要的資料,直到程式結束。一切正常,除非我需要在設備選項中使用“3”......如果在設備上設定了選項本身(我可以直觀地驗證 LED),但是當我嘗試讀取這個 LED 值時,只有最后 2 個位元組回傳 ( 0x3b 0xa),而不是值(從 4 開始的第二個位元組)。
int serial_set_interface_attribs(int fd, int canonical) {
pthread_mutex_lock(&m_serial);
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
pthread_mutex_unlock(&m_serial);
return -1;
}
switch (serial_speed) {
case 57600:
cfsetospeed(&tty, (speed_t) B57600);
cfsetispeed(&tty, (speed_t) B57600);
jonis_log_level(2, "Serial device speed set to 57600\n");
break;
case 115200:
cfsetospeed(&tty, (speed_t) B115200);
cfsetispeed(&tty, (speed_t) B115200);
jonis_log_level(2, "Serial device speed set to 115200\n");
break;
case 230400:
cfsetospeed(&tty, (speed_t) B230400);
cfsetispeed(&tty, (speed_t) B230400);
jonis_log_level(2, "Serial device speed set to 230400\n");
break;
case 460800:
cfsetospeed(&tty, (speed_t) B460800);
cfsetispeed(&tty, (speed_t) B460800);
jonis_log_level(2, "Serial device speed set to 460800\n");
break;
case 500000:
cfsetospeed(&tty, (speed_t) B500000);
cfsetispeed(&tty, (speed_t) B500000);
jonis_log_level(2, "Serial device speed set to 500000\n");
break;
case 576000:
cfsetospeed(&tty, (speed_t) B576000);
cfsetispeed(&tty, (speed_t) B576000);
jonis_log_level(2, "Serial device speed set to 576000\n");
break;
case 921600:
cfsetospeed(&tty, (speed_t) B921600);
cfsetispeed(&tty, (speed_t) B921600);
jonis_log_level(2, "Serial device speed set to 921600\n");
break;
default:
cfsetospeed(&tty, (speed_t) B921600);
cfsetispeed(&tty, (speed_t) B921600);
jonis_log_level(2, "Serial device speed set to 921600\n");
}
tty.c_cflag |= CLOCAL | CREAD;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
if (canonical == 1) {
jonis_log_level(1,"Interface in canonical mode\n");
tty.c_lflag |= ICANON | ISIG; /* canonical input */
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);
} else {
jonis_log_level(1,"Interface in non-canonical mode\n");
//Disable ECHO
tty.c_lflag &= ~(ICANON);
tty.c_lflag &= ~(ECHO | ECHOE);
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 10;
}
//tty.c_iflag &= ~IGNCR; /* preserve carriage return - estava comentado */
tty.c_iflag &= ~INPCK;
tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */
tty.c_oflag &= ~OPOST;
tty.c_cc[VEOL] = 0;
tty.c_cc[VEOL2] = 0;
tty.c_cc[VEOF] = 0x04;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
pthread_mutex_unlock(&m_serial);
return -1;
}
pthread_mutex_unlock(&m_serial);
return 0;
}
void *serial_threadGetSerialData(void *argv) {
AN_NOTUSED(argv);
// signal handlers:
signal(SIGINT, jonisSigintHandler);
signal(SIGTERM, jonisSigtermHandler);
if (pthread_mutex_init(&m_serial, NULL) != 0) {
printf("\n mutex init failed\n");
exit(EXIT_FAILURE);
}
if (serial_device == NULL) {
jonis_log("Can't start serial communication. Device is null.\n");
return NULL;
}
fd_serial = open(serial_device, O_RDWR | O_NOCTTY | O_SYNC);
if (fd_serial < 0) {
jonis_log("Error opening %s: %s\n", serial_device, strerror(errno));
return NULL;
}
// Configue LED and other settings
struct sdongle_version *tmp = serial_getDongleVersion();
if (tmp == NULL) {
jonis_log_level(1, "Function to get dongle FW version returned NULL!\n");
} else {
jonis_log("Serial dongle FW version: %d.%d\n",tmp->major,tmp->minor);
}
// Set LED to 3
serial_setLedstatus(3);
// Read LED status from device
serial_getLedstatus();
if (serial_bias_t == 1) {
// Enable Bias T
serial_setBiaststatus(1);
printf("Definido biast como 1!\n");
} else {
// Disabl Bias-T
serial_setBiaststatus(0);
printf("Definido biast como 0!\n");
}
(...)
serial_enableData();
/* simple canonical input */
do {
char buf[150];
//unsigned char *p;
int rdlen;
rdlen = read(fd_serial, buf, sizeof (buf) - 1);
if (rdlen > 0) {
buf[rdlen] = 0;
//printf("Read (main) %d bytes: ", rdlen);
/* first display as hex numbers then ASCII */
//for (p = buf; rdlen-- > 0; p ) {
// printf(" 0x%x", *p);
// if (*p < ' ')
// *p = '.'; /* replace any control chars */
//}
//printf("\n \"%s\"\n\n", buf);
//printf("%s", buf);
// Proccess data
//decodeRaw(buf);
} else if (rdlen < 0) {
jonis_log("Error from read: %d: %s\n", rdlen, strerror(errno));
} else { /* rdlen == 0 */
//printf("(main)Nothing read. EOF?\n");
}
/* repeat read */
} while (!MyProgram.exit);
jonis_log_level(1,"Reseting Serial Dongle options.\n");
if (serial_setLedstatus(0) != 1) {
jonis_log("Error reseting serial dongle LED status\n");
}
if (fd_serial > -1) {
close(fd_serial);
}
pthread_exit(EXIT_SUCCESS);
}
int serial_disableData(void) {
if (fd_serial < 0) {
jonis_log("Error disabling serial data: invalid serial connection.\n");
return -1;
}
char disable_data[] = {0xFF, 0x55, 0x09, 0x01};
serial_set_interface_attribs(fd_serial, 0);
jonis_log_level(1, "Canonical mode set to 0\n");
pthread_mutex_lock(&m_serial);
int wlen = 0;
wlen = write(fd_serial, disable_data, 4);
if (wlen != 4) {
jonis_log("Error from write: %d, %d\n", wlen, errno);
pthread_mutex_unlock(&m_serial);
return -1;
}
tcdrain(fd_serial); /* delay for output */
usleep(100000);
// Clear current buffer
char buf[9000] = {0};
int total_cleared = 0;
int rdlen = 0;
rdlen = read(fd_serial, buf, sizeof (buf) - 1);
total_cleared = rdlen;
jonis_log_level(1, "Clearing buffer. Current counter: %d. Returned: %d\n", total_cleared, rdlen);
while (rdlen != 0) {
rdlen = read(fd_serial, buf, sizeof (buf) - 1);
total_cleared = total_cleared rdlen;
usleep(100000);
jonis_log_level(1, "Clearing buffer. Current counter: %d. Returned: %d\n", total_cleared, rdlen);
}
jonis_log_level(1, "Finished sending 'disable_log' command do serial device! Data length in buffer: '%d'\n", total_cleared);
pthread_mutex_unlock(&m_serial);
return 1;
}
int serial_enableData(void) {
if (fd_serial < 0) {
jonis_log("Error enabling serial data: invalid serial connection.\n");
return -1;
}
serial_set_interface_attribs(fd_serial, 1);
pthread_mutex_lock(&m_serial);
char disable_data[] = {0xFF, 0x55, 0x09, 0x00};
int wlen = 0;
wlen = write(fd_serial, disable_data, 4);
if (wlen != 4) {
jonis_log("Error from write: %d, %d\n", wlen, errno);
pthread_mutex_unlock(&m_serial);
return -1;
}
tcdrain(fd_serial); /* delay for output */
jonis_log_level(1, "Finished sending 'enable_log' command do serial device!\n");
pthread_mutex_unlock(&m_serial);
return 1;
}
struct sdongle_version *serial_getDongleVersion(void) {
if (fd_serial < 0) {
jonis_log("Error getting serial data: invalid serial connection.\n");
return NULL;
}
if (serial_disableData() < 0) {
jonis_log("Could not disable data\n");
return NULL;
}
char disable_data[] = {0xFF, 0xAA, 0x0F, 0xFF};
int wlen = 0;
wlen = write(fd_serial, disable_data, 4);
if (wlen != 4) {
jonis_log("Error from write: %d, %d\n", wlen, errno);
return NULL;
}
tcdrain(fd_serial); /* delay for output */
usleep(100000);
char buf[150];
char *p;
int rdlen;
//rdlen = read(fd_serial, buf, sizeof (buf) - 1);
//if (rdlen > 0) {
while ((rdlen = read(fd_serial, buf, sizeof (buf) - 1)) < 4 || !Modes.exit) {
buf[rdlen] = 0;
//printf("(Version) Read '%d' bytes: ", rdlen);
if (rdlen == 4 && buf[0] == 0x23 && buf[2] == 0x3b && buf[3] == 0xa) {
jonis_log_level(1, "Version string found!\n");
int minor = buf[1] << 2 >> 2;
int major = buf[1] >> 6;
jonis_log_level(1, "Minor version: %d, Major version: %d\n", minor, major);
struct sdongle_version *ver = malloc(sizeof (struct sdongle_version));
ver->major = major;
ver->minor = minor;
return ver;
}
/* first display as hex numbers then ASCII */
for (p = buf; rdlen-- > 0; p ) {
//printf(" 0x%x", *p);
}
//printf("\n (version)Value: \"%s\"\n\n", buf);
}
return NULL;
}
int serial_getLedstatus(void) {
if (fd_serial < 0) {
jonis_log("Error getting serial data: invalid serial connection.\n");
return -1;
}
if (serial_disableData() < 0) {
jonis_log("Could not disable data\n");
return -1;
}
char led_status_data[] = {0xFF, 0xAA, 0x8, 0xFF};
int wlen = 0;
wlen = write(fd_serial, led_status_data, 4);
if (wlen != 4) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd_serial); /* delay for output */
sleep(1);
char buf[150] = {0};
char *p = NULL;
int rdlen = 0;
int tries = 0;
while (((rdlen = read(fd_serial, buf, sizeof (buf) - 1)) < 4 && !Modes.exit) && tries <= 5) {
jonis_log_level(1,"(led) Read '%d' bytes: \n", rdlen);
tries ;
// Force rwrite command
wlen = write(fd_serial, led_status_data, 4);
tcdrain(fd_serial);
sleep(1);
buf[rdlen] = 0;
/* first display as hex numbers then ASCII */
for (p = buf; rdlen-- > 0; p ) {
if (debug_level >= 1) {
printf(" 0x%x", *p);
}
}
if (debug_level >= 1) {
printf("\n");
jonis_log_level(1," (led)Value: \"%s\"\n\n", buf);
}
}
if (rdlen > 0) {
jonis_log_level(1,"Debug -> Received chars in LED Status\n");
jonis_log_level(1,"(led) Read '%d' bytes: ", rdlen);
buf[rdlen] = 0;
/* first display as hex numbers then ASCII */
for (p = buf; rdlen-- > 0; p ) {
if (debug_level >= 1) {
printf(" 0x%x", *p);
}
}
if (debug_level >= 1) {
printf("\n");
jonis_log_level(1," (led)Value: \"%s\"\n\n", buf);
}
}
jonis_log_level(1,"LED Status (function): %d\n",buf[1]);
return buf[1];
}
int serial_setLedstatus(char led_status) {
if (fd_serial < 0) {
jonis_log("Error getting serial data: invalid serial connection.\n");
return -1;
}
if (serial_disableData() < 0) {
jonis_log("Could not disable data\n");
return -1;
}
char led_data[] = {0xFF, 0x55, 0x08, led_status};
int wlen = 0;
wlen = write(fd_serial, led_data, 4);
if (wlen != 4) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd_serial); /* delay for output */
//serial_getLedstatus();
return 1;
}
int serial_getBiaststatus(void) {
if (fd_serial < 0) {
jonis_log("Error getting serial data: invalid serial connection.\n");
return -1;
}
if (serial_disableData() < 0) {
jonis_log("Could not disable data\n");
return -1;
}
char bias_status_data[] = {0xFF, 0xAA, 0x07, 0xFF};
int wlen = 0;
wlen = write(fd_serial, bias_status_data, 4);
if (wlen != 4) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd_serial); /* delay for output */
usleep(100000);
char buf[150];
char *p;
int rdlen;
rdlen = read(fd_serial, buf, sizeof (buf) - 1);
if (rdlen > 0) {
buf[rdlen] = 0;
printf("(biast) Read '%d' bytes: ", rdlen);
/* first display as hex numbers then ASCII */
for (p = buf; rdlen-- > 0; p ) {
printf(" 0x%x", *p);
}
printf("\n (biast)Value: \"%s\"\n\n", buf);
} else if (rdlen < 0) {
jonis_log("Error from read: %d: %s\n", rdlen, strerror(errno));
} else { /* rdlen == 0 */
//printf("(led)Nothing read. EOF?\n");
}
jonis_log_level(1,"BIAS-T Status (function): %d\n",buf[1]);
return buf[1];
}
int serial_setBiaststatus(char biast_status) {
if (fd_serial < 0) {
jonis_log("Error getting serial data: invalid serial connection.\n");
return -1;
}
if (serial_disableData() < 0) {
jonis_log("Could not disable data\n");
return -1;
}
char biast_data[] = {0xFF, 0x55, 0x07, biast_status};
int wlen = 0;
wlen = write(fd_serial, biast_data, 4);
if (wlen != 4) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd_serial); /* delay for output */
usleep(100000);
if (serial_getBiaststatus() == biast_status) {
return 1;
} else {
return 0;
}
}
這是回傳的文本(注意僅從 LED 狀態接收到 2 個位元組):
[2022-04-28 09:22:00] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:00] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:00] [serial_disableData] Clearing buffer. Current counter: 1. Returned: 1
[2022-04-28 09:22:01] [serial_disableData] Clearing buffer. Current counter: 1. Returned: 0
[2022-04-28 09:22:01] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '1'
[2022-04-28 09:22:01] [serial_getDongleVersion] Version string found!
[2022-04-28 09:22:01] [serial_getDongleVersion] Minor version: 34, Major version: 0
[2022-04-28 09:22:01] Serial dongle FW version: 0.34
[2022-04-28 09:22:01] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:01] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:02] [serial_disableData] Clearing buffer. Current counter: 0. Returned: 0
[2022-04-28 09:22:02] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '0'
[2022-04-28 09:22:02] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:02] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:03] [serial_disableData] Clearing buffer. Current counter: 0. Returned: 0
[2022-04-28 09:22:03] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '0'
[2022-04-28 09:22:04] [serial_getLedstatus] (led) Read '2' bytes:
0x3b 0xa
[2022-04-28 09:22:05] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:05] [serial_getLedstatus] (led) Read '2' bytes:
0x3b 0xa
[2022-04-28 09:22:06] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:06] [serial_getLedstatus] (led) Read '2' bytes:
0x3b 0xa
[2022-04-28 09:22:07] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:07] [serial_getLedstatus] (led) Read '2' bytes:
0x3b 0xa
[2022-04-28 09:22:08] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:08] [serial_getLedstatus] (led) Read '2' bytes:
0x3b 0xa
[2022-04-28 09:22:09] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:09] [serial_getLedstatus] (led) Read '2' bytes:
0x3b 0xa
[2022-04-28 09:22:10] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:10] [serial_getLedstatus] Debug -> Received chars in LED Status
[2022-04-28 09:22:10] [serial_getLedstatus] (led) Read '2' bytes: 0x3b 0xa
[2022-04-28 09:22:10] [serial_getLedstatus] (led)Value: ";
"
[2022-04-28 09:22:10] [serial_getLedstatus] LED Status (function): 10
[2022-04-28 09:22:10] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:10] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:11] [serial_disableData] Clearing buffer. Current counter: 0. Returned: 0
[2022-04-28 09:22:11] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '0'
[2022-04-28 09:22:12] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:12] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:13] [serial_disableData] Clearing buffer. Current counter: 0. Returned: 0
[2022-04-28 09:22:13] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '0'
[2022-04-28 09:22:13] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:13] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:14] [serial_disableData] Clearing buffer. Current counter: 0. Returned: 0
[2022-04-28 09:22:14] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '0'
[2022-04-28 09:22:14] [serial_set_interface_attribs] Interface in non-canonical mode
[2022-04-28 09:22:14] [serial_disableData] Canonical mode set to 0
[2022-04-28 09:22:15] [serial_disableData] Clearing buffer. Current counter: 0. Returned: 0
[2022-04-28 09:22:15] [serial_disableData] Finished sending 'disable_log' command do serial device! Data length in buffer: '0'
(biast) Read '4' bytes: 0x23 0x0 0x3b 0xa
(biast)Value: "#"
[2022-04-28 09:22:15] [serial_getBiaststatus] BIAS-T Status (function): 0
[2022-04-28 09:22:15] [serial_set_interface_attribs] Interface in canonical mode
[2022-04-28 09:22:15] [serial_enableData] Finished sending 'enable_log' command do serial device!
再次:設備回傳正確的位元組數(4),即使選項 os 的值為 3,但我的程式無法準備好所有這些位元組,只有最后 2 個。我在這里缺少什么?謝!
uj5u.com熱心網友回復:
好的,我的問題是:當我將 LED 狀態設定為 3 (0x3) 時,我無法從設備讀取狀態!
...
我確信設備正在發送正確的值(4個位元組,在這種情況下,0x23, 0x03, 0x3B, 0x0A...
0x03也是名為 ETX 的 ASCII 控制代碼。
termios 特殊字符VINTR的默認值為 ,0x03也稱為 ETX 和 Ctrl-C。
當 c_lflag 的 termios ISIG 屬性設定時,接收VINTR字符將導致行程獲得 SIGINT 信號,并且從輸入緩沖區中洗掉該字符。
if (canonical == 1) {
...
tty.c_lflag |= ICANON | ISIG; /* canonical input */
...
} else {
...
tty.c_lflag &= ~(ICANON);
tty.c_lflag &= ~(ECHO | ECHOE);
...
}
您的程式將 ISIG 屬性設定為“規范”模式,否則保持 c_lflag 中的該屬性不變。
顯然VINTR仍然有它的默認值0x03。
最終效果是始終啟用 ISIG 屬性,因此接收 0x03將始終不可讀。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/467409.html
