打印
[应用相关]

Linux下的串口编程(转载)

[复制链接]
1297|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wakayi|  楼主 | 2018-10-12 12:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

Author             :tiger-john
WebSite            :blog.csdn.net/tigerjb

Email               :jibo.tiger@gmail.com

Update-Time   : 2011年2月14日星期一


一.Linux下的串口编程又那几部分组成

1.    打开串口

2.    串口初始化

3.    读串口或写串口

4.    关闭串口


沙发
wakayi|  楼主 | 2018-10-12 12:59 | 只看该作者

二.串口的打开

既然串口在linux中被看作了文件,那么在对文件进行操作前先要对其进行打开操作。

1.在Linxu中,串口设备是通过串口终端设备文件来访问的,即通过访问/dev/ttyS0,/dev/ttyS1,/dev/ttyS2这些设备文件实现对串口的访问。

2.调用open()函数来代开串口设备,对于串口的打开操作,必须使用O_NOCTTY参数。

l  O_NOCTTY:表示打开的是一个终端设备,程序不会成为该端口的控制终端。如果不使用此标志,任务一个输入(eg:键盘中止信号等)都将影响进程。

l  O_NDELAY:表示不关心DCD信号线所处的状态(端口的另一端是否激活或者停止)。

3.打开串口模块有那及部分组成

1>调用open()函数打开串口,获取串口设备文件描述符

2>获取串口状态,判断是否阻塞

3>测试打开的文件描述符是否为终端设备



使用特权

评论回复
板凳
wakayi|  楼主 | 2018-10-12 12:59 | 只看该作者

4程序:


/*****************************************************************

* 名称:                    UART0_Open

* 功能:                    打开串口并返回串口设备文件描述

* 入口参数:            fd    :文件描述符     port :串口号(ttyS0,ttyS1,ttyS2)

* 出口参数:            正确返回为1,错误返回为0

*****************************************************************/

int UART0_Open(int fd,char* port)

{

      fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);

      if (FALSE == fd)

             {

                    perror("Can't Open Serial Port");

                    return(FASLE);

             }

  //判断串口的状态是否为阻塞状态                           

  if(fcntl(fd, F_SETFL, 0) < 0)

      {

             printf("fcntl failed!/n");

           return(FALSE);

      }     

  else

  {

       printf("fcntl=%d/n",fcntl(fd, F_SETFL,0));

  }

  //测试是否为终端设备   

  if(0 == isatty(STDIN_FILENO))

      {

             printf("standard input is not a terminal device/n");

        return(FALSE);

      }

  else

      {

           printf("isatty success!/n");

      }      

  printf("fd->open=%d/n",fd);

  return fd;

}


使用特权

评论回复
地板
wakayi|  楼主 | 2018-10-12 13:00 | 只看该作者

三.串口的初始化

1.    在linux中的串口初始化和前面的串口初始化一样。需要设置串口波特率,数据流控制,帧的格式(即数据位个数,停止位,校验位,数据流控制)

2.    串口初始化模块有那几部分组成:

1>.设置波特率

2>设置数据流控制

2>设置帧的格式(即数据位个数,停止位,校验位)

John哥说明:

1>设置串口参数时要用到termios结构体,因此先要通过函数

tcgettattr(fd,&options)获得串口指向termios结构的指针。

2>通过cfsetispeed函数和cfsetospeed函数用来设置串口的输入/输出波特率。一般情况下,输入和输出波特率相等的。

3>设置数据位可以通过修改termios机构体中c_flag来实现。其中CS5,CS6,CS7,CS8对应数据位的5,6,7,8。在设置数据位时,必须要用CSIZE做位屏蔽。

4>数据流控制是使用何种方法来标志数据传输的开始和结束。

5>在设置完波特率,数据流控制,数据位,校验位,停止位,停止位后,还要设置最小等待时间和最小接收字符。

6>在完成配置后要通过tcsetattr()函数来激活配置。


使用特权

评论回复
5
wakayi|  楼主 | 2018-10-12 13:00 | 只看该作者

3.程序:

/*******************************************************************

* 名称:                UART0_Set

* 功能:                设置串口数据位,停止位和效验位

* 入口参数:        fd         串口文件描述符

*                              speed      串口速度

*                              flow_ctrl  数据流控制

*                           databits   数据位   取值为 7 或者8

*                           stopbits   停止位   取值为 1 或者2

*                           parity     效验类型 取值为N,E,O,,S

*出口参数:              正确返回为1,错误返回为0

*******************************************************************/

int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)

{

   

      int   i;

         int   status;

         int   speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,

          B38400, B19200, B9600, B4800, B2400, B1200, B300 };

     int   name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,      38400, 19200,  9600, 4800, 2400, 1200,  300 };

         

    struct termios options;

   

    /*tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数,还可以测试配置是否正确,该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1.

    */

    if  ( tcgetattr( fd,&options)  !=  0)

       {

          perror("SetupSerial 1");   

          return(FALSE);

       }

  

    //设置串口输入波特率和输出波特率

    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)

                {

              if  (speed == name_arr)

              {      

                          cfsetispeed(&Options, speed_arr);

                          cfsetospeed(&Options, speed_arr);  

              }

       }     

   

    //修改控制模式,保证程序不会占用串口

    options.c_cflag |= CLOCAL;

    //修改控制模式,使得能够从串口中读取输入数据

    options.c_cflag |= CREAD;

  

    //设置数据流控制

    switch(flow_ctrl)

    {

      

       case 0 ://不使用流控制

              options.c_cflag &= ~CRTSCTS;

              break;   

      

       case 1 ://使用硬件流控制

              options.c_cflag |= CRTSCTS;

              break;

       case 2 ://使用软件流控制

              options.c_cflag |= IXON | IXOFF | IXANY;

              break;

    }

    //设置数据位

    options.c_cflag &= ~CSIZE; //屏蔽其他标志位

    switch (databits)

    {  

       case 5    :

                     options.c_cflag |= CS5;

                     break;

       case 6    :

                     options.c_cflag |= CS6;

                     break;

       case 7    :   

                 options.c_cflag |= CS7;

                 break;

       case 8:   

                 options.c_cflag |= CS8;

                 break;  

       default:   

                 fprintf(stderr,"Unsupported data size/n");

                 return (FALSE);

    }

    //设置校验位

    switch (parity)

    {  

       case 'n':

       case 'N': //无奇偶校验位。

                 options.c_cflag &= ~PARENB;

                 options.c_iflag &= ~INPCK;   

                 break;

       case 'o':  

       case 'O'://设置为奇校验   

                 options.c_cflag |= (PARODD | PARENB);

                 options.c_iflag |= INPCK;            

                 break;

       case 'e':

       case 'E'://设置为偶校验  

                 options.c_cflag |= PARENB;      

                 options.c_cflag &= ~PARODD;      

                 options.c_iflag |= INPCK;      

                 break;

       case 's':

       case 'S': //设置为空格

                 options.c_cflag &= ~PARENB;

                 options.c_cflag &= ~CSTOPB;

                 break;

        default:  

                 fprintf(stderr,"Unsupported parity/n");   

                 return (FALSE);

    }

    // 设置停止位

    switch (stopbits)

    {  

       case 1:   

                 options.c_cflag &= ~CSTOPB;

                 break;

       case 2:   

                 options.c_cflag |= CSTOPB;

                         break;

       default:   

                       fprintf(stderr,"Unsupported stop bits/n");

                       return (FALSE);

    }

   

    //修改输出模式,原始数据输出

    options.c_oflag &= ~OPOST;

   

    //设置等待时间和最小接收字符

    options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */  

    options.c_cc[VMIN] = 1; /* 读取字符的最少个数为1 */

   

    //如果发生数据溢出,接收数据,但是不再读取

    tcflush(fd,TCIFLUSH);

   

    //激活配置 (将修改后的termios数据设置到串口中)

    if (tcsetattr(fd,TCSANOW,&options) != 0)  

    {

               perror("com set error!/n");  

       return (FALSE);

    }

    return (TRUE);

}

/*******************************************************************

* 名称:                  UART0_Init()

* 功能:                串口初始化

* 入口参数:        fd           文件描述符   

*               speed     串口速度

*                              flow_ctrl   数据流控制

*               databits    数据位   取值为 7 或者8

*                           stopbits   停止位   取值为 1 或者2

*                           parity     效验类型 取值为N,E,O,,S                    

* 出口参数:        正确返回为1,错误返回为0

*******************************************************************/

int UART0_Init(int fd, int speed,int flow_ctrlint databits,int stopbits,int parity)

{

    int err;

    //设置串口数据帧格式

    if (UART0_Set(fd,115200,0,8,1,'N') == FALSE)

    {                                                     

        return FALSE;

    }

    else

    {

               return  TRUE;

        }

}


使用特权

评论回复
6
wowu| | 2018-10-12 13:11 | 只看该作者
和windows有何不同呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

4083

帖子

1

粉丝