我正在尝试编写一个程序,用于 Teltonika 的 TRB246 上的串行通信(BusyBox v1.34.1)。
传入的数据是原始数据,以十六进制字节为单位,每秒传入一次。
三种解决方案:
microcom
(swift 选项,应该足够了)microcom
microcom
:失败脚本:
#!/bin/sh
ask_dataA='\xFF\x12\xB0\x80\x28\x00\x01\x01\x00\xEA\x00\x00\x00\x00\x77\xA8\x04\xFF'
echo "Asking data A..."
echo -en $ask_dataA > /dev/rs485 # send query
nice -20 microcom -t 1100 -s 9600 /dev/rs485 > tmpsf # listen
if [ -s tmpsf ]; then # checks if file is empty
hexdump -ve '/1 "%02x"' -n 36 tmpsf # convert to ascii
echo ""
else
echo "nothing"
fi
输出: 在此输入图片描述
有时 if 会按预期给出十六进制答案。
我正在使用 Docklight 监视通信,每条消息都正确且准时地传输。只是 TRB246 没有捕捉到答案。
我想我来得太晚了
microcom
,因为答案在回声后几十毫秒出现。
read()
无法正常工作),代码:#include <fcntl.h>
#include <termios.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#define RS485_DEV "/dev/ttyS1"
#define RS485_BAUDRATE B9600
#define RS485_TIMEOUT 0 // in tenths of sec; or use poll() https://man7.org/linux/man-pages/man2/poll.2.html
#define RS485_MINBRD 16 // min bytes to read see http://manpagesfr.free.fr/man/man3/termios.3.html
#define RS485_IBUFFSIZE 32
int main()
{
printf("Hello guys!\n");
uint8_t ibuff[RS485_IBUFFSIZE];
int fd = open(RS485_DEV, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) { printf("Failed to open rs485 port: %s\n", strerror(errno)); exit(1); }
struct termios term_conf;
struct termios new_term_conf;
if (tcgetattr(fd, &term_conf) == -1) { printf("Failed to get term config: %s\n", strerror(errno)); } // get current settings
printf("Former terminal configuration:\n");
printf("term_conf:\n\tc_iflag = %u\n\tc_oflag = %u\n\tc_cflag = %u\n\tc_lflag = %u\n\n",
term_conf.c_iflag, term_conf.c_oflag, term_conf.c_cflag, term_conf.c_lflag);
for (int i = 0; i < NCCS; i++) { printf("\tc_cc[%d] = %u\n", i, term_conf.c_cc[i]); }
printf("\n");
// Configure terminal settings
// cfmakeraw(&term_conf);
// Control flags
// Input flags
// convert break to null byte, no CR to NL translation,
// no NL to CR translation, don't mark parity errors or breaks
// no input parity check, don't strip high bit off,
// no XON/XOFF software flow control
term_conf.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); //cfmakeraw adds IGNCR and removes INPCK
// Output flags
// no CR to NL translation, no NL to CR-NL translation,
// no NL to CR translation, no column 0 CR suppression,
// no Ctrl-D suppression, no fill characters, no case mapping,
// no local output processing
term_conf.c_oflag = 0;
// Local flags
// echo off, echo newline off, canonical mode off,
// extended input processing off, signal chars off
term_conf.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
// Chars processing
term_conf.c_cflag &= ~(CSIZE | PARENB); //clear current char size mask, no parity checking
term_conf.c_cflag |= CS8; //force 8 bit input
// Others
printf("term_conf.c_cc[VTIME] = %d, RS485_TIMEOUT = %d, VTIME = %d\n\n", term_conf.c_cc[VTIME], RS485_TIMEOUT, VTIME);
printf("term_conf.c_cc[VMIN] = %d, RS485_MINBRD = %d, VMIN = %d\n\n", term_conf.c_cc[VMIN], RS485_MINBRD, VMIN);
term_conf.c_cc[VTIME] = RS485_TIMEOUT;
printf("term_conf.c_cc[VTIME] = %d, RS485_TIMEOUT = %d, VTIME = %d\n\n", term_conf.c_cc[VTIME], RS485_TIMEOUT, VTIME);
term_conf.c_cc[VMIN] = RS485_MINBRD;
printf("term_conf.c_cc[VMIN] = %d, RS485_MINBRD = %d, VMIN = %d\n\n", term_conf.c_cc[VMIN], RS485_MINBRD, VMIN);
if (cfsetispeed(&term_conf, RS485_BAUDRATE) == -1) { printf("Failed to set term ispeed: %s\n", strerror(errno)); }
if (cfsetospeed(&term_conf, RS485_BAUDRATE) == -1) { printf("Failed to set term ospeed: %s\n", strerror(errno)); }
tcsetattr(fd, TCSANOW, &term_conf); // apply new conf now
tcgetattr(fd, &new_term_conf); // get conf again
if (memcmp(&term_conf, &new_term_conf, sizeof(term_conf)) != 0) { // compare to check if changes applied
printf("Terminal configuration failed\n");
printf("term_conf:\n\tc_iflag = %u\n\tc_oflag = %u\n\tc_cflag = %u\n\tc_lflag = %u\n\n",\
term_conf.c_iflag, term_conf.c_oflag, term_conf.c_cflag, term_conf.c_lflag);
for (int i = 0; i < NCCS; i++) { printf("\tc_cc[%d] = %u\n", i, term_conf.c_cc[i]); }
printf("\n");
printf("new_term_conf:\n\tc_iflag = %u\n\tc_oflag = %u\n\tc_cflag = %u\n\tc_lflag = %u\n\n",\
new_term_conf.c_iflag, new_term_conf.c_oflag, new_term_conf.c_cflag, new_term_conf.c_lflag);
for (int i = 0; i < NCCS; i++) { printf("\tc_cc[%d] = %u\n", i, new_term_conf.c_cc[i]); }
printf("\n");
printf("new_term_conf.c_cc[VTIME] = %d, RS485_TIMEOUT = %d, VTIME = %d\n\n", new_term_conf.c_cc[VTIME], RS485_TIMEOUT, VTIME);
printf("new_term_conf.c_cc[VMIN] = %d, RS485_MINBRD = %d, VMIN = %d\n\n", new_term_conf.c_cc[VMIN], RS485_MINBRD, VMIN);
}
// if (ioctl(fd, TIOCEXCL, NULL) == -1) { printf("Failed to get exclusivity: %s", strerror(errno)); }
// if (tcflush(fd, TCIOFLUSH) == -1) { printf("Failed to flush: %s", strerror(errno)); }
memset(ibuff, 0, RS485_IBUFFSIZE);
int i = 20000;
while (i) {
i--;
if (read(fd, ibuff, 1) != -1) { printf("%x\n", ibuff[0]); }
usleep(200);
}
close(fd);
// printf("EAGAIN = %d\n", EAGAIN);
return 0;
}
输出:
Hello guys!
Former terminal configuration:
term_conf:
c_iflag = 0
c_oflag = 0
c_cflag = 3261
c_lflag = 0
c_cc[0] = 3
c_cc[1] = 28
c_cc[2] = 127
c_cc[3] = 21
c_cc[4] = 16
c_cc[5] = 0
c_cc[6] = 0
c_cc[7] = 0
c_cc[8] = 17
c_cc[9] = 19
c_cc[10] = 26
c_cc[11] = 0
c_cc[12] = 18
c_cc[13] = 15
c_cc[14] = 23
c_cc[15] = 22
c_cc[16] = 4
c_cc[17] = 0
c_cc[18] = 0
c_cc[19] = 0
c_cc[20] = 0
c_cc[21] = 0
c_cc[22] = 0
c_cc[23] = 0
c_cc[24] = 64
c_cc[25] = 235
c_cc[26] = 119
c_cc[27] = 0
c_cc[28] = 0
c_cc[29] = 0
c_cc[30] = 0
c_cc[31] = 100
term_conf.c_cc[VTIME] = 0, RS485_TIMEOUT = 0, VTIME = 5
term_conf.c_cc[VMIN] = 16, RS485_MINBRD = 16, VMIN = 4
term_conf.c_cc[VTIME] = 0, RS485_TIMEOUT = 0, VTIME = 5
term_conf.c_cc[VMIN] = 16, RS485_MINBRD = 16, VMIN = 4
Terminal configuration failed
term_conf:
c_iflag = 0
c_oflag = 0
c_cflag = 3261
c_lflag = 0
c_cc[0] = 3
c_cc[1] = 28
c_cc[2] = 127
c_cc[3] = 21
c_cc[4] = 16
c_cc[5] = 0
c_cc[6] = 0
c_cc[7] = 0
c_cc[8] = 17
c_cc[9] = 19
c_cc[10] = 26
c_cc[11] = 0
c_cc[12] = 18
c_cc[13] = 15
c_cc[14] = 23
c_cc[15] = 22
c_cc[16] = 4
c_cc[17] = 0
c_cc[18] = 0
c_cc[19] = 0
c_cc[20] = 0
c_cc[21] = 0
c_cc[22] = 0
c_cc[23] = 0
c_cc[24] = 64
c_cc[25] = 235
c_cc[26] = 119
c_cc[27] = 0
c_cc[28] = 0
c_cc[29] = 0
c_cc[30] = 0
c_cc[31] = 100
new_term_conf:
c_iflag = 0
c_oflag = 0
c_cflag = 3261
c_lflag = 0
c_cc[0] = 3
c_cc[1] = 28
c_cc[2] = 127
c_cc[3] = 21
c_cc[4] = 16
c_cc[5] = 0
c_cc[6] = 0
c_cc[7] = 0
c_cc[8] = 17
c_cc[9] = 19
c_cc[10] = 26
c_cc[11] = 0
c_cc[12] = 18
c_cc[13] = 15
c_cc[14] = 23
c_cc[15] = 22
c_cc[16] = 4
c_cc[17] = 0
c_cc[18] = 0
c_cc[19] = 0
c_cc[20] = 0
c_cc[21] = 0
c_cc[22] = 0
c_cc[23] = 161
c_cc[24] = 7
c_cc[25] = 64
c_cc[26] = 0
c_cc[27] = 168
c_cc[28] = 152
c_cc[29] = 232
c_cc[30] = 119
c_cc[31] = 104
new_term_conf.c_cc[VTIME] = 0, RS485_TIMEOUT = 0, VTIME = 5
new_term_conf.c_cc[VMIN] = 16, RS485_MINBRD = 16, VMIN = 4
4
fe
4
fe
4
fe
4
fe
4
fe
4
fe
4 和 fe 是我的消息的标准最终字节。即使我更改了函数调用中要读取的 nbytes,我也永远不会得到其他字节。 注意:在 10k 次读取中,它仅返回几个字节。 当没有返回任何内容时,read() 失败并返回 -1,并带有
errno = 11 = EAGAIN
,并且 strerror(errno)
给出 “资源暂时不可用”。
我尝试设置 VMIN = 0 和 VTIME = 12(1.2 秒),但是
read()
根本不等待,就像 VTIME = 0 一样。为什么?
microcom
这就是我现在正在寻找的并行解决方案,试图在 BusyBox 中创建一个新程序,但这并不合适......
如果您能就如何使脚本工作或如何解决
read()
问题提供建议,我非常感谢!
最后,删除 O_NDELAY 使我能够读取数据,但顺序错误。
设置超时没有帮助(VTIME = 10,VMIN = 0)。而且我的数据顺序错误。
在read()中设置要读取的确切字节数,并让VTIME = 0,VMIN =要读取的确切字节数,彻底解决了问题!
谢谢您的帮助!