QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2019|回复: 4

如何写串口设置函数

[复制链接]
发表于 2006-4-18 10:55:02 | 显示全部楼层 |阅读模式
我想做Linux下串口通信,可是看了半天论文和网上的相关内容,还是很糊涂,因为每篇设置所用的函数的设置很不一样,我认为这不排除打印错误和手误的可能。所以请各位高手指点一下我的串口设置是否写的正确(主要是那个结构体termios的写法)!
    我的通信协议:baudrate是38400,8位数据位,1位停止位,无奇偶校验。
    struct  termios options;
      options.c_cflag|=CS8;            /*8位数据位*/
      options.c_cflag&=CSTOPB;     /*1位停止位*/
      options.c_cflag&=~PARENB;   /*无奇偶校验*/

另外,波特率怎么设置呢?
   我看到有三种方法:
(1)、用一种数组的方式,通过一个循环的判断;
(2)、用函数cfsetispeed,cfsetospeed函数设置;
(3)、直接设置:
        比如: #define BAUDRATE  B38400;
                       .....
                       options.c_cflag=BAUDRATE|.......
  
       所以我很是糊涂,不知道到底怎则设置,请大家指点一下。

   
发表于 2006-4-18 13:32:46 | 显示全部楼层
[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]
回复

使用道具 举报

 楼主| 发表于 2006-4-18 22:43:40 | 显示全部楼层
真感谢你能写出这么详细的程序,我要仔细学习研究一下!
再次感谢!
回复

使用道具 举报

 楼主| 发表于 2006-4-19 11:07:34 | 显示全部楼层
看了这个程序,有几个不懂得地方:
(1)、整个程序为什么要用位操作;
(2)、在设置数据位的时候,
        tty.c_cflag=(tty.c_cflag & ~CSIZE)|CS5);我知道这是5位数据位的意思,  但是我想知道为什么这么写。
(3)、设置奇偶校验的那一段很糊涂,为什么无奇偶校验的情况要写上三次?
(4)、规范的模式怎么写呢?
另外是不是只有设定是raw模式下才用得着tty c_cc[VTIME]和c_cc[VMIN]这两个函数啊
,如果是规范模式就不用考虑镇两个参数是么?
回复

使用道具 举报

 楼主| 发表于 2006-4-19 11:09:54 | 显示全部楼层
如果斑竹有什么相关的书或者资料推荐我看一下的话,那将会少麻烦你了!
回复

使用道具 举报

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

本版积分规则

GMT+8, 2024-11-2 18:20 , Processed in 0.099683 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

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