Hi 3520D中未传输文本文件中的整个字符

时间:2016-12-20 13:22:14

标签: c linux serial-port

我正在尝试从文本文件中读取一些数据并将其写入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");
}

2 个答案:

答案 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);

...