WhyCan Forum

人过留名,雁过留声,感谢各位朋友不离不弃地支持。 QQ: 516333132, 微信: whycan_cn (哇酷网/挖坑网/填坑网) admin@whycan.cn

您尚未登录。

#1 2019-11-28 19:28:46

并夕夕
会员
注册时间: 2019-11-24
累计积分: 25

分享一个稳定的 ndk jni 读写串口的代码

serial.cpp

//包含头文件
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef _WIN32 
#include <sys/ioctl.h>
#include <unistd.h>
#include <termios.h>
#else
#include <io.h>
#pragma warning (disable:4996)
#endif

#include <errno.h>
#include <string.h>

#include <time.h>

int			fd_ = -1;


extern "C" {
	int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop, int min_btye);
}

long long  getMilisec()
{
#ifndef _WIN32 
	struct timeval now;
	gettimeofday(&now, NULL);
	long long  t_mili = ((long long)now.tv_sec) * 1000 + now.tv_usec / 1000;
	return t_mili;
#else
	return 0;
#endif
}

//打印
//#include "android/log.h"
//static const char *TAG = "HelloWorldScene";
//#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
//#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
//#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)



extern "C"  {

	bool Serial_Open()
	{
		if (fd_ > 0)//already open
			return true;

#ifndef _WIN32
		//char *dev[] = { "/dev/ttySAC0", "/dev/ttySAC1", "/dev/ttySAC2", "/dev/ttySAC3" };
		//long vdisable;
		fd_ = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);
		if (fd_ == -1) {
			return false;
		}

		//LOGE("Open Serial Port %s\n",dev[comport]);
		//恢复串口为阻塞状态
		if (fcntl(fd_, F_SETFL, 0) < 0) {
			return false;
		}

		/*测试是否为终端设备*/
		if (isatty(STDIN_FILENO) == 0) {
			//LOGE("standard input is not a terminal device\n");
		}

		set_opt(fd_, 9600, 8, 'N', 1, 200);

#else
		fd_ = open("/dev/ttyS4", O_RDWR);
		if (fd_ == -1) {
			return false;
		}
#endif

		return fd_ > 0;
	}

	void Serial_Close()
	{
		if (fd_ > 0)
		{
			close(fd_);
			fd_ = -1;
		}
	}

	int Serial_SendData(const unsigned char* data, int size)
	{
		if (fd_ < 0)//not open
			return -1;

		int ret = write(fd_, data, size);
		return ret;
	}

	int Serial_RecvData(unsigned char* buff, int len)
	{
		if (fd_ < 0)//not open
			return -1;

		memset(buff, 0, len);
		int readSize = read(fd_, buff, len);

		return readSize;
	}

	/*****************************
	 * 功能:设置串口函数
	 * 入口:(fd,波特率,数据位,奇偶校验,停止位)
	 *****************************/

	int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop, int min_btye)
	{
#ifndef _WIN32
		struct termios newtio, oldtio;
		/*保存测试现有串口参数设置,在这里如果串口号出错,会有相关的出错信息*/
		if (tcgetattr(fd, &oldtio) != 0) {
			// LOGE("SetupSerial 1");
			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;
		}

		/*设置奇偶校验位*/
		switch (nEvent) {
		case 'O': //奇数
			newtio.c_cflag |= PARENB;
			newtio.c_cflag |= PARODD;
			newtio.c_iflag |= (INPCK | ISTRIP);
			break;
		case 'E': //偶数
			newtio.c_iflag |= (INPCK | ISTRIP);
			newtio.c_cflag |= PARENB;
			newtio.c_cflag &= ~PARODD;

			break;
		case 'N': //无奇偶校验位
			newtio.c_cflag &= ~PARENB;
			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 19200:
			cfsetispeed(&newtio, B19200);
			cfsetospeed(&newtio, B19200);
			break;
		case 115200:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		case 460800:
			cfsetispeed(&newtio, B460800);
			cfsetospeed(&newtio, B460800);
			break;
		default:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		}

		/*设置停止位*/
		if (nStop == 1) {
			newtio.c_cflag &= ~CSTOPB;
		}
		else if (nStop == 2) {
			newtio.c_cflag |= CSTOPB;
		}

		/*设置等待时间和最小接收字符*/
		newtio.c_cc[VTIME] = 1;
		newtio.c_cc[VMIN] = min_btye;

		/*处理未接收字符*/
		tcflush(fd, TCIFLUSH);
		/*激活新配置*/
		if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
			// LOGE("COM set error\n");
			return -1;
		}
#endif
		return 0;
	}
}

Android.mk

#
# Copyright 2009 Cedric Priscal
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
# http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License. 
#

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

NDK_TOOLCHAIN_VERSION := 4.9

LOCAL_C_INCLUDES := C:/android-ndk-r15b/sources/cxx-stl/gnu-libstdc++/4.9/include
LOCAL_C_INCLUDES +=C:\android-ndk-r15b\sources\cxx-stl\gnu-libstdc++\4.9\libs\armeabi\include

TARGET_PLATFORM := android-18
LOCAL_MODULE    := serialport
LOCAL_SRC_FILES := serial.cpp
LOCAL_LDLIBS    := -llog

LOCAL_CPPFLAGS := -std=c++11 -D __cplusplus=201103L

APP_STL := gnustl_shared

APP_CPPFLAGS := -std=c++11 -frtti -fexceptions
APP_CPPFLAGS += -std=gun++11 -lpthread

include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_ABI := armeabi armeabi-v7a x86

离线

#2 2019-11-28 19:55:28

并夕夕
会员
注册时间: 2019-11-24
累计积分: 25

Re: 分享一个稳定的 ndk jni 读写串口的代码

离线

#3 2019-11-29 11:39:11

JasonWoo
会员
注册时间: 2019-06-04
累计积分: 11

Re: 分享一个稳定的 ndk jni 读写串口的代码

谢谢分享

离线

页脚