Linux C 配置串口

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux C 配置串口相关的知识,希望对你有一定的参考价值。

参考技术A

配置串口需要包含头文件

其中最核心的配置结构体为:

如何获取该结构呢?我们操作串口跟操作文件一样,也是调用 open() 函数来打开串口,

这样我们就能够得到一个文件描述符 fd ,然后就可以调用 tcgetattr() 函数来获取上述配置结构体了。

Linux 串口默认的配置为:波特率 9600,数据位 8 位,无奇偶校验,停止位 1 位,无 CTS/RTS 。

以下介绍一些常用的配置项:波特率、奇偶校验、数据位、停止位、硬件控制流。

相关接口:

Linux 将串口的波特率分为了输入波特率和输出波特率,不过最常用的场景是将两者设置成一样。

cfgetispeed() 函数获取输入波特率, cfgetospeed() 函数获取输出波特率。 cfsetispeed() 函数设置输入波特率, cfsetospeed() 函数用于设置输出波特率,当然 cfsetspeed() 函数扩展为同时设置输入和输出波特率。

上述接口中的 speed_t 是一系列波特率的标志位,例如常用的 115200 波特率就为 B115200,参考下述选项:

设置奇偶校验位可以通过修改 termios 结构体中的 c_cflag 成员来实现,若无校验,则将 PARENB 位设为 0;若有校验,则 PARENB 为 1。之后再根据 PARODD 来区分奇偶校验, PARODD 为 1 表示奇校验, PARODD 为 0 表示偶校验。例如设置无奇偶校验位:

设置数据位可以通过修改 termios 结构体中的 c_cflag 成员来实现,CS5、CS6、CS7 和 CS8 分别代表数据位 5、6、7 和 8。不过在设置数据位之前,需要先用 CSIZE 来做屏蔽字段,清楚这几个标志位,例如设置数据位为 8 位:

设置停止位可以通过修改 termios 结构体中的 c_cflag 成员来实现, CSTOPB 位为 1 表示 2 位停止位, CSTOPB 位为 0 标志 1 位停止位。例如设置停止位为 1 位:

设置硬件控制流可以通过修改 termios 结构体中的 c_cflag 成员来实现, CRTSCTS 为 1 表示使用硬件控制流,为 0 表示不使用硬件控制流。例如使能硬件控制流:

当然,最后还需要用 tcflush() 抛弃存储在 fd 里的未接收的数据。

再利用接口 tcsetattr() 函数将配置信息写入文件描述符 fd :

这样整个串口最常用的用法就配置完成了。

具体的配置使用可以参考我的项目 HCI-Middleware 里的 hci_transport_uart_linux.c 文件。

参考:

Linux C Serial串口编程


1,Linux 下打开串口设备,信号模型 读写程序

2,串口读写的IO复用Select模型

3, Linux 下打开串口设备,读写程序



1,Linux 下打开串口设备,信号模型 读写程序

[email protected]:/tmp/serial# cat main.c 
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<fcntl.h>  
#include<termios.h>  
#include<errno.h>  

#define FALSE -1  
#define TRUE 0  

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, };  

void set_speed(int fd, int speed)
{  
    int   i;   
    int   status;   
    struct termios   Opt;  
    tcgetattr(fd, &Opt);   
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++) 
    {   
        if  (speed == name_arr[i]) 
        {       
            tcflush(fd, TCIOFLUSH);       
            cfsetispeed(&Opt, speed_arr[i]);    
            cfsetospeed(&Opt, speed_arr[i]);     
            status = tcsetattr(fd, TCSANOW, &Opt);    
            if  (status != 0) 
            {          
                perror("tcsetattr fd1");    
                return;       
            }      
            tcflush(fd,TCIOFLUSH);     
        }    
    }  
}  

int set_Parity(int fd,int databits,int stopbits,int parity)  
{   
    struct termios options;   
    if  ( tcgetattr( fd,&options)  !=  0) 
    {   
        perror("SetupSerial 1");       
        return(FALSE);    
    }  
    options.c_cflag &= ~CSIZE;   
    switch (databits)   
    {     
        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;   /* Clear parity enable */  
            options.c_iflag &= ~INPCK;     /* Enable parity checking */   
            break;    
        case ‘o‘:     
        case ‘O‘:       
            options.c_cflag |= (PARODD | PARENB);   
            options.c_iflag |= INPCK;             /* Disnable parity checking */   
            break;    
        case ‘e‘:    
        case ‘E‘:     
            options.c_cflag |= PARENB;     /* Enable parity */      
            options.c_cflag &= ~PARODD;      
            options.c_iflag |= INPCK;       /* Disnable parity checking */  
            break;  
        case ‘S‘:   
        case ‘s‘:  /*as no parity*/     
            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);   
    }   
    /* Set input parity option */   
    if (parity != ‘n‘)     
        options.c_iflag |= INPCK;   
    tcflush(fd,TCIFLUSH);  
    options.c_cc[VTIME] = 150;   
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */  
    if (tcsetattr(fd,TCSANOW,&options) != 0)     
    {   
        perror("SetupSerial 3");     
        return (FALSE);    
    }   
    return (TRUE);    
}  

int main()  
{  
    int fd;  
    fd = open("/dev/ttyUSB0",O_RDWR);  
    if(fd == -1)  
    {  
        perror("serialport error\n");  
    }  
    else  
    {  
        printf("open ");  
        printf("%s",ttyname(fd));  
        printf(" succesfully\n");  
    }  

    set_speed(fd,115200);  
    if (set_Parity(fd,8,1,‘N‘) == FALSE)  {  
        printf("Set Parity Error\n");  
        exit (0);  
    }  
    char buf[] = "1234567890123456789012345678901234567890";
    int n= write(fd,buf,strlen(buf));  
    printf("字符串实际长度%zd \n", strlen(buf));
    printf("成功写入%d \n", n);
    char buff[512];   
    int nread;    
    while(1)  
    {  
        if((nread = read(fd, buff, 512))>0)  
        {  
            printf("Len: %d:",nread);  
            buff[nread] = ‘\0‘;  
            printf("%s \n",buff);  
        }  
    }  
    close(fd);  
    return 0;  
}
[email protected]:/tmp/serial# gcc -Wall main.c && ./a.out   
open /dev/ttyUSB0 succesfully
字符串实际长度40 
成功写入40 
Len: 32:12345678901234567890123456789012 
Len: 8:34567890 
^C
[email protected]:/tmp/serial#



2,串口读写的IO复用Select模型

[email protected]:/tmp/serial# cat main.c 
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<sys/signal.h>  
#include<fcntl.h>  
#include<termios.h>  
#include<errno.h>  

#define FALSE -1  
#define TRUE 0  
#define flag 1  
#define noflag 0  

int wait_flag = noflag;  
int STOP = 0;  
int res;  

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, };  
void set_speed (int fd, int speed)  
{  
    int i;  
    int status;  
    struct termios Opt;  
    tcgetattr (fd, &Opt);  
    for (i = 0; i < sizeof (speed_arr) / sizeof (int); i++)  
    {  
        if (speed == name_arr[i])  
        {  
            tcflush (fd, TCIOFLUSH);  
            cfsetispeed (&Opt, speed_arr[i]);  
            cfsetospeed (&Opt, speed_arr[i]);  
            status = tcsetattr (fd, TCSANOW, &Opt);  
            if (status != 0)  
            {  
                perror ("tcsetattr fd1");  
                return;  
            }  
            tcflush (fd, TCIOFLUSH);  
        }  
    }  
}  

int set_Parity (int fd, int databits, int stopbits, int parity)  
{  
    struct termios options;  
    if (tcgetattr (fd, &options) != 0)  
    {  
        perror ("SetupSerial 1");  
        return (FALSE);  
    }  
    options.c_cflag &= ~CSIZE;  
    switch (databits)  
    {  
        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;   /* Clear parity enable */  
            options.c_iflag &= ~INPCK;    /* Enable parity checking */  
            break;  
        case ‘o‘:  
        case ‘O‘:  
            options.c_cflag |= (PARODD | PARENB);  
            options.c_iflag |= INPCK; /* Disnable parity checking */  
            break;  
        case ‘e‘:  
        case ‘E‘:  
            options.c_cflag |= PARENB;    /* Enable parity */  
            options.c_cflag &= ~PARODD;  
            options.c_iflag |= INPCK; /* Disnable parity checking */  
            break;  
        case ‘S‘:  
        case ‘s‘:           /*as no parity */  
            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);  
    }  
    /* Set input parity option */  
    if (parity != ‘n‘)  
        options.c_iflag |= INPCK;  
    tcflush (fd, TCIFLUSH);  
    options.c_cc[VTIME] = 150;  
    options.c_cc[VMIN] = 0;   /* Update the options and do it NOW */  
    if (tcsetattr (fd, TCSANOW, &options) != 0)  
    {  
        perror ("SetupSerial 3");  
        return (FALSE);  
    }  
    return (TRUE);  
}  

void signal_handler_IO (int status)  
{  
    printf ("received SIGIO signale.\n");  
    wait_flag = noflag;  
}  

int main ()  
{  
    int fd;  
    struct sigaction saio;  
    fd = open ("/dev/ttyUSB0", O_RDWR);  
    if (fd == -1)  
    {  
        perror ("serialport error\n");  
    }  
    else  
    {  
        printf ("open ");  
        printf ("%s", ttyname (fd));  
        printf (" succesfully\n");  
    }  

    saio.sa_handler = signal_handler_IO;  
    sigemptyset (&saio.sa_mask);  
    saio.sa_flags = 0;  
    saio.sa_restorer = NULL;  
    sigaction (SIGIO, &saio, NULL);  

    //allow the process to receive SIGIO  
    fcntl (fd, F_SETOWN, getpid ());  
    //make the file descriptor asynchronous  
    fcntl (fd, F_SETFL, FASYNC);  

    set_speed (fd, 115200);  
    if (set_Parity (fd, 8, 1, ‘N‘) == FALSE)  
    {  
        printf ("Set Parity Error\n");  
        exit (0);  
    }  

    char str[] = "1234567890123456789012345678901234567890";
    int n= write(fd,str,strlen(str));  
    printf("字符串实际长度%zd \n", strlen(str));
    printf("成功写入%d \n", n);

    char buf[255];  
    while (STOP == 0)  
    {  
        usleep (100000);  
        /* after receving SIGIO ,wait_flag = FALSE,input is availabe and can be read */  
        if (wait_flag == 0)  
        {  
            memset (buf, 0, sizeof(buf));  
            res = read (fd, buf, 255);  
            printf ("nread=%d,%s\n", res, buf);  
            //    if (res ==1)  
            //      STOP = 1;       /*stop loop if only a CR was input */  
            wait_flag = flag; /*wait for new input */  
        }  
    }  

    close (fd);  
    return 0;  
}
[email protected]:/tmp/serial# gcc -Wall main.c && ./a.out   
open /dev/ttyUSB0 succesfully
字符串实际长度40 
成功写入40 
received SIGIO signale.
received SIGIO signale.
nread=32,12345678901234567890123456789012
received SIGIO signale.
nread=8,34567890
^C
[email protected]:/tmp/serial#



3, Linux 下打开串口设备,读写程序

[email protected]:/tmp/serial# cat main.c 
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<sys/signal.h>  
#include<fcntl.h>  
#include<termios.h>  
#include<errno.h>  

#define FALSE -1  
#define TRUE 0  
#define flag 1  
#define noflag 0  

int wait_flag = noflag;  
int STOP = 0;  
int res;  

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, };  
void set_speed (int fd, int speed)  
{  
    int i;  
    int status;  
    struct termios Opt;  
    tcgetattr (fd, &Opt);  
    for (i = 0; i < sizeof (speed_arr) / sizeof (int); i++)  
    {  
        if (speed == name_arr[i])  
        {  
            tcflush (fd, TCIOFLUSH);  
            cfsetispeed (&Opt, speed_arr[i]);  
            cfsetospeed (&Opt, speed_arr[i]);  
            status = tcsetattr (fd, TCSANOW, &Opt);  
            if (status != 0)  
            {  
                perror ("tcsetattr fd1");  
                return;  
            }  
            tcflush (fd, TCIOFLUSH);  
        }  
    }  
}  

int set_Parity (int fd, int databits, int stopbits, int parity)  
{  
    struct termios options;  
    if (tcgetattr (fd, &options) != 0)  
    {  
        perror ("SetupSerial 1");  
        return (FALSE);  
    }  
    options.c_cflag &= ~CSIZE;  
    switch (databits)  
    {  
        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;   /* Clear parity enable */  
            options.c_iflag &= ~INPCK;    /* Enable parity checking */  
            break;  
        case ‘o‘:  
        case ‘O‘:  
            options.c_cflag |= (PARODD | PARENB);  
            options.c_iflag |= INPCK; /* Disnable parity checking */  
            break;  
        case ‘e‘:  
        case ‘E‘:  
            options.c_cflag |= PARENB;    /* Enable parity */  
            options.c_cflag &= ~PARODD;  
            options.c_iflag |= INPCK; /* Disnable parity checking */  
            break;  
        case ‘S‘:  
        case ‘s‘:           /*as no parity */  
            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);  
    }  
    /* Set input parity option */  
    if (parity != ‘n‘)  
        options.c_iflag |= INPCK;  
    tcflush (fd, TCIFLUSH);  
    options.c_cc[VTIME] = 150;  
    options.c_cc[VMIN] = 0;   /* Update the options and do it NOW */  
    if (tcsetattr (fd, TCSANOW, &options) != 0)  
    {  
        perror ("SetupSerial 3");  
        return (FALSE);  
    }  
    return (TRUE);  
}  

void signal_handler_IO (int status)  
{  
    printf ("received SIGIO signale.\n");  
    wait_flag = noflag;  
}  

int main ()  
{  
    int fd;  
    fd = open ("/dev/ttyUSB0", O_RDWR);  
    if (fd == -1)  
    {  
        perror ("serialport error\n");  
    }  
    else  
    {  
        printf ("open ");  
        printf ("%s", ttyname (fd));  
        printf (" succesfully\n");  
    }  

    set_speed (fd, 115200);  
    if (set_Parity (fd, 8, 1, ‘N‘) == FALSE)  
    {  
        printf ("Set Parity Error\n");  
        exit (0);  
    }  


    char str[] = "1234567890123456789012345678901234567890";
    int n= write(fd,str,strlen(str));  
    printf("字符串实际长度%zd \n", strlen(str));
    printf("成功写入%d \n", n);

    char buf[255];  
    fd_set rd;  
    int nread = 0;  
    while(1)  
    {  
        FD_ZERO(&rd);  
        FD_SET(fd, &rd);  
        while(FD_ISSET(fd, &rd))  
        {  
            if(select(fd+1, &rd, NULL,NULL,NULL) < 0)  
            {  
                perror("select error\n");  
            }  
            else  
            {  
                while((nread = read(fd, buf, sizeof(buf))) > 0)  
                {  
                    printf("nread= %02d,%s\n",nread, buf);  
                    memset(buf, 0 , sizeof(buf));  
                }  
            }  
        }  
    }  
    close (fd);  
    return 0;  
}
[email protected]:/tmp/serial# gcc -Wall main.c && ./a.out   
open /dev/ttyUSB0 succesfully
字符串实际长度40 
成功写入40 
nread= 32,12345678901234567890123456789012
nread= 08,34567890




本文出自 “魂斗罗” 博客,请务必保留此出处http://990487026.blog.51cto.com/10133282/1901695

以上是关于Linux C 配置串口的主要内容,如果未能解决你的问题,请参考以下文章

Linux下如何测试及使用USB转串口线

linux串口编程(c)

Linux C Serial串口编程

如何配置使用串口设备登录linux终端Linux Serial Console HOWTO

Linux 查看串口配置 去除回显

在linux使用命令配置串口