【问题标题】:sending a file over serial port通过串口发送文件
【发布时间】:2013-03-06 02:50:56
【问题描述】:

使用此代码,我正在尝试将文件发送到 CC430f5137 并从中接收。我正在使用 2 个程序,一个是下面的程序(它用于向我的 linux VM 发送和接收回文件,另一个是 CC430f5137 的程序(它包含我在 windows 中的设备的 rx、tx 代码)。我可以能够将单个字节(例如,A)从文件发送到我的设备,但不能发送多个字节。

//sample1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <termios.h>
#define BUFSIZE            1300 //1

int open_serial( char *dev_name, int baud, int vtime, int vmin )
{
    int fd;
    struct termios  newtio;

    fd = open( dev_name, O_RDWR | O_NOCTTY );
    if ( fd < 0 )
    {
        printf( "Device OPEN FAIL %s\n", dev_name );
        return  -1;
    }
    memset(&newtio, 0, sizeof(newtio));
    newtio.c_iflag = IGNPAR|INLCR;  // non-parity void UARTHandler(int fd);
    newtio.c_oflag = 0;
    newtio.c_cflag = CS8 | CLOCAL | CREAD; // NO-rts/cts

    switch( baud )
    {
        case 115200 : newtio.c_cflag |= B115200; break;
        case 57600  : newtio.c_cflag |= B57600;  break;
        case 38400  : newtio.c_cflag |= B38400;  break;
        case 19200  : newtio.c_cflag |= B19200;  break;
        case 9600   : newtio.c_cflag |= B9600;   break;
        case 4800   : newtio.c_cflag |= B4800;   break;
        case 2400   : newtio.c_cflag |= B2400;   break;
        default     : newtio.c_cflag |= B115200; break;
    }
    //set input mode (non-canonical, no echo,.....)
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME] = vtime;
    newtio.c_cc[VMIN]  = vmin;
    tcflush  ( fd, TCIFLUSH );
    tcsetattr( fd, TCSANOW, &newtio );

    return fd;
}

int sendfile(int fd)      //void sendfile(int fd)
{
    int fd1,readc;
    unsigned short fileLength;
    unsigned char buf[BUFSIZE];

    fd1=open("cert.pem",O_RDONLY);

    fileLength=lseek(fd1,0,SEEK_END);
    printf("file length is %d bytes\n",fileLength);
    lseek(fd1,0,SEEK_SET);

    write(fd,(unsigned char*)&fileLength, 2);
           while(fileLength>0)
            {
                if(fileLength>=BUFSIZE)
                {
                    readc=read(fd1,buf,BUFSIZE);
                    if(readc==-1)
                    {
                    printf("read failed!!\n");
                    }
                    if(read>0)
                    {
                    buf[BUFSIZE]='\0';
                    printf("%s\n",buf);
                    if(write(fd,buf,BUFSIZE))
                    fileLength -= BUFSIZE;
                    }
                }
                else
                {
                    readc=read(fd1,buf,fileLength);
                    if(readc==-1)
                    {
                    printf("read failed!!\n");
                    }
                    if(readc>0)
                    {
                    buf[fileLength]='\0';
                    printf("%s\n",buf);
                    if(write(fd, buf, fileLength))
                    fileLength=0;
                    }
                }
            }
    printf("%s\n",fd);
    printf("file sent succssfully\n");
    return fd1;//close(fd1);
    close(fd);

}

void receivefile(int fd)
    {
        char buf[1300],read_byte,buf2[1300];
        int fd2,readc;
        unsigned short fileLength;

        fd2=open("test.pem", O_WRONLY|O_CREAT);

                if(fd2<0)
                {
                printf("file open failed!!\n");
                        }
                while(!(read(fd,(unsigned char*)&fileLength,2)>0));

                printf("i am in receive file\n");

                while(fileLength>0) 
                {
                    readc = read(fd, buf, BUFSIZE);
                    if(readc==-1)
                    {
                    printf("read failed!!\n");
                    }
                printf("read %d bytes, value is %s\n",readc,buf);

                    if(readc >0)
                    {
                    buf[readc]='\0';
                    printf("buf value is%s\n", buf);
                    write(fd2,buf,readc);
                    fileLength -= readc;
                    }
                }
            close(fd2);
            close(fd);
    }

void close_serial( int fd )
{
    close( fd );
    printf("ClosePort!!\n");
}

int  main( int argc, char **argv )
{
    int fd;
    int baud;
    char  dev_name[128];

    if ( argc != 3)
    {
        printf( " sample_serial [device] [baud]\n" \
               "    device : /dev/ttySAC0 ...\n"    \
               "    baud   : 2400 ... 115200\n" );
        return -1;
    }
    printf( " Serial test start...  (%s)\n", __DATE__ );

    strcpy( dev_name, argv[1] );
    baud    = strtoul( argv[2], NULL, 10 );

    fd = open_serial( dev_name, baud, 4, 1);

    sendfile(fd);
    receivefile(fd);        
    close_serial( fd );        
    printf( " Serial test end\n" );

    return  0;
}

这是从文件发送 1 个字节到串口的输出

  [root@localhost ~]# gcc -std=c99 -std=gnu99 sample1.c -o out1
  sample1.c:151:50: warning: backslash and newline separated by space
  sample1.c:152:45: warning: backslash and newline separated by space
  [root@localhost ~]# ./out1 /dev/ttyUSB20 115200
  Serial test start...  (Mar  6 2013)
  file length is 2 bytes
  A
  wrote 3 bytes
  file sent succssfully
  i am in receive file
  read 1 bytes, value is A
  buf value isA
  read 1 bytes, value is A
  buf value isA
  read 1 bytes, value is A
  buf value isA
  read 1 bytes, value is A
  buf value isA

这是从文件向串口发送多个字节的输出

  [root@localhost ~]# gcc -std=c99 -std=gnu99 sample1.c -o out1
  sample1.c:151:50: warning: backslash and newline separated by space
  sample1.c:152:45: warning: backslash and newline separated by space
  [root@localhost ~]# ./out1 /dev/ttyUSB20 115200
  Serial test start...  (Mar  6 2013)
  file length is 2 bytes
  i am doing well today
  wrote 3 bytes
  file sent succssfully
  i am in receive file
  read 1 bytes, value is
  buf value is
  read 1 bytes, value is 
  buf value is
  read 1 bytes, value is 
  buf value is
  read 1 bytes, value is 
  buf value is

正如你在这里看到的,我没有得到文件内容,我正在接收空字符 从我的设备,即使我向我的设备发送了多个字节。

sendfile() 工作正常,我可以将“cert.pem”写入端口。我有一个 从端口读取文件并写回“test.pem”的问题。我得到了输出 接收程序中给出了一些打印语句,但连续获取数据。标志设置在 正确的方式。我也重置了所有连接。

【问题讨论】:

  • 有很多代码供我们阅读……您能否更具体地说明哪些有效,哪些无效?也许只显示代码的相关部分?
  • 串行端口可能是毛茸茸的小野兽。您发布代码并要求我们告诉您为什么“它不起作用”对您来说没有效率。您应该首先自己进行一些基本调查。获取连接代码并测试它是否有效。检查所有端口标志是否设置正确。尝试发送和接收单个字节。测试您的文件是否被正确打开和读取。测试接收端是否可以创建文件。
  • 在上面的注释中......我注意到当你打开test.pem时你从不检查你的文件句柄是否有效。
  • while(!(read(fd,(unsigned char*)&amp;fileLength,2)&gt;0)); 的目的是什么?这实际上并没有给你带来任何好处,如果 read 返回-1(错误),它实际上会伤害你——你会永远循环。 man read
  • libcurl ??? curl.haxx.se/libcurl

标签: c linux file-io serial-port


【解决方案1】:

你做错了——不要重新发明通过串行链接发送二进制文件问题的解决方案,而是使用已经存在的标准解决方案,例如ZMODEM

当你这样做时,你不必编写 Linux 端程序,因为已经存在一个免费的程序,你可以将现有的程序移植到你的 CC430f5137,不管是什么。

【讨论】:

  • 谢谢。具体来说,我正在发送微控制器的文件(证书,用于测试身份验证),文件是使用 linux 虚拟机中的开源代码生成的。我正在将文件发送到其他开源代码(此代码旨在在 Windows 中的微控制器上运行。请让我现在知道您的响应。你是说这个案子吗?
  • 我是说您需要使用现有的库和协议,例如 ZMODEM。这将节省您的编码和调试时间。
【解决方案2】:

让我们从显而易见的开始。

a : Sendfile 没有任何循环结构...

b:缓冲区溢出,像这样:

unsigned char buf[BUFSIZE];
...
buf[BUFSIZE]=0

c: 你有这样的调试“读取 1 个字节,值为 A”,但它不在代码中。很难修复您尚未发布的代码...

【讨论】:

  • 谢谢。你能告诉我更多吗?我可以在端口上写文件。但无法接收回文件 test.pem。我之前错过了代码中的一行(如你所说)。我已经编辑了代码。
  • @aparna :a:当您发送的文件超过一个缓冲区时,您需要一个循环(forwhile),就像您在接收代码中那样。 缓冲区溢出。 C 数组索引从 0 到 n-1,因此 buf[BUFSIZE] 正在您的数组外部写入并破坏其他内容。
猜你喜欢
  • 2011-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
  • 2011-06-15
  • 2013-09-09
  • 2015-08-29
相关资源
最近更新 更多