該驅動適用於採用linux和android系統平臺的C/C++開發。
用於配置串口相關參數:端口選擇、阻塞非阻塞、波特率、停止位、數據位、校驗位等。
注:需要系統開啓串口操作權限,否則配置失敗。
本驅動在MTK8735平臺上驗證測試,其它平臺修改串口端口名稱即可。
源代碼:
serial.h
//
// Created by taxiang&xuezi on 2018/4/2.
//
#ifndef NDKAPPECG_SERIAL_H
#define NDKAPPECG_SERIAL_H
#ifdef SERIAL_GLOBALS
#define SERIAL_EXT
#else
#define SERIAL_EXT extern
#endif
#define SERIAL_DBG 1
SERIAL_EXT s32 uart_open(s32 fd,s32 port,s8 block);
SERIAL_EXT s32 uart_set(s32 fd, s32 nSpeed, s32 nBits, s8 nEvent, s32 nStop);
#endif //NDKAPPECG_SERIAL_H
serial.c/serial.cpp
//
// Created by taxiang&xuezi on 2018/4/2.
//
#define SERIAL_GLOBALS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#ifdef SERIAL_DBG
#define SERIAL_PRINT0(X) printf(X);
#define SERIAL_PRINT1(X,A) printf (X,A);
#define SERIAL_PRINT2(X,A,B) printf (X,A,B);
#define SERIAL_PRINT3(X,A,B,C) printf (X,A,B,C);
#define SERIAL_PRINT4(X,A,B,C,D) printf (X,A,B,C,D);
#else
#define SERIAL_PRINT0(X)
#define SERIAL_PRINT1(X,A)
#define SERIAL_PRINT2(X,A,B)
#define SERIAL_PRINT3(X,A,B,C)
#define SERIAL_PRINT4(X,A,B,C)
#endif
/*******************************************************************************
* 函數名稱: s32 uart_open(s32 fd,s32 port,s8 block)
* 函數功能: 打開串口
* 輸入參數:
* 輸出參數:
* 返回值 :
*******************************************************************************/
s32 uart_open(s32 fd,s32 port,s8 block)
{
s8 *dev[]={"/dev/ttyMT0","/dev/ttyMT1","/dev/ttyMT2","/dev/ttyMT3"};
fd = open(dev[port], O_RDWR|O_NOCTTY|O_NONBLOCK);//nblock
if(fd == -1){
SERIAL_PRINT3("%s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
return -1;
}
if(block == 0){//nblock
// if(fcntl(fd, F_SETFL, FNDELAY)<0){
// SERIAL_PRINT3("%s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
// return -1;
// }
}else{//block
if(fcntl(fd, F_SETFL, 0)<0){
SERIAL_PRINT3("%s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
return -1;
}
}
// if(isatty(STDIN_FILENO)==0){
// SERIAL_PRINT3("%s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
// return -1;
// }
// SERIAL_PRINT0("uart open done\n");
return fd;
}
/*******************************************************************************
* 函數名稱: s32 uart_set(s32 fd, s32 nSpeed, s32 nBits, s8 nEvent, s32 nStop)
* 函數功能: 配置串口
* 輸入參數:
* 輸出參數:
* 返回值 :
*******************************************************************************/
s32 uart_set(s32 fd, s32 nSpeed, s32 nBits, s8 nEvent, s32 nStop)
{
struct termios newtio;
struct termios oldtio;
if(tcgetattr(fd,&oldtio) != 0){
SERIAL_PRINT3("%s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
return -1;
}
bzero(&newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL |CREAD;
/***********數據位選擇****************/
newtio.c_cflag &= ~CSIZE;
switch(nBits){
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
default :
newtio.c_cflag |= CS8;
break;
}
/***********校驗位選擇****************/
switch(nEvent){
case 'n':
case 'N':
newtio.c_cflag &= ~PARENB;
newtio.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= INPCK;
break;
case 'e':
case 'E':
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_iflag |= INPCK;
break;
case 's':
case 'S':
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~CSTOPB;
newtio.c_iflag |= INPCK;
default :
newtio.c_cflag &= ~PARENB;
newtio.c_iflag &= ~INPCK;
break;
}
/***********波特率選擇****************/
switch(nSpeed){
case 2400:
cfsetispeed(&newtio,B2400);
cfsetospeed(&newtio,B2400);
break;
case 4800:
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
case 57600:
cfsetispeed(&newtio,B57600);
cfsetospeed(&newtio,B57600);
break;
case 115200:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;
case 230400:
cfsetispeed(&newtio,B230400);
cfsetospeed(&newtio,B230400);
break;
case 460800:
cfsetispeed(&newtio,B460800);
cfsetospeed(&newtio,B460800);
break;
case 500000:
cfsetispeed(&newtio,B500000);
cfsetospeed(&newtio,B500000);
break;
case 576000:
cfsetispeed(&newtio,B576000);
cfsetospeed(&newtio,B576000);
break;
case 921600:
cfsetispeed(&newtio,B921600);
cfsetospeed(&newtio,B921600);
break;
case 2000000:
cfsetispeed(&newtio,B2000000);
cfsetospeed(&newtio,B2000000);
break;
default:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
/***********停止位選擇****************/
switch(nStop){
case 1:
newtio.c_cflag &= ~CSTOPB;
break;
case 2:
newtio.c_cflag |= CSTOPB;
break;
default:
newtio.c_cflag &= ~CSTOPB;
break;
}
//VTIME和VMIN僅在阻塞模式下有效
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio)) != 0){
SERIAL_PRINT3("%s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
return -1;
}
SERIAL_PRINT4("uart set done:%d %d %C %d\n",nSpeed,nBits,nEvent,nStop);
return 0;
}