Linux下串口编程(二)

相关内容:

  Linux下串口编程(一)

  Linux下串口编程(二)

1、dev_uart.c

#include "dev_uart.h"

/*******************************************************************  
*名称:             dev_uart_open 
*功能:             打开串口并返回串口设备文件描述  
*入口参数:         fd      文件描述符                    port    串口号(ttyS0,ttyS1,ttyS2)  
*出口参数:正确返回为1,错误返回为0  
*******************************************************************/    
int 
dev_uart_open(int fd,char *port)
{        
    fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);        
    if (fd<0)        
    {            
        printf("******Can't Open uart*****
");           
        return -1;        
    }        
    //恢复串口为阻塞状态                                      
    if(fcntl(fd, F_SETFL, 0) < 0)        
    {            
        printf("******fcntl fail*****
");           
        return -1;       
    }             
    else        
    {            
        printf("*****fcntl=%d******
",fcntl(fd, F_SETFL,0));        
    }        
    //测试是否为终端设备            
    if(0 == isatty(STDIN_FILENO))        
    {            
        printf("*****standard input is not a terminal device*****
");            
        return -1;        
    }        
    else        
    {           
        printf("*****isatty success!*******
");        
    }                      
    printf("******fd->open=%d******
",fd);        
    return fd;    
} 



void dev_uart_close(int fd)    
{    
    close(fd);    
} 



int
dev_uart_set(int fd,int uart_speed,int flow_ctrl,int databits,int stopbits,int parity)    
{              
    int   i;                
    int   speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};        
    int   name_arr[] = {115200,  19200,  9600,  4800,  2400,  1200,  300};                     
    struct termios options;               
    /*  tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数还可以测试配置是否正确,        该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1.  */        
    if( tcgetattr( fd,&options)  !=  0)        
    {            
        printf("tcgetattr err");                
        return -1;         
    }              
    //设置串口输入波特率和输出波特率        
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)        
    {            
        if  (uart_speed == name_arr[i])            
        {                             
            cfsetispeed(&options, speed_arr[i]);                 
            cfsetospeed(&options, speed_arr[i]);              
        }        
    }                    
    //修改控制模式,保证程序不会占用串口        
    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:                        
            printf("Unsupported data size
");                     
            return -1;         
    }        
    //设置校验位        
    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:                       
            printf("Unsupported parity
");                         
            return -1;         
        }         
    // 设置停止位         
    switch (stopbits)        
    {              
        case 1:                        
            options.c_cflag &= ~CSTOPB; break;             
        case 2:                        
            options.c_cflag |= CSTOPB; break;            
        default:                              
            printf("Unsupported stop bits
");                            
            return -1;        
    }               
    //修改输出模式,原始数据输出        
    options.c_oflag &= ~OPOST;              
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);        
    //options.c_lflag &= ~(ISIG | ICANON);               //设置等待时间和最小接收字符        
    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)          
    {            
        printf("com set error!
");              
        return -1;         
    }        
    return 1;     
}    


int
dev_uart_read(int fd, char *rcv_buf,int data_len)    
{        
    int len;
    len = read(fd,rcv_buf,data_len);         
    return len; 
    
} 




int
dev_uart_write(int fd, char *send_buf,int data_len)    
{        
    int len = 0;               
    len = write(fd,send_buf,data_len);        
    return len;            
               
}    

2、dev_uart.h

#ifndef  _DEV_UART_H
#define  _DEV_UART_H 
//串口相关的头文件    
#include<stdio.h>      /*标准输入输出定义*/    
#include<stdlib.h>     /*标准函数库定义*/    
#include<unistd.h>     /*Unix 标准函数定义*/    
#include<sys/types.h>     
#include<sys/stat.h>       
#include<fcntl.h>      /*文件控制定义*/    
#include<termios.h>    /*PPSIX 终端控制定义*/    
#include<errno.h>      /*错误号定义*/    
#include<string.h>              //宏定义




int 
dev_uart_open(int fd,char *port);

void 
dev_uart_close(int fd) ;

int
dev_uart_set(int fd,int uart_speed,int flow_ctrl,int databits,int stopbits,int parity);


int
dev_uart_read(int fd, char *rcv_buf,int data_len);


int
dev_uart_write(int fd, char *send_buf,int data_len);



#endif
View Code

2、uart_test.c  串口测试代码

#include "pthread.h"
#include "dev_uart.h"


#define TIME_DIF    2    //2秒
#define uart_buf_SIZE 200    //接收缓冲区数据长度


char buf123[12]         ={0x00,0x10,0x00,0x24,0x06,0x00,0x01,0x00,0x01,0x00,0x01,0x0D};    



static char uart_buf[uart_buf_SIZE];      //接收缓冲区
static volatile char  uart_cnt = 0;                 //接收缓冲计数
static volatile int flag = 1;            
static volatile int fd = -1;



int
uart_read_proc(char *buf,unsigned int len)
{
    int cnt;
        
    memcpy(uart_buf+uart_cnt, buf, len);
    uart_cnt += len;
            
    if (uart_cnt == 100)
    {
         for(cnt = 0;cnt<uart_cnt;cnt++)
            {
                printf(" %02x",uart_buf[cnt]);
                if(cnt%20 == 19)
                    printf("
");
            }
            printf("
");

            memset(uart_buf , 0,sizeof(uart_buf));
            uart_cnt = 0;
            flag = 1;    
            
            return 1;
                
        }
    
}




int
uart_read(int fd)    
{
    char buf[200];
    int iRet;
    unsigned int len;
    int i = 30;
    
    memset(uart_buf , 0,sizeof(uart_buf));
    uart_cnt = 0;
    flag = -1;

    
    while(i > 0)
    {
        i--;
        if(flag == -1)
        {            
            memset(buf, 0, sizeof(buf));
            len = dev_uart_read(fd, buf, 30);
            if(len > 0)
            {
                iRet = uart_read_proc(buf,len);
            }
            return iRet;
        }
        else 
            break;
    }
}


int
uart_write(int fd)
{
    int len = 0;

    len = dev_uart_write(fd,buf123, sizeof(buf123));
    if(len <= 0)
    {
        printf("*******hal_uart_write err*******
");
        return -1;
    }
    return len;
        
}


/****************************************************************************
 * @brief      
 ***************************************************************************/
int main(void)
{
    static unsigned int time_second = 0;
        char *dev = "/dev/ttyPS1";
        int iRet = 0;
    
        printf("Line %d
", __LINE__);
    
      fd = dev_uart_open(fd,dev);

        iRet = dev_uart_set(fd,115200,0,8,1,'N');    
    
        while(1)
        {
            usleep(200000);//延时200ms
            time_t time_now = time((time_t *)NULL);
            //-->定时查询串口数据
            if ((time_now - time_second) >= TIME_DIF)
            {
                time_second = time_now;
                uart_write(fd);        
                uart_read(fd);        
            }
        }
    
    return 0;
}
View Code

3、Makefile

CROSS    =    
LIB_PWD = $(shell pwd)
TARGET_BIN = test



CPP    = $(CROSS)g++ -std=c++11
CC    = $(CROSS)gcc
LD    = $(CROSS)ld


CFLAGS  += -I$(shell pwd)

CFLAGS  += -Wall -g  
LDFLAGS += -lpthread
        
        
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
%.o: %.c
    $(CPP) $(CFLAGS) -o $@ -c $< 
    
all:$(OBJS)
    $(CPP) -o $(TARGET_BIN)  $(OBJS) $(LDFLAGS)
    find . -name "*.o"  | xargs rm -f  
    
clean:
    find . -name "*.o"  | xargs rm -f 
View Code

参考文档: POSIX操作系统的串行编程指南

      Linux 下串口编程入门

原文地址:https://www.cnblogs.com/listxue/p/13377161.html