ARM Tiny210v2开发板Android系统读写串口设备
2013-10-03 10:11
537 查看
之前买了块Tiny210v2开发板,需要在Android系统下读写串口,于是自己在JNI层封装了下串口读写,PS:友善官方也提供了底层硬件的读写库,这个纯粹是自己写了玩的。
代码主要分为5个部分,ReadWriteSerialPortLib.c+stty.h+Android.mk+accessarmborddevlib.java+MainActivity.java
stty.h主要是对于串口设备/dev/s3c2410_serial3的读写,参考常见的linux系统串口读写代码编写
ReadWriteSerialPortLib.c是JNI的C语言层封装代码
Android.mk是Android NDK编译脚本
accessarmborddevlib.java是JNI的Java语言层封装代码
MainActivity.java是Android最上层的调用代码
stty.h代码如下:
ReadWriteSerialPortLib.c代码如下:
Android.mk代码如下:
accessarmborddevlib.java代码如下:
MainActivity.java核心代码如下:
要注意修改串口设备/dev/s3c2410_serial3的读写权限,至于如何修改可以参考这篇/article/9285337.html
代码主要分为5个部分,ReadWriteSerialPortLib.c+stty.h+Android.mk+accessarmborddevlib.java+MainActivity.java
stty.h主要是对于串口设备/dev/s3c2410_serial3的读写,参考常见的linux系统串口读写代码编写
ReadWriteSerialPortLib.c是JNI的C语言层封装代码
Android.mk是Android NDK编译脚本
accessarmborddevlib.java是JNI的Java语言层封装代码
MainActivity.java是Android最上层的调用代码
stty.h代码如下:
//filename:stty.h #ifndef __STTY_H__ #define __STTY_H__ //包含头文件 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <errno.h> #include <pthread.h> #include <sys/ioctl.h> #include<string.h> #include<time.h> #define DEVPATHLEN 40 // 串口设备信息结构 typedef struct tty_info_t { int fd; // 串口设备ID pthread_mutex_t mt; // 线程同步互斥对象 char name[DEVPATHLEN]; // 串口设备名称,例:"/dev/ttyS0" struct termios ntm; // 新的串口设备选项 struct termios otm; // 旧的串口设备选项 } TTY_INFO; // 串口操作函数 TTY_INFO *readyTTY(char* devname); int setTTYSpeed(TTY_INFO *ptty, int speed); int setTTYParity(TTY_INFO *ptty,int databits,char parity,int stopbits); int cleanTTY(TTY_INFO *ptty); int sendnTTY(TTY_INFO *ptty,char *pbuf,int size); int recvnTTY(TTY_INFO *ptty,char *pbuf,int size); int lockTTY(TTY_INFO *ptty); int unlockTTY(TTY_INFO *ptty); void thread_receive(TTY_INFO *ptty); void thread_send(TTY_INFO *ptty); #endif /* 从头文件中的函数定义不难看出,函数的功能,使用过程如下: (1) 打开串口设备,调用函数setTTYSpeed(); (2) 设置串口读写的波特率,调用函数setTTYSpeed(); (3) 设置串口的属性,包括停止位、校验位、数据位等,调用函数setTTYParity(); (4) 向串口写入数据,调用函数sendnTTY(); (5) 从串口读出数据,调用函数recvnTTY(); (6) 操作完成后,需要调用函数cleanTTY()来释放申请的串口信息接口; 其中,lockTTY()和unlockTTY()是为了能够在多线程中使用。在读写操作的前后,需要锁定和释放串口资源。 具体的使用方法,在代码实现的原文件中,main()函数中进行了演示。下面就是源代码文件: */ // 初始化串口设备并进行原有设置的保存 TTY_INFO *readyTTY(char* DevName) { TTY_INFO *ptty; ptty = (TTY_INFO *)malloc(sizeof(TTY_INFO)); if(ptty == NULL) return NULL; memset(ptty,0,sizeof(TTY_INFO)); pthread_mutex_init(&ptty->mt,NULL); memset(ptty->name,0,DEVPATHLEN); strcat(ptty->name,"/dev/"); strcat(ptty->name,DevName); //填充字符串数组内存 // 打开并且设置串口 ptty->fd = open(ptty->name, O_RDWR | O_NOCTTY |O_NDELAY); if (ptty->fd <0) { free(ptty); return NULL; } // 取得并且保存原来的设置 tcgetattr(ptty->fd,&ptty->otm); return ptty; } // 清理串口设备资源 int cleanTTY(TTY_INFO *ptty) { // // 关闭打开的串口设备 if(ptty->fd>0) { tcsetattr(ptty->fd,TCSANOW,&ptty->otm); close(ptty->fd); ptty->fd = -1; free(ptty); ptty = NULL; } return 0; } // 设置串口通信速率 // ptty 参数类型(TTY_INFO *),已经初始化的串口设备信息结构指针 // speed 参数类型(int),用来设置串口的波特率 // return 返回值类型(int),函数执行成功返回零值,否则返回大于零的值 int setTTYSpeed(TTY_INFO *ptty, int speed) { int i; // // 进行新的串口设置,数据位为8位 bzero(&ptty->ntm, sizeof(ptty->ntm)); tcgetattr(ptty->fd,&ptty->ntm); ptty->ntm.c_cflag = /*CS8 |*/ CLOCAL | CREAD; switch(speed) { case 300: ptty->ntm.c_cflag |= B300; break; case 1200: ptty->ntm.c_cflag |= B1200; break; case 2400: ptty->ntm.c_cflag |= B2400; break; case 4800: ptty->ntm.c_cflag |= B4800; break; case 9600: ptty->ntm.c_cflag |= B9600; break; case 19200: ptty->ntm.c_cflag |= B19200; break; case 38400: ptty->ntm.c_cflag |= B38400; break; case 115200: ptty->ntm.c_cflag |= B115200; break; } ptty->ntm.c_iflag = IGNPAR; ptty->ntm.c_oflag = 0; tcflush(ptty->fd, TCIFLUSH); tcsetattr(ptty->fd,TCSANOW,&ptty->ntm); return 0; } // 设置串口数据位,停止位和效验位 // ptty 参数类型(TTY_INFO *),已经初始化的串口设备信息结构指针 // databits 参数类型(int), 数据位,取值为7或者8 // stopbits 参数类型(int),停止位,取值为1或者2 // parity 参数类型(int),效验类型 取值为N,E,O,,S // return 返回值类型(int),函数执行成功返回零值,否则返回大于零的值 int setTTYParity(TTY_INFO *ptty,int databits,char parity,int stopbits) { // 取得串口设置 if( tcgetattr(ptty->fd,&ptty->ntm) != 0) { printf("SetupSerial [%s]\n",ptty->name); return 1; } bzero(&ptty->ntm, sizeof(ptty->ntm)); ptty->ntm.c_cflag = CS8 | CLOCAL | CREAD; ptty->ntm.c_iflag = IGNPAR; ptty->ntm.c_oflag = 0; // 设置串口的各种参数 ptty->ntm.c_cflag &= ~CSIZE; switch (databits) { //设置数据位数 case 7: ptty->ntm.c_cflag |= CS7; break; case 8: ptty->ntm.c_cflag |= CS8; break; default: printf("Unsupported data size\n"); return 5; } switch (parity) { // 设置奇偶校验位数 case 'n': case 'N': ptty->ntm.c_cflag &= ~PARENB; /* Clear parity enable */ ptty->ntm.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': ptty->ntm.c_cflag |= (PARODD|PARENB); /* 设置为奇效验*/ ptty->ntm.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': ptty->ntm.c_cflag |= PARENB; /* Enable parity */ ptty->ntm.c_cflag &= ~PARODD; /* 转换为偶效验*/ ptty->ntm.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ ptty->ntm.c_cflag &= ~PARENB; ptty->ntm.c_cflag &= ~CSTOPB; break; default: printf("Unsupported parity\n"); return 2; } // 设置停止位 switch (stopbits) { case 1: ptty->ntm.c_cflag &= ~CSTOPB; break; case 2: ptty->ntm.c_cflag |= CSTOPB; break; default: printf("Unsupported stop bits\n"); return 3; } ptty->ntm.c_lflag = 0; ptty->ntm.c_cc[VTIME] = 0; // inter-character timer unused ptty->ntm.c_cc[VMIN] = 1; // blocking read until 1 chars received tcflush(ptty->fd, TCIFLUSH); if (tcsetattr(ptty->fd,TCSANOW,&ptty->ntm) != 0) { printf("SetupSerial \n"); return 4; } return 0; } int recvnTTY(TTY_INFO *ptty,char *pbuf,int size) { int ret,left,bytes; left = size; while(left>0) { ret = 0; bytes = 0; pthread_mutex_lock(&ptty->mt); ioctl(ptty->fd, FIONREAD, &bytes); if(bytes>0) { ret = read(ptty->fd,pbuf,left); } pthread_mutex_unlock(&ptty->mt); if(ret >0) { left -= ret; pbuf += ret; } usleep(100); } return size - left; } int sendnTTY(TTY_INFO *ptty,char *pbuf,int size) { int ret,nleft; char *ptmp; ret = 0; nleft = size; ptmp = pbuf; while(nleft>0) { pthread_mutex_lock(&ptty->mt); ret = write(ptty->fd,ptmp,nleft); pthread_mutex_unlock(&ptty->mt); if(ret >0) { nleft -= ret; ptmp += ret; } //usleep(100); } return size - nleft; } int lockTTY(TTY_INFO *ptty) { if(ptty->fd < 0) { return 1; } return flock(ptty->fd,LOCK_EX); } int unlockTTY(TTY_INFO *ptty) { if(ptty->fd < 0) { return 1; } return flock(ptty->fd,LOCK_UN); } //多线程读写相关函数 //ptty作为参数传入两个线程处理函数 //data->8 bits void thread_receive(TTY_INFO *ptty) { int nbyte,idx=0; unsigned char data[16]; while(1) { nbyte = recvnTTY(ptty,data,1); printf("Receive Data %d:%02X\n",idx++,data[0]); } pthread_exit(0); } void thread_send(TTY_INFO *ptty) { unsigned char data; while(1) { //printf("Please input the data(HEX:such as 0x00) you want to send:\n"); //scanf("%x",&data) ; //sendnTTY(ptty,&data,1); } pthread_exit(0); }
ReadWriteSerialPortLib.c代码如下:
// Serial Port接口 #include <string.h> #include <jni.h> #include <stdio.h> #include <stdlib.h> #include "stty.h" #include <android/log.h> #define TAG "ReadWriteSerialPortLib" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) //#define DEVNAMELEN 35 TTY_INFO *ptty; jint Java_org_echo_prox_accessarmborddevlib_openserialdev(JNIEnv* env, jobject thiz, jstring devname, jint baudrate) { const jbyte *DevNameStr; char DevNameStrArray[DEVPATHLEN-5]; pthread_t id_rec,id_send; int ret; DevNameStr = (*env)->GetStringUTFChars(env, devname, NULL); if (DevNameStr == NULL) { return -1; } memset(DevNameStrArray,0,DEVPATHLEN-5); strcpy(DevNameStrArray,DevNameStr); LOGE("devname:%s",DevNameStrArray); ptty = readyTTY(DevNameStrArray); if(ptty == NULL) { LOGE("readyTTY error"); return -1; } lockTTY(ptty); if(setTTYSpeed(ptty,baudrate)>0) { LOGE("setTTYSpeed() error"); return -1; } if(setTTYParity(ptty,8,'N',1)>0) { LOGE("setTTYParity() error"); return -1; } LOGE("readyTTY OK"); return 0; } jint Java_org_echo_prox_accessarmborddevlib_writedata(JNIEnv* env, jobject thiz, jbyteArray dataarray, jint datalen) { jbyte * dataarraybuf = (jbyte*)(*env)->GetByteArrayElements(env, dataarray, 0); int ret=-1; ret=sendnTTY(ptty,dataarraybuf,datalen); (*env)->ReleaseByteArrayElements(env, dataarray, dataarraybuf, 0); return ret; } jint Java_org_echo_prox_accessarmborddevlib_closeserialdev(JNIEnv* env, jobject thiz) { unlockTTY(ptty); cleanTTY(ptty); LOGE("cleanTTY OK"); return 0; }
Android.mk代码如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS += -llog LOCAL_MODULE := AccessARMBordDevLib LOCAL_SRC_FILES := ReadWriteSerialPortLib.c include $(BUILD_SHARED_LIBRARY)
accessarmborddevlib.java代码如下:
package org.echo.prox; import android.util.Log; public class accessarmborddevlib { static public native int openserialdev(String DevName,int BaudRate); static public native int writedata(byte[] SendDataArray,int SendDataLen); static public native int closeserialdev(); static { try { System.loadLibrary("AccessARMBordDevLib"); } catch (UnsatisfiedLinkError e) { Log.d("readwriteserialportlib","ReadWriteSerialPortLib library not found!"); } } }
MainActivity.java核心代码如下:
org.echo.prox.accessarmborddevlib AccessDev =new org.echo.prox.accessarmborddevlib(); AccessDev.openserialdev("s3c2410_serial3", 9600); byte[] data=new byte[4]; data[0]='p'; data[1]='r'; data[2]='o'; data[3]='x'; AccessDev.writedata(data, data.length); AccessDev.closeserialdev();
要注意修改串口设备/dev/s3c2410_serial3的读写权限,至于如何修改可以参考这篇/article/9285337.html
相关文章推荐
- ARM 开发板嵌入式linux系统与主机PC通过串口传输文件
- 基于tiny210v2开发板下搭建网络文件系统
- amlogic平台android 系统linux内核中添加i2c设备实现i2c的读写
- Android系统访问串口设备
- OK6410开发板android系统boot编译—/usr/local/arm/4.3.2/bin/arm-none-linux-gnueabi-gcc:命令未找到
- Android系统访问串口设备
- Android系统访问串口设备
- 210开发板Android系统串口程序
- Android app如何正确读写系统sys设备节点
- FriendlyARM Tiny210v2 SPI接口Android平台测试
- Android app如何正确读写系统sys设备节点
- ARM 开发板嵌入式linux系统与主机PC通过串口传输文件
- Android系统访问串口设备
- Android开发板串口读写操作
- Android系统访问串口设备
- FriendlyARM Tiny 4412开发板烧写Linux系统步骤
- 基于Ubuntu14.04环境下编译qt-everywhere-opensource-src-5.6.1配置qt creater 的arm编译器环境并移植到tiny210v2开发板上
- 2H开发板启动 android 4.0.3 系统
- Android平台读写i2c设备开发笔记一
- Android开发 获取系统已连接蓝牙设备