主题 : 请教一个使用QQ2440第二个串口,即硬件上的TXD1,RXD1 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 209
精华: 0
发帖: 9
金钱: 90 两
威望: 9 点
综合积分: 18 分
注册时间: 2008-03-03
最后登录: 2009-06-12
楼主  发表于: 2008-12-05 22:35

 请教一个使用QQ2440第二个串口,即硬件上的TXD1,RXD1

本来以为直接对/dev/tts/2进行操作就可以了,但是发现不行,会出现Illegal seek的错误。后来在/proc/devices里面看见有一个serial设备的主设备号是204,所以自己在/dev下使用mknod /dev/qq c 204 65,建了一个主设备号是204,从设备号是65的文件,对其进行串口写时,完全没有问题。但是在读时,却发现其不是阻塞的。只要read就马上返回了,不知道这个问题怎么解决。请教各位高手。


PS:我用的是QQ2440 2.6.13的内核。不知道有没有遇到和我相同问题的弟兄。能帮我看看,谢谢。
我的串口程序如下:
#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 set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    if  ( tcgetattr( fd,&oldtio)  !=  0) {
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag  |=  CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    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 )
        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);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}

int open_port(int fd,int comport)
{
    char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};
    long  vdisable;
    if (comport==1)
    {    fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS0 .....\n");
    }
    else if(comport==2)
    {    fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS1 .....\n");
    }
    else if (comport==3)
    {
        fd = open( "/dev/qq", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS2 .....\n");
    }
    if(fcntl(fd, F_SETFL, 0)<0)
        printf("fcntl failed!\n");
    else
        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
    if(isatty(STDIN_FILENO)==0)
        printf("standard input is not a terminal device\n");
    else
        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;
}

int main(void)
{
    int fd;
    int nread,i;
    char buff[]="Hello\n";

    if((fd=open_port(fd,3))<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);

    nread=read(fd,buff,8);
    printf("nread=%d,%s\n",nread,buff);
    close(fd);
    return;
}
级别: 新手上路
UID: 209
精华: 0
发帖: 9
金钱: 90 两
威望: 9 点
综合积分: 18 分
注册时间: 2008-03-03
最后登录: 2009-06-12
2楼  发表于: 2008-12-05 23:20
刚才看见QQ2440V3的用户手册上介绍了串口2和串口3的测试,结果按照手册的命令输入:

armcomtest –d /dev/tts/1 -o
出现错误提示
Unable to set comm port
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
3楼  发表于: 2008-12-05 23:29
首先搞清楚一个概念,open /dev下的哪一个文件,重要的不是它的名字,而是它对应的主,从设备号,换句话说,如果/dev/tts/2对应的是IDE设备的号码,到明天天亮你的程序也操作不了串口;
从你描述的问题看,你操作串口应该没有接收到数据(并不是接了串口线,线上就会有数据的), 而且,因为你传递给open()的参数里有O_NDELAY, 这等于告诉串口你的程序用的是非阻塞方式进行读写动作的,所以, read()不立即返回才怪.

在写程序之前,先用man命令查清楚要用的函数的用法.
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 209
精华: 0
发帖: 9
金钱: 90 两
威望: 9 点
综合积分: 18 分
注册时间: 2008-03-03
最后登录: 2009-06-12
4楼  发表于: 2008-12-06 10:28
谢谢版主的提醒,
我将
fd = open( "/dev/qq", O_RDWR|O_NOCTTY|O_NDELAY);
改为了
fd = open( "/dev/qq", O_RDWR|O_NOCTTY);
但是问题还是一样。
另外我是用过一个MAX3232将开发板的串口2与电脑的串口连接的,然后使用的串口调试助手进行的调试。

当写串口的时候完全没有问题,传的数据都正确,但是读的时候不阻塞的话,我没办法手动从电脑的串口发数据过来。
级别: 新手上路
UID: 209
精华: 0
发帖: 9
金钱: 90 两
威望: 9 点
综合积分: 18 分
注册时间: 2008-03-03
最后登录: 2009-06-12
5楼  发表于: 2008-12-06 11:48
事实上我的程序中在open后,用了
if(fcntl(fd, F_SETFL, 0)<0)
printf("fcntl failed!\n");
来从新将串口设置成阻塞方式了。。。。
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
6楼  发表于: 2008-12-06 19:14
复制代码
  1.     if(fcntl(fd, F_SETFL, 0)<0)
  2.         printf("fcntl failed!\n");
  3.     else
  4.         printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
  5.     if(isatty(STDIN_FILENO)==0)
  6.         printf("standard input is not a terminal device\n");
  7.     else
  8.         printf("isatty success!\n");


在用别人的程序之前先搞清楚程序是干什么用的。
[ 此帖被kasim在2008-12-06 19:22重新编辑 ]
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
7楼  发表于: 2008-12-06 19:25
有一点我可以告诉你的是,如果fcntl(fd, F_SETFL, 0)真的成功了,那你也别想操作串口了。

记住Linux的man命令比那些所谓的Linux XX编程宝典正确的多
[ 此帖被kasim在2008-12-06 19:30重新编辑 ]
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 3064
精华: 0
发帖: 6
金钱: 60 两
威望: 42 点
综合积分: 12 分
注册时间: 2008-12-25
最后登录: 2009-11-25
8楼  发表于: 2008-12-25 11:22
楼主要理解一切皆文件的这个概念啊
级别: 新手上路
UID: 14798
精华: 0
发帖: 5
金钱: 25 两
威望: 5 点
综合积分: 10 分
注册时间: 2010-02-23
最后登录: 2017-09-13
9楼  发表于: 2010-07-15 13:54
你可以看一下串口的驱动是否支持阻塞