QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1394|回复: 13

请教,串口操作的函数有哪些?

[复制链接]
发表于 2005-9-21 17:39:48 | 显示全部楼层 |阅读模式
用OPEN打开DEV/TTYS0后该如何进行读写等操作呢?
我翻了手上几本书,都没提到。
发表于 2005-9-21 19:39:22 | 显示全部楼层
跟读写文件一样
回复

使用道具 举报

 楼主| 发表于 2005-9-21 22:38:30 | 显示全部楼层
具体点吧,
比如,我怎么知道串口有数据到了?一直读?用中断?怎么用?
回复

使用道具 举报

发表于 2005-9-22 09:35:24 | 显示全部楼层
一直读,可以用阻塞模式。
干脆给你个例子
[code:1]
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>

/*
* 串口初始化函数。
* 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(char *dev,int speed,int databits,int parity,int stopbits,int hwf,int swf)
{

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

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

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

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

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

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

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

[/code:1]
回复

使用道具 举报

 楼主| 发表于 2005-9-22 09:44:36 | 显示全部楼层
非常感谢!

另外,这个SerialPortInit()函数是自带的还是要自己写?
回复

使用道具 举报

发表于 2005-9-22 22:09:05 | 显示全部楼层
自己写
回复

使用道具 举报

 楼主| 发表于 2005-9-26 10:19:33 | 显示全部楼层
今天尝试了一下,
有些不明白的地方,
函数cfsetispeed()和cfsetospeed(),还有tty.c_iflag能的介绍什么地方能找到呢?
回复

使用道具 举报

发表于 2005-9-26 13:17:56 | 显示全部楼层
man cfsetispeed
man cfsetospeed
回复

使用道具 举报

 楼主| 发表于 2005-9-26 14:24:46 | 显示全部楼层
汗,把这个忘了…………

有没有什么书是讲这个呢?

谢谢!
回复

使用道具 举报

 楼主| 发表于 2005-9-27 11:37:45 | 显示全部楼层
再请教一下,我对这句不解:
int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,B0};

看起来定义的是一个整数型数组,里面用B××××是什么意思呢?
回复

使用道具 举报

发表于 2005-9-28 12:02:32 | 显示全部楼层
Bxxxx是宏,在/usr/include/bits/termios.h里定义
回复

使用道具 举报

 楼主| 发表于 2005-9-29 14:57:48 | 显示全部楼层
还有一点迷惑,ttyS0和S1应该是用不同的寄存器设置,不过从例子中似乎看不出来…………
回复

使用道具 举报

发表于 2005-9-29 17:32:00 | 显示全部楼层
那是驱动应该干的事情
回复

使用道具 举报

 楼主| 发表于 2005-10-10 17:43:05 | 显示全部楼层
试的结果是对/dev/ttyS0可以,单对/dev/ttyS1就显示:tcgetattr error
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-5 02:02 , Processed in 0.105114 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表