我写了几个bash脚本文件,通过两个串口进行通信。一个脚本可以被认为是接收器而另一个可以被认为是发送器。接收脚本逐行读取和显示数据,直到它读取字符序列<break>
。然后它停止收听,并将one
或two
的字符序列发送回发送器。因此脚本是:
#!/bin/bash
# Read and reply bash script.
exec 3<> /dev/ttyS4
while true; do
#cat -v /dev/ttyS4 | while read -r input; do
while read -r -u 3 input; do
if [ "$input" = "<break>" ]
then
echo "break command received."
break
else
echo -e "${input}"
fi
done
echo "Sending selection"
if [ "$selection" = "one" ]
then
selection="two"
else
selection="one"
fi
echo "$selection" >&3
done
发送器脚本传输一些字符数据,然后从上面的接收器脚本等待one
或two
的回复:
exec 4<> /dev/ttyS0
selection="one"
while true; do
echo "************************************" > /dev/ttyS0
echo " Selection: ${selection}" > /dev/ttyS0
echo "************************************" > /dev/ttyS0
echo "<break>" > /dev/ttyS0
read -r -t 3 -u 4 input
if [ -z "$input" ]
then
echo "Response from remote timed out."
elif [ "$input" = "one" ]
then
selection=$input
elif [ "$input" = "two" ]
then
selection=$input
colour=$RED
else
echo "Unknown selection: $input"
fi
sleep 1
done
上述两个脚本工作正常,接收者脚本正确识别<break>
字符序列。
我希望用一个小的C程序替换'发送器'脚本但是我发现当我发送字符序列<break>
时,接收器脚本这次 NOT 识别是'传输结束',是简单的回声<break>
到标准输出,而不是break command received
。我尝试过几个例子,比如添加转义字符,但Bash echo
的工作方式和我在C代码中发送数据的方式显然有所不同:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
int main(int argc, char *argv[]) {
int selected_tool = DEFAULT_TOOL_SELECTION;
FILE *ser2_fd_write, *ser2_fdrw;
struct termios tios, tios_w; // ser 2 termios structure
int ser2_fd, ser2_fdw;
char read_buffer[BUFFER_SIZE];
struct timespec tdelay;
bzero(&tdelay, sizeof(tdelay));
tdelay.tv_sec = 1;
tdelay.tv_nsec = 5000;
if ((ser2_fd = open("/dev/ttyS0", O_RDWR)) == -1){
printf("Unable to open ttyS0 as read-write only.\n");
return EXIT_FAILURE;
}
bzero(&tios, sizeof(tios));
cfsetispeed(&tios, B38400);
cfsetospeed(&tios, B38400);
tios.c_cflag = B38400 | CS8 | CLOCAL | CREAD | CRTSCTS;
tios.c_iflag = IGNPAR;
tios.c_oflag = 0;
tios.c_lflag = ICANON; //0
tios.c_cc[VTIME] = 0;
tios.c_cc[VMIN] = 10;
tcflush(ser2_fd, TCIFLUSH);
if (tcsetattr(ser2_fd, TCSANOW, &tios) == -1){
printf("Could not set ser 2 attributes.\n");
return -1;
}
if ((ser2_fdrw = fdopen(ser2_fd, "awr")) == NULL){
printf("Unable to open file descriptor.\n");
return EXIT_FAILURE;
}
while(1){
push_to_ser2(ser2_fdrw, selected_tool);
/*
* This is where sending <break> differs from echo
*/
//fputs("break", ser2_fdrw);
fprintf(ser2_fdrw, "break\r\n");
//fprintf(ser2_fdrw, "\r\n");
//write(ser2_fd,"break\r\n", 9);
fflush(ser2_fdrw);
int c = 0;
nanosleep(&tdelay, NULL);
tcflush(ser2_fd, TCIOFLUSH);
tcdrain(ser2_fd);
fcntl(ser2_fd, F_SETFL, 0);
if ( (c = read(ser2_fd, read_buffer, BUFFER_SIZE)) > 0){
read_buffer[c] = 0;
if (strcmp(read_buffer, "one\r\n") == 0){
selected_tool = 1;
} else if (strcmp(read_buffer, "two\r\n") == 0){
selected_tool = 2;
}
}else{
}
}
return EXIT_SUCCESS;
}
/*
* Convenience function to push data to ser 2
* *c_data pointer to the card data
* *t_data pointer to the tool data
*/
void push_to_ser2(FILE * fd, int tool){
fprintf(fd, "**********************************************************\n");
fprintf(fd, "* *\n");
fprintf(fd, "* Tool %d Data *\n", tool);
fprintf(fd, "* *\n");
fprintf(fd, "**********************************************************\n");
fprintf(fd,"\r\n");
fflush(fd);
}
我也尝试过对termios
结构进行各种更改,但它没有任何区别。有什么想法吗?
答案 0 :(得分:1)
您的代码有几个问题需要纠正:
bzero(&tios, sizeof(tios))
代码应该调用 tcgetattr()来正确初始化结构。对于规范输入而言,这可能是一个严重的问题,因为现有代码将所有控制代码规范归零,而不是具有适当的定义。 read(ser2_fd,...)
默默地忽略错误。 答案 1 :(得分:0)
看起来好像bash脚本正在发送包含尖括号的文字字符串<break>
。同时,C程序只发送break
。将尖括号添加到C程序中的文字。 (这些括号对echo
或fprintf
没有任何特殊含义,因此它们只是按原样发送。)