Faz*_*ton 6 c serial-port termios
我试图在Linux中编写一个C程序,通过串口从微控制器发送和接收数据.作为测试,我已将微控制器配置为立即回显所有发送的字符.我已经验证这可以在minicom中工作,也可以使用"cat"和"echo"来发送和接收数据.
但是,当我尝试在C程序中执行相同操作时,我的读取调用会永久阻塞.我将串口设置为非规范模式,MIN为'1',TIME为'0'.我的minicom测试证明微控制器在键入时返回字符,所以我希望在写调用发送字符后返回读取.我将我的代码与几个在线示例进行了比较,但我没有发现任何我遗漏的内容.我已尝试过以下代码的几种排列,但没有运气.有人能发现问题吗?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#define UART_SPEED B115200
char buf[512];
void init_serial (int fd)
{
struct termios termios;
int res;
res = tcgetattr (fd, &termios);
if (res < 0) {
fprintf (stderr, "Termios get error: %s\n", strerror (errno));
exit (-1);
}
cfsetispeed (&termios, UART_SPEED);
cfsetospeed (&termios, UART_SPEED);
termios.c_iflag &= ~(IGNPAR | IXON | IXOFF);
termios.c_iflag |= IGNPAR;
termios.c_cflag &= ~(CSIZE | PARENB | CSTOPB | CREAD | CLOCAL);
termios.c_cflag |= CS8;
termios.c_cflag |= CREAD;
termios.c_cflag |= CLOCAL;
termios.c_lflag &= ~(ICANON | ECHO);
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
res = tcsetattr (fd, TCSANOW, &termios);
if (res < 0) {
fprintf (stderr, "Termios set error: %s\n", strerror (errno));
exit (-1);
}
}
int main (int argc, char **argv)
{
int fd;
int res;
int i;
if (argc < 2) {
fprintf (stderr, "Please enter device name\n");
return -1;
}
fd = open (argv[1], O_RDWR | O_NOCTTY);
if (fd < 0) {
fprintf (stderr, "Cannot open %s: %s\n", argv[1], strerror(errno));
return -1;
}
init_serial (fd);
res = write (fd, "P=20\r\n", 6);
if (res < 0) {
fprintf (stderr, "Write error: %s\n", strerror(errno));
return -1;
}
tcdrain (fd);
res = read (fd, buf, 512);
printf ("%d\n", res);
if (res < 0) {
fprintf (stderr, "Read error: %s\n", strerror(errno));
return -1;
}
for (i=0; i<res; i++) {
printf ("%c", buf[i]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您可能要插入一些延迟,或者循环等待输入。
设置比特率后,某些类型的UART硬件以新的速度占用一个或两个字符以与新的速度同步。前几个字符有可能在写入时丢失。
写完六个字符后,立即以0.1秒的超时发出读取。并非所有来自的字符write()都已在之前完成传输read(),更不用说任何时候远程设备都可以响应了。
例如,一种解决方案是:
init_serial (fd);
usleep (100000); // delay 0.1 seconds (Linux) so term parameters have time to change
res = write (fd, "P=20\r\n", 6);
if (res < 0) {
fprintf (stderr, "Write error: %s\n", strerror(errno));
return -1;
}
tcdrain (fd);
usleep (250000); // delay 0.25 for device to respond and return data
res = read (fd, buf, 512);
Run Code Online (Sandbox Code Playgroud)
另一种方法是继续读取,直到到达足够数量的字符或经过一段合理的时间。