Bootstrap

树莓派 Linux 下的串口通讯 (C语言)

运行环境:Ubuntu14.04、树莓派3B+

功能:实现串口数据的收发

main.c文件

#include "com.h" 

#define BUFFER_SIZE 30      /*最大缓存区*/

char *pstr[]={"NO1\n","NO2\n","NO3\n","NO4\n"}; 
int main(int argc, char *argv[])
{
	int fd;
	int i;
	char read_buffer[BUFFER_SIZE];
	int read_buffer_size;

	//打开串口
	fd = open_port(0);
	//设置串口
    if(set_com_config(fd, 115200, 8, 'N', 1) < 0) /* 配置串口 */ 
    { 
        perror("set_com_config"); 
        return 1; 
    } 

	//发送数据
	do{
		for(i = 0; i < 4; i++)
		{
			write(fd, pstr[i], strlen(pstr[i]));
			sleep(1);
			do{
				memset(read_buffer,0, BUFFER_SIZE);
				read_buffer_size = read(fd, read_buffer, BUFFER_SIZE);				
			}while(!read_buffer_size);
			printf("read[%d][%s]\n",  read_buffer_size,read_buffer);
		}
	}while(1);
	close(fd);
	return 0;
}

com.c文件

#include "com.h"
/*
struct termios
{
    unsigned short c_iflag;   //输入模式标志
    unsigned short c_oflag;   //输出模式标志-
    unsigned short c_cflag;   //控制模式标志
    unsigned short c_lflag;   //本地模式标志-
    unsigned char c_line;     //线路规程-
    unsigned char c_cc[NCC];  //控制特性
    speed_t c_ispeed;         //输入速度-
    speed_t c_ospeed;         //输出速度-
}
*/

/****************************************/
/************打开串口函数****************/ 
/****************************************/
int open_port(int com_port) 
{
    int fd; 
    /* 使用普通串口 */ 
    //char *dev[] = {"/dev/ttySAC0","/dev/ttySAC1","/dev/ttySAC2","/dev/ttySAC3"};  
    /* 使用 USB 转串口 */ 
    char *dev[] = {"/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2"}; 

    printf("open dev [%s]\n",dev[com_port]);
    //O_NDELAY 同 O_NONBLOCK。
    fd = open(dev[com_port], O_RDWR|O_NOCTTY); 
    if (fd < 0) 
    { 
        perror("open serial port"); 
        return(-1); 
    } 

    //恢复串口为阻塞状态 
    //非阻塞:fcntl(fd,F_SETFL,FNDELAY)  
    //阻塞:fcntl(fd,F_SETFL,0) 
    if (fcntl(fd, F_SETFL, 0) < 0) 
    { 
        perror("fcntl F_SETFL\n"); 
    } 
    /*测试是否为终端设备*/ 
    if (isatty(STDIN_FILENO) == 0) 
    { 
        perror("standard input is not a terminal device"); 
    } 

    return fd; 
} 

/***********************************/
/************串口配置***************/
/***********************************/
int set_com_config(int fd,int baud_rate,int data_bits, char parity, int stop_bits) 
{ 
    struct termios opt;
    int speed;
    if(tcgetattr(fd, &opt) != 0)  
    { 
        perror("tcgetattr"); 
        return -1; 
    }
   
    /* 设置字符大小*/ 
    //opt = opt;
    //cfmakeraw(&opt);//配置为原始模式
    //opt.c_cflag &= ~CSIZE;//c_cflag 控制模式标志

    /*设置波特率*/ 
    switch (baud_rate) 
    { 
        case 2400:  speed = B2400;  break; 
        case 4800:  speed = B4800;  break; 
        case 9600:  speed = B9600;  break; 
        case 19200: speed = B19200; break; 
        case 38400: speed = B38400; break;
        default:    speed = B115200;break;   
    } 
    cfsetispeed(&opt, speed); 
    cfsetospeed(&opt, speed); 
    tcsetattr(fd,TCSANOW,&opt);

    opt.c_cflag &= ~CSIZE;

    /*设置数据位*/ 
    switch (data_bits) 
    { 
        case 7: {opt.c_cflag |= CS7;}break;//7个数据位  
        default:{opt.c_cflag |= CS8;}break;//8个数据位 
    } 
      
    /*设置奇偶校验位*/ 
    switch (parity) //N
    {   
        case 'n':case 'N': 
        { 
            opt.c_cflag &= ~PARENB;//校验位使能     
            opt.c_iflag &= ~INPCK; //奇偶校验使能  
        }break;
        case 'o':case 'O': 
        { 
            opt.c_cflag |= (PARODD | PARENB);//PARODD使用奇校验而不使用偶校验 
            opt.c_iflag |= INPCK;
        }break; 
        case 'e':case 'E': 
        { 
            opt.c_cflag |= PARENB;   
            opt.c_cflag &= ~PARODD;  
            opt.c_iflag |= INPCK;    
        }break; 
        case 's':case 'S': /*as no parity*/  
        { 
        	opt.c_cflag &= ~PARENB; 
        	opt.c_cflag &= ~CSTOPB; 
        }break;
        default:
        {
            opt.c_cflag &= ~PARENB;//校验位使能     
            opt.c_iflag &= ~INPCK; //奇偶校验使能          	
        }break; 
     }
           
     /*设置停止位*/ 
     switch (stop_bits)
     { 
        case 1: {opt.c_cflag &=  ~CSTOPB;} break;
        case 2: {opt.c_cflag |= CSTOPB;}   break;
        default:{opt.c_cflag &=  ~CSTOPB;} break; 
     } 
      
    /*处理未接收字符*/ 
    tcflush(fd, TCIFLUSH); 

    /*设置等待时间和最小接收字符*/ 
    opt.c_cc[VTIME]  = 11; 
    opt.c_cc[VMIN] = 0; 
      
    /*关闭串口回显*/
    opt.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH); 

    /*激活新配置*/ 
    if((tcsetattr(fd, TCSANOW, &opt)) != 0) 
    { 
        perror("tcsetattr"); 
        return -1; 
    }      
    return 0; 
}

com.h文件

#ifndef _COM_H_
#define _COM_H_

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

int set_com_config(int fd,int baud_rate,int data_bits, char parity, int stop_bits);
int open_port(int com_port);

#endif

在树莓派3B+中的编译结果和运行结果如下:

通过上位机发送一个字符串“test string”,树莓派会按顺序返回一个字符串"NO1"~"NO4"。

;