嵌入式Linux串口編程簡介

簡介

嵌入式Linux下串口編程與Linux系統下的編程沒有什麼區別,系統API都是一樣的。嵌入式設備中串口編程是很常用的,比如會對接一些傳感器模塊,這些模塊大多是RS232或者RS485接口,對於軟件層面上來說,RS232與RS48區別不大。RS232與RS485在使用上的區別,RS232是全雙工的,只能對接一個設備串口設備。RS485是半雙工的總線協議,一般可以掛多個傳感器設備,半雙工的意思是同時只能有一個設備向串口發數據。

用到的API函數

函數 說明
open 打開設備,用於打開串口設備
fcntl 修改設備描述符屬性參數
isatty 檢測打開的描述符是否指向一個終端
tcgetattr 用來獲取串口終端參數
cfmakeraw 將終端設置爲原始模式,該模式下所有的輸入數據以字節爲單位被處理
tcflush 用於清空輸入、輸出緩衝區
tcsetattr 設置串口終端參數
read 讀取數據
write 寫數據
close 關閉串口設備

代碼

#include<termios.h>
#include "uart.h"

/***************************************
*name    : open_port
*功能描述: 打開串口
*入口參數: 串口號
*返 回 值: 成功返回文件描述符,失敗返回負值
*作    者: 
*修改時間:
***************************************/
int open_port(const char * com_port)
{
    int fd;

	if( com_port == NULL ){
        printf("the port name is null\n");
        return -1;
    }
    /*open port*/
    fd = open(com_port, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd < 0){
        fd = open(com_port, O_RDWR | O_NOCTTY | O_NDELAY);
        if(fd < 0){
            perror("open serial port");
            return -1;
        }
    }
    printf("open %s OK!\n", com_port);
    if(fcntl(fd, F_SETFL,0) < 0){
        perror("fcntl F_SETFL");
    }

    if(isatty(fd) == 0){
        perror("isatty is not a terminal device");
    }
    return fd;
}

/******************************
*name    : set_port
*功能描述: 設置串口參數
*入口參數: fd 文件描述符, baud_rate 波特率, data_bits 數據位,
*          parity 奇偶校驗, stop_bits 停止位
*			調用示例: set_port(fd, 115200, 8, 'N',1);
*返 回 值: 成功返回0,失敗返回-1
*作    者: 
*修改: 
******************************/
int set_port(int fd, int baud_rate,
             int data_bits, char parity, int stop_bits)
{
    struct termios new_cfg, old_cfg;
    int speed_arry[]= {B2400, B4800, B9600, B19200, B38400,B57600, B115200};
    int speed[]={2400,4800,9600,19200,38400,57600,115200};
    int i = 0;

    /*save and test the serial port*/
    if(tcgetattr(fd, &old_cfg) < 0){
        perror("tcgetattr");
        return -1;
    }
	
	if(fcntl(fd,F_SETFL,0) < 0)//恢復爲阻塞模式
	{
		perror("fcntl(CzjFd,F_SETFL,0)!");
	}

    new_cfg = old_cfg;
    cfmakeraw(&new_cfg);     //配置爲原來配置
    new_cfg.c_cflag &= ~ CSIZE;     //用數據位掩碼清空數據位的設置

    /*set baud_rate*/
    for(i = sizeof(speed_arry) / sizeof(speed_arry[0]); i > 0; i--)
    {
        if(baud_rate == speed[i]){
            cfsetispeed(&new_cfg,speed_arry[i]);
            cfsetospeed(&new_cfg,speed_arry[i]);
        }
    }

    switch(data_bits)    /*設置數據位*/
    {
        case 7:
                new_cfg.c_cflag |= CS7;
                break;

        default:
        case 8:
                new_cfg.c_cflag |= CS8;
                break;
    }

    switch(parity)
    {
        default:
        case 'N':
        case 'n':
        {
            new_cfg.c_cflag &= ~PARENB;     //清除校驗位
            new_cfg.c_iflag &= ~(ICRNL|INPCK|IXON|IXOFF);      //關閉奇偶校驗  關閉軟件流控
            
			break;
        }

        case 'o':
        case 'O':
        {
            new_cfg.c_cflag |= (PARODD | PARENB); //使用奇校驗不是用偶校驗
            new_cfg.c_iflag |= INPCK;
			break;
        }

        case 'e':
        case 'E':
        {
            new_cfg.c_cflag |= PARENB;
            new_cfg.c_cflag &= ~PARODD;     //使用偶校驗
			new_cfg.c_iflag |= INPCK;
			break;
        }

        case 's':
        case 'S':
        {
            new_cfg.c_cflag &= ~PARENB;
            new_cfg.c_cflag &= ~CSTOPB;
			break;
        }
    }
	
    new_cfg.c_iflag &= ~(ICRNL| IXON | IXOFF  );      //關閉奇偶校驗  關閉軟件流控
	new_cfg.c_oflag &= ~OPOST;

    switch(stop_bits)
    {
        default:
        case 1:
        {
            new_cfg.c_cflag &= ~CSTOPB;
            new_cfg.c_cflag &= ~CRTSCTS;   //禁用硬件流控
            //new_cfg.c_cflag |= CRTSCTS;    //啓用硬件流控
			break;
        }
        case 2:
        {
            new_cfg.c_cflag |= CSTOPB;
			break;
		}
    }

    /*set wait time*/
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN]  = 1;

    tcflush(fd, TCIFLUSH);   //處理未接收字符
	if((tcsetattr(fd, TCSANOW, &new_cfg)) < 0)
    {
        perror("tcsetattr");
        return -1;
    }

    return 0;
}


調用測試代碼:

#include "uart.h"
#include <stdio.h>
#include <unistd.h>


int main()
{
	int fd = open_port("/dev/ttyS1");
	if ( fd < 0 )
	{
		perror("open port");
		return -1;
	}
	
	set_port(fd, 115200, 8, 'N',1);
	
	char readBuf[32] ={0};
	const char *pstr="hello world";
	write(fd, pstr, strlen(pstr)+1);
	
	read(fd, readBuf, sizeof(readBuf));
	
	close(fd);
}

微信公衆號:
微信公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章