我正在尝试从文本文件中读取一些数据并将其写入ttyUSB *套接字ID。 我正在使用Hi3520d Dvr。我把它的RS485端口连接到" RS485到RS232转换器"。该转换器通过USB端口连接到PC。
文本文件正在被正确读取到缓冲区,但在写入文本的最后几行时没有传输。对于大小超过4.5kb且没有usleep()函数的文件,会发生这种情况。
我在linux终端上使用minicom来显示读写文本。 提前感谢您对此进行调查。
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define Bdrate B9600
int Intserial(char *dev, int Baudrate)
{
//printf("Insterial func\n");
int sid;
int iDebug = -1;
struct termios serial_struct;
sid = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (sid > 0)
{
memset(&serial_struct, 0, sizeof(serial_struct)); /* clear the new struct */
serial_struct.c_cflag = Baudrate | CS8 | CLOCAL | CREAD;
serial_struct.c_iflag = IGNPAR;
serial_struct.c_oflag = 0;
serial_struct.c_lflag = 0;
serial_struct.c_cc[VMIN] = 0; /* block untill n bytes are received */
serial_struct.c_cc[VTIME] = 0; /* block untill a timer expires (n * 100 mSec.) */
iDebug = tcsetattr(sid, TCSANOW, &serial_struct);
if (iDebug < 0)
{
printf("Err 0\n"); //Unable to set serial port parameters
return (0);
}
}
else
{
printf("Err 1\n"); //Serial port not open
return (0);
}
//printf("sid is %d \n",sid);
return (sid);
}
int main()
{
int sid1 = -1, size = 0, i = 0, x, w;
size_t ln;
FILE *fd;
char buf[2233];
fd = fopen("h.txt", "r");
if (fd)
{
sid1 = Intserial("/dev/ttyAMA1", Bdrate); //RS485 port of Hi3520d
if (sid1 > -1)
{
system("himm 0x200F004C 0"); // commands transmitting and recieving
system("himm 0x201A0400 1");
system("himm 0x201a0004 1");
while (!feof(fd))
{
memset(buf, 0, sizeof(buf));
fread(buf, sizeof(buf), 1, fd);
printf("%s", buf);
write(sid1, buf, sizeof(buf));
usleep(5);
}
getchar();
}
else
printf("com port cant open\r\n ");
fclose(fd);
close(sid1);
}
else
printf("File cant open\r\n");
printf("task completed............\r\n");
}
答案 0 :(得分:1)
您必须观察fread函数读取的字节数的fread返回值。实际的读取大小可能不等于请求的字节数,你也必须通过fread读取的字节数(作为缓冲区中的有效字节)来写入函数作为要写入的字节数。
代码应该是这样的
memset(buf,0,sizeof(buf));
size_t bytesRead = fread(buf,sizeof(buf),1,fd);
if(bytesRead > 0)
write(sid1,buf, bytesRead);
另外正如LP所说,fread不会终止具有终止字符的缓冲区,因此将fread填充的缓冲区传递给printf(“%s”)将是未定义的行为
答案 1 :(得分:0)
您的代码存在许多问题,但“文本未传输”的显着原因可能是未能检查
的返回值write(sid1, buf, sizeof(buf));
由于串行终端是在非阻塞模式下打开的,因此在实际传输数据之前,每个 write()将立即返回。
由于串行终端配置为相当慢的9600波特,因此数据可以在线路规则缓冲区和其他中间缓冲区中排队。
行规则缓冲区通常为4096字节长 假设 fread()操作总是成功的(您似乎已经验证过),那么2233字节的 write()的第二次迭代可能会使该行饱和规则缓冲区,并返回 short 写入返回值(将被忽略)。
write()的第三次迭代,如果足够快,则可以直接拒绝,返回值为-1, errno < / strong> EAGAIN 表示写入会阻止 将忽略此错误情况,并且永远不会传输此2233字节的数据。
这似乎与你对的观察完全相关“文本的最后几行没有传输...文件的大小超过4.5kb且没有usleep()函数。” < / p>
ADDENDUM
修改后的阻塞模式代码,正确的端子设置和返回值检查如下所示 @ e.jahandar的修正版本的建议和@LPs的评论也被纳入。
...
sid = open(dev, O_RDWR | O_NOCTTY);
if (sid < 0) {
printf("Err 1\n"); //Serial port not open
return (-1);
}
if (tcgetattr(sid, &serial_struct) < 0) {
printf("Err 2\n");
return (-2);
}
cfsetospeed(&serial_struct, (speed_t)Baudrate);
cfsetispeed(&serial_struct, (speed_t)Baudrate);
cfmakeraw(&serial_struct);
serial_struct.c_cc[VMIN] = 1;
serial_struct.c_cc[VTIME] = 10;
serial_struct.c_cflag &= ~CSTOPB;
serial_struct.c_cflag &= ~CRTSCTS; /* no HW flow control? */
serial_struct.c_cflag |= CLOCAL | CREAD;
if (tcsetattr(sid, TCSANOW, &serial_struct) < 0) {
printf("Err 3\n"); //Unable to set serial port parameters
return (-3);
}
...
#define BUFSIZE 2233
char buf[BUFSIZE + 1];
...
size_t frv;
ssize_t wrv;
...
do {
frv = fread(buf, 1, BUFSIZE, fd);
buf[frv] = 0; /* terminate string for printf */
if (frv > 0) {
wrv = write(sid1, buf, frv);
if (wrv < frv) {
/* handle error or short write */
}
} else
break;
} while (1);
...