转载_Linux下串口编程

来源:互联网 发布:3d溜溜软件 编辑:程序博客网 时间:2024/05/03 14:46

一.termios相关的操作,termios是在计算机使用初期,linux提供对串口操作的支持的接口

 

1总览:

 

#include <termios.h> 
#include <unistd.h>

int tcgetattr(int fd, struct termios *termios_p);//获取当前对串口设置的参数

int tcsetattr(int fd, int optional_actions, struct termios *termios_p);//用已经配置好的参数设置串口

int tcsendbreak(int fd, int duration);

int tcdrain(int fd);

int tcflush(int fd, int queue_selector);//刷新数据缓存去

int tcflow(int fd, int action);

int cfmakeraw(struct termios *termios_p);

speed_t cfgetispeed(struct termios *termios_p);//获取当前串口的输出波特率

speed_t cfgetospeed(struct termios *termios_p);//获取当前串口的输入波特率

int cfsetispeed(struct termios *termios_p, speed_t speed);//设置串口输出的波特率

int cfsetospeed(struct termios *termios_p, speed_t speed);//设置串口输入的波特率

 

2数据结构:

 

tcflag_t c_iflag; /* 输入模式 */

tcflag_t c_oflag; /* 输出模式 */

tcflag_t c_cflag; /* 控制模式 */

tcflag_t c_lflag; /* 本地模式 */

cc_t c_cc[NCCS]; /* 控制字符 */

 

 

 

二.对串口设置的实现流程:

 

1.保存以前对串口的设置:

   使用tcgetattr()

 

2.激活串口

   设置c_cflag的CLOCAL和CREAD标记位

 

3.设置波特率:

   使用cfsetispeed()设置输入的波特率

   使用cfsetospeed()设置输出的波特率 

 

4.设置数据位:

    设置c_cflag的~CSIZE和CS8的标记位

 

5.设置奇偶校验:

    如果设置为奇校验,需要设置的标记位如下:

    c_cflag的PARENB和PARODD

    c_iflag的INPCK和ISTRIP

    如果设置为偶校验,需要设置的标记位如下:

    c_cflag的PARENB和~PARODD

    c_iflag的INPCK和ISTRIP

 

6.设置停止位:

    一位停止位:

    c_cflag设置为~CSTOPB

    两位停止位

    c_cflag设置为CSTOPB

 

7.设置最少等待时间和最小字符:

    c_cc[VIME]=0;

    c_cc[VMIN]=0; 

 

8.处理要写入的对象:

    tcflush()

    这里面有三个参数要注意:

    TCIFLUSH 刷新输入队列

    TCOFLUSH 刷新输出队列

    TCIOFLUSH 刷新输入输出队列

 

9.激活配置:

    tcgetattr();获取设置好的参数

    tcsetattr();设置并且激活对串口的配置

    这里面有三个参数要注意:  

    TCSANOW 更改立即发生

    TCSADRAIN 发送了所有的输出后更改才发生,若更改输出参数应该使用这个选项

    TCSAFLUSH 发送了所有的输出后更改才发生,在更改发生时未读的所有数据都删除

 

 

三.对串口的操作:

 

 

1.打开串口设备:

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

   O_NOCTTY:通知linux系统,这个程序不会成为这个端口的控制终端

   O_NDELAY:通知linux系统不关心DCD信号线所处的状态(DCD信号线用以检测串口线另一端是否有设备连接)

 

2.串口的读和写:

   read(fd,buff,8);

   write(fd,buff,8);

 

四.经测试可用的源代码:

 

 

#include   <stdio.h>     

#include   <stdlib.h>   

#include   <unistd.h>     

#include   <sys/types.h> 

#include   <sys/stat.h>  

#include   <fcntl.h>    

#include   <termios.h>  

#include   <errno.h>    

#include   <string.h>

#define TRUE 1

//初始化串口选项:

 

 

void setTermios(struct termios * pNewtio, int uBaudRate)

{

    bzero(pNewtio, sizeof(struct termios));

    //8N1

    pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;

    pNewtio->c_iflag = IGNPAR;

    pNewtio->c_oflag = 0;

    pNewtio->c_lflag = 0; 

    pNewtio->c_cc[VINTR] = 0; /* Ctrl-c */

    pNewtio->c_cc[VQUIT] = 0; /* Ctrl-/ */

    pNewtio->c_cc[VERASE] = 0; /* del */

    pNewtio->c_cc[VKILL] = 0; /* @ */

    pNewtio->c_cc[VEOF] = 4; /* Ctrl-d */

    pNewtio->c_cc[VTIME] = 5; /* inter-character timer, timeout VTIME*0.1 */

    pNewtio->c_cc[VMIN] = 0; /* blocking read until VMIN character arrives */

    pNewtio->c_cc[VSWTC] = 0; /* '/0' */

    pNewtio->c_cc[VSTART] = 0; /* Ctrl-q */

    pNewtio->c_cc[VSTOP] = 0; /* Ctrl-s */

    pNewtio->c_cc[VSUSP] = 0; /* Ctrl-z */

    pNewtio->c_cc[VEOL] = 0; /* '/0' */

    pNewtio->c_cc[VREPRINT] = 0; /* Ctrl-r */

    pNewtio->c_cc[VDISCARD] = 0; /* Ctrl-u */

    pNewtio->c_cc[VWERASE] = 0; /* Ctrl-w */

    pNewtio->c_cc[VLNEXT] = 0; /* Ctrl-v */

    pNewtio->c_cc[VEOL2] = 0; /* '/0' */

}

 

#define BUFSIZE 512

 

int main(int argc, char **argv)

{

    int fd;

    int nread;

    char buff[BUFSIZE];

    struct termios oldtio, newtio;

    struct timeval tv;

    char *dev ="/dev/ttyS0";

    fd_set rfds;

 

    if ((fd = open(dev, O_RDWR | O_NOCTTY))<0)

    {

       printf("err: can't open serial port!/n");

       return -1;

    }

 

    tcgetattr(fd, &oldtio); /* save current serial port settings */

    setTermios(&newtio, B9600);

 

    tcflush(fd, TCIFLUSH);

    tcsetattr(fd, TCSANOW, &newtio);

 

    tv.tv_sec=30;

    tv.tv_usec=0;

 

    while (TRUE)

    {

       printf("wait.../n");

       FD_ZERO(&rfds);

       FD_SET(fd, &rfds);

       if (select(1+fd, &rfds, NULL, NULL, &tv)>0)

       {

           if (FD_ISSET(fd, &rfds))

           {

              nread=read(fd, buff, BUFSIZE);

              printf("readlength=%d/n", nread);

              buff[nread]='/0';

              printf("%d/n", buff[6]);

           }

       }

    }

 

    tcsetattr(fd, TCSANOW, &oldtio);

    close(fd);

}