串口编程2:编程基础

阅读目录

操作串口需要包含的头文件

#include <stdio.h>   /*标准输入输出的定义*/
#include <errno.h>  /*错误号定义*/
#include <sys/stat.h>
#include <fcntl.h>  /*文件控制定义*/
#include <termios.h>    /*PPSIX 终端控制定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <sys/types.h>
#include <unistd.h> /*UNIX 标准函数定义*/

串口相关操作 

打开串口

我们都知道,在Linux下,除了网络设备,其余的都是文件的形式。串口设备也一样在/dev下。

所以我们可以通过open系统调用/函数来访问它。 示例: 

fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY|O_NDELAY); 

O_NOCTTY:可以告诉Linux这个程序不会成为这个端口上的“控制终端”.如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。 
O_NDELAY:标志则是告诉Linux,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接。

读写串口

与普通文件一样,使用read,write函数。 示例:

read(fd,buff,8); 
write(fd,buff,8);

串口属性设置 

最基本的设置串口包括波特率设置,效验位和停止位设置。这由通信双方协定。

很多系统都支持POSIX终端(串口)接口.程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等.要使用这个端口的话,你必须将<termios.h>头文件包含到你的程序中。这个头文件中定义了终端控制结构体和POSIX控制函数。

最重要的就是这个结构体:

struct termios
{
    tcflag_t  c_iflag;  //输入选项
    tcflag_t  c_oflag;  //输出选项
    tcflag_t  c_cflag;  //控制选项
    tcflag_t  c_lflag;  //行选项
    cc_t      c_cc[NCCS]; //控制字符
};

其中我们更关注的是c_cflag控制选项。其中包含了波特率、数据位、校验位、停止位的设置。 
它可以支持很多常量名称其中设置数据传输率为相应的数据传输率前要加上“B”。 
c_cflag成员不能直接对其初始化,而要将其通过与、或操作使用其中的某些选项。 
设置串口属性主要是配置termios结构体中的各个变量,大致流程如下:

使用函数tcgetattr保存原串口属性 

struct termios newtio,oldtio; 
tcgetattr(fd,&oldtio);

通过位掩码的方式激活本地连接和接受使能选项:CLOCAL和CREAD 

newtio.c_cflag | = CLOCAL | CREAD;

使用函数cfsetispeed和cfsetospeed设置数据传输率 

cfsetispeed(&newtio,B115200); 
cfsetospeed(&newtio,B115200);

取值必须是以下常量之一:

B0    B50    B75    B110    B134    B150    B200    B300    B600    B1200    B1800
B2400    B4800    B9600    B19200    B38400    B57600    B115200    B230400

通过位掩码设置字符大小

newtio.c_cflag &= ~CSIZE; 
newtio.c_cflag |= CS8;

设置奇偶效验位

设置奇偶效验位需要用到两个termios中的成员:c_cflag和c_iflag。首先要激活c_cflag中的校验位使能标志PARENB和是否进行奇偶效验,同时还要激活c_iflag中的奇偶效验使能。 

//设置奇校验: 
newtio.c_cflag |= PARENB; 
newtio.c_cflag |= PARODD; 
newtio.c_iflag |= (INPCK | ISTRIP); 
//设置偶校验: 
newtio.c_iflag |= (INPCK|ISTRIP); 
newtio.c_cflag |= PARENB; 
newtio.c_cflag |= ~PARODD;

设置停止位

激活c_cflag中的CSTOPB设置停止位。若停止位为1,则清除CSTOPB;若停止位为0,则激活CSTOPB。

newtio.c_cflag &= ~CSTOPB;

设置最少字符和等待时间

在对接收字符和等待时间没有特别要求的情况下,可以将其设置为0。

newtio.c_cc[VTIME] = 0; 
newtio.c_cc[VMIN] = 0;

处理要写入引用的对象

调用函数”tcflush(fd,queue_selector)”来处理要写入引用的对象,queue_selector可能的取值有以下几种:

TCIFLUSH:刷新收到的数据但是不读 
TCOFLUSH:刷新写入的数据但是不传送 
TCIOFLUSH:同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送。

激活配置

在完成配置后,需要激活配置使其生效。使用tcsetattr()函数。

int tcsetattr(int filedes,int opt,const struct termios *termptr);

串口配置的完整代码

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


int set_serial(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
    struct termios newttys1,oldttys1;

     /*保存原有串口配置*/
     if(tcgetattr(fd,&oldttys1)!=0) 
     {
          perror("Setupserial 1");
          return -1;
     }
     bzero(&newttys1,sizeof(newttys1));
     newttys1.c_cflag|=(CLOCAL|CREAD ); /*CREAD 开启串行数据接收,CLOCAL并打开本地连接模式*/

     newttys1.c_cflag &=~CSIZE;/*设置数据位*/
     /*数据位选择*/   
     switch(nBits)
     {
         case 7:
             newttys1.c_cflag |=CS7;
             break;
         case 8:
             newttys1.c_cflag |=CS8;
             break;
     }
     /*设置奇偶校验位*/
     switch( nEvent )
     {
         case '0':  /*奇校验*/
             newttys1.c_cflag |= PARENB;/*开启奇偶校验*/
             newttys1.c_iflag |= (INPCK | ISTRIP);/*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特  */
             newttys1.c_cflag |= PARODD;/*启用奇校验(默认为偶校验)*/
             break;
         case 'E':/*偶校验*/
             newttys1.c_cflag |= PARENB; /*开启奇偶校验  */
             newttys1.c_iflag |= ( INPCK | ISTRIP);/*打开输入奇偶校验并去除字符第八个比特*/
             newttys1.c_cflag &= ~PARODD;/*启用偶校验*/
             break;
         case 'N': /*无奇偶校验*/
             newttys1.c_cflag &= ~PARENB;
             break;
     }
     /*设置波特率*/
    switch( nSpeed )  
    {
        case 2400:
            cfsetispeed(&newttys1, B2400);
            cfsetospeed(&newttys1, B2400);
            break;
        case 4800:
            cfsetispeed(&newttys1, B4800);
            cfsetospeed(&newttys1, B4800);
            break;
        case 9600:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
        case 115200:
            cfsetispeed(&newttys1, B115200);
            cfsetospeed(&newttys1, B115200);
            break;
        default:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
    }
     /*设置停止位*/
    if( nStop == 1)/*设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB*/
    {
        newttys1.c_cflag &= ~CSTOPB;/*默认为一位停止位; */
    }
    else if( nStop == 2)
    {
        newttys1.c_cflag |= CSTOPB;/*CSTOPB表示送两位停止位*/
    }

    /*设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
    newttys1.c_cc[VTIME] = 0;/*非规范模式读取时的超时时间;*/
    newttys1.c_cc[VMIN]  = 0; /*非规范模式读取时的最小字符数*/
    tcflush(fd ,TCIFLUSH);/*tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */

     /*激活配置使其生效*/
    if((tcsetattr( fd, TCSANOW,&newttys1))!=0)
    {
        perror("com set error");
        return -1;
    }

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章