免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7135 | 回复: 15

[应用] read函数读串口失败 [复制链接]

论坛徽章:
0
发表于 2012-05-18 16:51 |显示全部楼层
本帖最后由 yff1030 于 2012-08-29 08:14 编辑

大家好!
我写了一个Linux下串口和主机通信的小程序,问题是这样的:
首先我的网络是通的,我用主机上的串口助手和Mini2440上的串口助手可以互相通信,所以硬件问题排除了。
现在,mini2440给PC发数据,PC可以收到,可是,PC给mini2440发数据,mini2440收不到。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>



/*******************打开串口*************************/
int open_port(int fd,int comport)
{
        char *dev[]={"/dev/ttySAC0","/dev/ttySAC1","/dev/ttySAC2"};
        long  vdisable;
        if (comport==1)
        {       
                fd = open( "/dev/ttySAC0", O_RDWR|O_NOCTTY|O_NONBLOCK);
        /*读写操作、不作为控制终端、不关心另一端口是否激活或关闭*/
                if (-1 == fd){
                        perror("Can't Open Serial Port");
                        return(-1);
                }
                else
                        printf("open ttySAC0 .....\n");
        }
        else if(comport==2)
        {       
                fd = open( "/dev/ttySAC1", O_RDWR|O_NOCTTY|O_NONBLOCK);
                if (-1 == fd){
                        perror("Can't Open Serial Port");
                        return(-1);
                }
                else
                        printf("open ttySAC1 .....\n");
        }
        else if (comport==3)
        {
                fd = open( "/dev/ttySAC2", O_RDWR|O_NOCTTY|O_NONBLOCK);
                if (-1 == fd){
                        perror("Can't Open Serial Port");
                        return(-1);
                }
                else
                        printf("open ttySAC2 .....\n");
        }
       
        if(fcntl(fd, F_SETFL, 0)<0)                //fcntl()设置串口的状态为阻塞状态,等待串口数据读入
                printf("fcntl failed!\n");
        else
                printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));//F_SETFL设置文件标记状态
       
        if(isatty(STDIN_FILENO)==0)                //isatty()测试打开的文件描述符是否引用一个终端设备,以进一步确认串口是否正确打开
                printf("standard input is not a terminal device\n");
        else
                printf("isatty success!\n");
        printf("fd_open=%d\n",fd);
        return fd;
}


/*******************设置串口参数************************/

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
        struct termios newtio,oldtio;
        if  ( tcgetattr( fd,&oldtio)  !=  0)          //将原有的设置保存到oldio,以便程序结束后恢复
        {
                perror("SetupSerial 1");
                return -1;
        }
        bzero( &newtio, sizeof( newtio ) );
        newtio.c_cflag  |=  CLOCAL | CREAD;         //本地连接和接收使能
        newtio.c_cflag &= ~CSIZE;                         //清除数据位掩码设置
        newtio.c_lflag&=~(ICANON);
        newtio.c_lflag &= ~(ICANON |ISIG);
        newtio.c_iflag &= ~(ICRNL|IGNCR);

        switch( nBits )
        {
        case 7:
                newtio.c_cflag |= CS7;                //数据位数
                break;
        case 8:
                newtio.c_cflag |= CS8;
                break;
        }

        switch( nEvent )
        {
        case 'O':                        //奇校验设置
                newtio.c_cflag |= PARENB;
                newtio.c_cflag |= PARODD;               
                newtio.c_iflag |= (INPCK | ISTRIP);
                break;
        case 'E':                         //偶校验设置
                newtio.c_iflag |= (INPCK | ISTRIP);
                newtio.c_cflag |= PARENB;
                newtio.c_cflag &= ~PARODD;
                break;
        case 'N':                  //无校验
                newtio.c_cflag &= ~PARENB;
                break;
        }

        switch( nSpeed )
        {
        case 2400:
                cfsetispeed(&newtio, B2400);        //设置输入波特率
                cfsetospeed(&newtio, B2400);//设置输出波特率
                break;
        case 4800:
                cfsetispeed(&newtio, B4800);
                cfsetospeed(&newtio, B4800);
                break;
        case 9600:
                cfsetispeed(&newtio, B9600);
                cfsetospeed(&newtio, B9600);
                break;
        case 115200:
                cfsetispeed(&newtio, B115200);
                cfsetospeed(&newtio, B115200);
                break;
        default:
                cfsetispeed(&newtio, B9600);
                cfsetospeed(&newtio, B9600);
                break;
        }
        if( nStop == 1 )       
        //停止位设置,若停止位为1, 则清除CSTOPB,
        //若停止位为2,则激活CSTOPB。

                newtio.c_cflag &=  ~CSTOPB;
        else if ( nStop == 2 )
        newtio.c_cflag |=  CSTOPB;
        newtio.c_cc[VTIME]  = 0;
        newtio.c_cc[VMIN] = 0;
       
        tcflush(fd,TCIFLUSH);
        //tcflush()刷清输入缓冲区或输出缓冲区
        //TCIFLUSH 输入队列
        if((tcsetattr(fd,TCSANOW,&newtio))!=0)                //前面串口的参数设置立即生效
        {
                perror("com set error");
                return -1;
        }
        printf("set done!\n");
        return 0;
}




/************************主函数************************/

int main(void)
{
        int fd;
        int i;       
        int nread;
        char *buff;
        if((fd=open_port(fd,1))<0)
        {
                perror("open_port error!");
                return;
        }
        if((i=set_opt(fd,115200,8,'N',1))<0)
        {
                perror("set_opt error!");
                return;
        }
        printf("fd=%d\n",fd);
       
        while(1)
        {
                nread=read(fd,buff,255);           //读串口数据
                printf("nread=%d\n",nread);
                if(nread>0)
                {
                       
                        printf("receive data is %s\n",buff);
                }
                else
                        printf("cannot receive data!\n");

                sleep(2);
        }
        close(fd);       
        return 0;
}






执行结果:
open ttySAC0......
fcntl=0
isatty success!
fd_open=11;
set done!
fd=11;
nread=0
cannot receive data!
nread=0
cannot receive data!
nread=-1
cannot receive data!
nread=-1
cannot receive data!
nread=-1
cannot receive data!
nread=-1
cannot receive data!
........

求指教,为什么read函数一直读不成功?


论坛徽章:
0
发表于 2012-05-18 16:53 |显示全部楼层
求指教!

论坛徽章:
0
发表于 2012-05-18 18:34 |显示全部楼层
支持一下!
~~~~

论坛徽章:
0
发表于 2012-05-25 12:04 |显示全部楼层
int main(void)
{
        int fd;
        int i;        
        int nread;
        char *buff;  //不是指针,是数组  char buff[512]
        if((fd=open_port(fd,1))<0)
        {
                perror("open_port error!");
                return;
        }
        if((i=set_opt(fd,115200,8,'N',1))<0)
        {
                perror("set_opt error!");
                return;
        }
        printf("fd=%d\n",fd);
        
        while(1)
        {
                nread=read(fd,buff,255);           //读串口数据
                printf("nread=%d\n",nread);
                if(nread>0)
                {
                        
                        printf("receive data is %s\n",buff);
                }
                else
                        printf("cannot receive data!\n");

                sleep(2);
        }
        close(fd);        
        return 0;
}

论坛徽章:
0
发表于 2012-06-14 10:17 |显示全部楼层
请问楼主,你这个问题解决了吗?怎么解决的啊回复 1# yff1030


   

论坛徽章:
0
发表于 2012-08-07 19:36 |显示全部楼层
没有呢,然后现在没有在做那一块了

论坛徽章:
0
发表于 2012-08-08 21:38 |显示全部楼层
本帖最后由 cxjchen1 于 2012-08-08 21:59 编辑

回复 6# yff1030


    哈哈,你走运,正好最近我也遇到了这个问题。
    newtio.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    newtio.c_oflag  &= ~OPOST;   /*Output*/
如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯。


如果不这样设置,你就会发现,每次read返回的都是-1

论坛徽章:
0
发表于 2012-08-08 22:00 |显示全部楼层
如果成功了,记得告诉我

论坛徽章:
0
发表于 2012-08-09 08:16 |显示全部楼层
回复 8# cxjchen1



   

论坛徽章:
0
发表于 2012-08-09 09:05 |显示全部楼层
回复 9# yff1030


    不行就算了,还费我注册个账号。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP