串口通信遇到麻烦.请各位帮忙

linuxcici
串口通信遇到麻烦.请各位帮忙

用一条RS232线连接两台LINUX .用了命令测试串口和发消息是保证系统和线是没问题的.
在两端用同一样的代码. 也试过一台LINUX read.另外一台write. 还是不行.
问题就是在read那里阻塞. 读不到数据. 但write那边是正确的喔. 什么原因呢
代码是书上的
代码:
[code]
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<termios.h>



int open_port(void)
{
        int fd;
        fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
        if(fd==-1)
        {
                printf(" unable to open /dev/ttyS1/n");

        }
        else
        {
                printf("/nOpen serial Ok~/n");
                      fcntl(fd,F_SETFL,0);


        }

        return(fd);
}


void init_serial(int fd)
{
        struct termios options;
        tcgetattr(fd,&options);
        cfsetispeed(&options,B115200);
        cfsetospeed(&options,B115200);
        options.c_cflag|=(CLOCAL|CREAD);
        options.c_cflag&=~CSIZE;
        options.c_cflag|=CS8;
        tcsetattr(fd,TCSANOW,&options);

}


int read_data(int fd)
{
        char buffer[255];
        char *bufptr;
        int nbytes;
        bufptr=buffer;

     while((nbytes=read(fd,bufptr,buffer+sizeof(buffer)-bufptr-1))>0)
        {

              
        bufptr+=nbytes;
        if(bufptr[-1]=='/n'|| bufptr[-1]=='/r')
                 break;


        }

        *bufptr='/0';
        printf("/n%s/n",buffer);

        return(0);
}

int write_port(int fd)
{
        int n;
        printf("in F_write_port/n");
        n=write(fd,"hello world!/r",12);
        if(n<0)
        {
                fputs("failed!/n",stderr);
        }
        else
        {
                printf("write ok/n");
        }
        return 0;
}

int main(void)
{
        int fd;
        fd=open_port();
        if(fd!=-1)
        {
                    init_serial(fd);
        //      write_port(fd);

      
                read_data(fd);

     

        }

        close(fd);
        return 0;
}

[/code]

linuxcici
在A机器运行:cat /dev/ttyS0

在B机器运行:echo 'test1234' > /dev/ttyS0 , A机器是能收到的.

但在B机器运行上面代码.[只用write_port这涵数]的话. 运行后A机器没反应.但如果再运行一次:
echo 'test1234' > /dev/ttyS0 . A机器就显示:hello worltest1234 把原来B机器的程序的消息也连同命令的消息发送出去了. 为什么呢?

jamesr
难道是缓冲问题?

xi2008wang
fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
        if(fd==-1)
        {
                printf(" unable to open /dev/ttyS1/n");

书上也有这样的代码?

cccccc
机器的流模式设置不对吧。在两台机器里运行  stty -a -F /dev/ttyS1看看

cjaizss
你两边链路层设置不一样
再者,通信之前应该tcflush一下

[[i] 本帖最后由 cjaizss 于 2008-2-14 12:39 编辑 [/i]]

linuxcici
thanks

linuxcici
[code]
while((nbytes=read(fd,bufptr,buffer+sizeof(buffer)-bufptr-1))>0)
        {

              
        bufptr+=nbytes;
        if(bufptr[-1]=='/n'|| bufptr[-1]=='/r')
                 break;


        }

        *bufptr='/0';
        printf("/n%s/n",buffer);

        return(0);
}

[/code]
这段代码. 我写了:write(fd,"hello World!/r",12);
这个read老是运行了两次. 要是我发:write(fd,"hello World!",12);简直什么都收不到.
请问串口发信息,字符串是以什么结束的呢? 我又改了: read(fd, buffer,sizeof(buffer))这样的标准形式去读. 但是什么都读不到. 请各位有经验的大牛能贴一下代码吗? 真的很急..

linuxcici
顶一下

cccccc
char tmp="hello word/n";
write(fd,tmp,sizeof(tmp));
这样试试

linuxcici
[code]
#include &lt;stdio.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;termios.h&gt;
#include &lt;unistd.h&gt;
#include &lt;string.h&gt;

/*
* 串口初始化函数。
* dev:串口设备名,串口1是"/dev/ttyS0",串口2是"/dev/ttyS1",依此类推。
* USB转串口的设备名是"/dev/ttyUSB0"、"/dev/ttyUSB1"等等。
* speed:串口波特率,可以是230400, 115200, 57600, 38400,  19200,  9600, 4800, 2400, 1200,  300, 0。
* databits:数据位,值是5、6、7或者8。
* parity:奇偶校验。值为'N','E','O','S'。
* stopbits:停止位,值是1或者2。
* hwf:硬件流控制。1为打开,0为关闭。
* swf:软件流控制。1为打开,0为关闭。
*/
int SerialPortInit&#40;char *dev,int speed,int databits,int parity,int stopbits,int hwf,int swf&#41;
{

    int                fd,i,ret;
    struct termios        tty;
    int speed_arr&#91;&#93; = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,B0};
    int name_arr&#91;&#93; = {230400, 115200, 57600, 38400,  19200,  9600, 4800, 2400, 1200,  300, 0};
    fd=open&#40;dev,O_RDWR|O_NOCTTY&#41;;
    if&#40;!fd&#41;
    {
        printf&#40;"cannot open %s/n",dev&#41;;
        return -1;
    }
    ret=tcgetattr&#40;fd, &tty&#41;;
    if&#40;ret&lt;0&#41;
    {
        printf&#40;"tcgetattr error/n"&#41;;
        close&#40;fd&#41;;
        return -1;
    }
    //设置波特率
    for&#40;i= 0;  i &lt; sizeof&#40;speed_arr&#41; / sizeof&#40;int&#41;;  i++&#41;
    {
        if&#40;speed == name_arr&#91;i&#93;&#41;
        {
            cfsetispeed&#40;&tty, speed_arr&#91;i&#93;&#41;;
            cfsetospeed&#40;&tty, speed_arr&#91;i&#93;&#41;;
            break;
        }
        if&#40;name_arr&#91;i&#93; == 0&#41;
        {
            printf&#40;"speed %d is not support,set to 9600/n",speed&#41;;
            cfsetispeed&#40;&tty, B9600&#41;;
            cfsetospeed&#40;&tty, B9600&#41;;
        }
    }
    //设置数据位
    switch &#40;databits&#41;
    {
        case 5&#58;
                 tty.c_cflag = &#40;tty.c_cflag & ~CSIZE&#41; | CS5;
                 break;
        case 6&#58;
                 tty.c_cflag = &#40;tty.c_cflag & ~CSIZE&#41; | CS6;
                 break;
        case 7&#58;
                 tty.c_cflag = &#40;tty.c_cflag & ~CSIZE&#41; | CS7;
                 break;
        case 8&#58;
        default&#58;
                 tty.c_cflag = &#40;tty.c_cflag & ~CSIZE&#41; | CS8;
                 break;

    }
    //设置停止位
    if&#40;stopbits == 2&#41;
        tty.c_cflag |= CSTOPB;
    else
        tty.c_cflag &= ~CSTOPB;
    //设置奇偶校验
    switch &#40;parity&#41;
    {
        //无奇偶校验
        case 'n'&#58;
        case 'N'&#58;
            tty.c_cflag &= ~PARENB;   /* Clear parity enable */
            tty.c_iflag &= ~INPCK;    /* Enable parity checking */
            break;
            //奇校验
        case 'o'&#58;
        case 'O'&#58;
            tty.c_cflag |= &#40;PARODD | PARENB&#41;; /* 设置为奇效验*/
            tty.c_iflag |= INPCK;             /* Disable parity checking */
            break;
            //偶校验
        case 'e'&#58;
        case 'E'&#58;
            tty.c_cflag |= PARENB;    /* Enable parity */
            tty.c_cflag &= ~PARODD;   /* 转换为偶效验*/
            tty.c_iflag |= INPCK;     /* Disable parity checking */
            break;
            //等效于“无奇偶校验”
        case 'S'&#58;
        case 's'&#58;  /*as no parity*/
            tty.c_cflag &= ~PARENB;
            tty.c_cflag &= ~CSTOPB;

            break;
        default&#58;
            tty.c_cflag &= ~PARENB;   /* Clear parity enable */
            tty.c_iflag &= ~INPCK;    /* Enable parity checking */
            break;

    }
    //设置硬件流控制
    if &#40;hwf&#41;
        tty.c_cflag |= CRTSCTS;
    else
        tty.c_cflag &= ~CRTSCTS;

    //设置软件流控制
    if &#40;swf&#41;
        tty.c_iflag |= IXON | IXOFF;
    else
        tty.c_iflag &= ~&#40;IXON|IXOFF|IXANY&#41;;
    //设置为RAW模式
    tty.c_iflag &= ~&#40;IGNBRK | IGNCR | INLCR | ICRNL | IUCLC |
            IXANY | IXON | IXOFF | INPCK | ISTRIP&#41;;
    tty.c_iflag |= &#40;BRKINT | IGNPAR&#41;;
    tty.c_oflag &= ~OPOST;
    tty.c_lflag &= ~&#40;XCASE|ECHONL|NOFLSH&#41;;
    tty.c_lflag &= ~&#40;ICANON | ISIG | ECHO&#41;;
    tty.c_cflag |= &#40;CLOCAL | CREAD&#41;;

    tty.c_cc&#91;VTIME&#93; = 1;        /*(非阻塞模式)操作超时,单位为0.1秒*/
    tty.c_cc&#91;VMIN&#93; = 1;        /* 1为阻塞模式,0为非阻塞模式*/

    //设置串口属性
    ret = tcsetattr&#40;fd, TCSANOW, &tty&#41;;
    if&#40;ret &lt; 0&#41;
    {
        printf&#40;"error while setting %s attribe/n"&#41;;
        close&#40;fd&#41;;
        return -1;
    }
    tcflush&#40;fd,TCIOFLUSH&#41;;
    return fd;
}
main&#40;&#41;
{
    int fd;
    char *data="hello";
    char buf&#91;10&#93;;
    fd=SerialPortInit&#40;"/dev/ttyS0",9600,8,'N',1,0,0&#41;;
    if&#40;fd&#41;
    {
        read&#40;fd,buf,10&#41;;
        close&#40;fd&#41;;
    }
}

[/code]

[[i] 本帖最后由 linuxcici 于 2008-2-20 09:56 编辑 [/i]]

linuxcici
现在可以通信的. 问题就是同步的问题.
例如:

PC1:                                             PC2:
while(read())                          while(write())
如果wirte发的是"aaa"

但在PC1中的read因为在不停的在read有时候它收到的可能是全部的aaa, 但有时候收到的只是一个a. 剩下的两个a在下一次才收到. 请问怎么判断同步的问题呢?一定要在read里面去判断的吗?还是在设计串口的参数里面可以设置好的呢?

jamesr
以前发过类似的帖子没有人回复。串口参数是最复杂的了,你那个只有遇到/n才收到数据就是参数没有设置好。
搜到一个代码,希望有帮助。这部分主要是靠翻手册:
[url]http://www.tongyi.net/os/linux/1045036.html[/url]

sleetboy
回复 #12 linuxcici 的帖子

用select试过没有?
另外read的buffer改小一点儿试试