• Android系统访问串口设备


    在常见的嵌入式外设中,串口通信是经常使用的一种通信机制,本篇文章给你带来,如何在Android系统中实现对串口设备的访问。

    在Android中如何访问底层Linux的设备驱动,必然要用到HAL,即:硬件抽象层。关于HAL的概念及框架分析,请查看作者的下面几篇博文。

      > 深入浅出 - Android系统移植与平台开发(七)- 初识HAL

    http://blog.csdn.net/mr_raptor/article/details/8069588

      > 深入浅出 - Android系统移植与平台开发(八)- HAL Stub框架分析

    http://blog.csdn.net/mr_raptor/article/details/8074549

      > 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析

    http://blog.csdn.net/mr_raptor/article/details/8082360

    1. 首先,我们先定义出串口的API类,即:SerialService,它为串口访问应用程序提示了两个API接口:read()和write()方法。

    @serial_appsrccncomfarsightSerialServiceSerialService.java

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. package cn.com.farsight.SerialService;  
    2. import java.io.BufferedReader;  
    3. import java.io.UnsupportedEncodingException;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.io.InputStreamReader;  
    7.   
    8. import android.util.Log;  
    9.   
    10. public class SerialService {  
    11.     private static final String TAG = "SerialService";  
    12.     // 底层初始化状态  
    13.     private boolean isInitOk = false;  
    14.   
    15.     // 加载本地库,read()和write()的实现通过JNI在本地代码实现  
    16.     static {  
    17.         Log.d(TAG, "System.loadLibrary()");  
    18.         System.loadLibrary("serial_runtime");  
    19.     }     
    20.       
    21.     // 构造器,用于初始化本地HAL及runtime  
    22.     public SerialService(){     
    23.         Log.d(TAG, "SerialService()");  
    24.         // 初始化本地HAL  
    25.         isInitOk =  _init();  
    26.         Log.d(TAG, "_init()");  
    27.     }  
    28.   
    29.     // 读串口数据  
    30.     public String read() {  
    31.         Log.d(TAG, "read()");  
    32.         if(!isInitOk)  
    33.             return "串口初始化失败,请确认已经连接串口设备。";  
    34.         // 由于 Java String是双字节字符,而串口数据是原始字节流,所以要进行转化  
    35.         byte[] data = new byte[128];  
    36.         // 从驱动读取字节流  
    37.         _read(data, 128);  
    38.            
    39.         String ret;  
    40.         try{  
    41.             // 转化为Java String字符  
    42.             ret = new String(data, "GBK");  
    43.         }catch(UnsupportedEncodingException e1) {  
    44.             return null;  
    45.         }  
    46.         return ret;  
    47.     }  
    48.   
    49.     // 写入字符串数据  
    50.     public int  write(String s) {  
    51.         Log.d(TAG, "write()");  
    52.         int len;  
    53.         try{  
    54.             // 将Java String字符串转码成字节流后,写入串口  
    55.             len = _write(s.getBytes("GBK"));  
    56.         }catch(UnsupportedEncodingException e1) {  
    57.             return -1;  
    58.         }  
    59.         return len;  
    60.     }  
    61.   
    62.     private static native boolean _init();  
    63.     private static native int _read(byte[] data, int len);  
    64.     private static native int _write(byte[] data);  
    65. }  


    2. 编写SerialService的运行时代码,即:cn_com_farsight_SerialService_SerialService.cpp,实现JNI调用函数:_init(),_read(),_write()。

    串口硬件抽象层头文件:

    @serial_halincludeserial.h

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #include <hardware/hardware.h>  
    2. #include <fcntl.h>  
    3. #include <errno.h>  
    4. #include <cutils/log.h>  
    5. #include <cutils/atomic.h>  
    6.   
    7. #define serial_HARDWARE_MODULE_ID "serial"  
    8.   
    9.   
    10. /*每一个硬件模块都每必须有一个名为HAL_MODULE_INFO_SYM的数据结构变量, 
    11. 它的第一个成员的类型必须为hw_module_t*/  
    12. struct serial_module_t {  
    13.     struct hw_module_t common; //模块类型  
    14.       
    15. };   
    16. /*见hardware.h中的hw_module_t定义的说明, 
    17. xxx_module_t的第一个成员必须是hw_module_t类型, 
    18. 其次才是模块的一此相关信息,当然也可以不定义, 
    19. 这里就没有定义模块相关信息 
    20. */  
    21.   
    22.   
    23. /*每一个设备数据结构的第一个成员函数必须是hw_device_t类型, 
    24. 其次才是各个公共方法和属性*/  
    25. struct serial_control_device_t {  
    26.     struct hw_device_t common; //设备类型  
    27.     /* supporting control APIs go here */  
    28.   
    29.     int (*serial_read_hal)(struct serial_control_device_t *dev, char *buf, int count);  
    30.     /***************************************/  
    31.     int (*serial_write_hal)(struct serial_control_device_t *dev, char *buf, int count);  
    32.     /***************************************/  
    33. };  
    34. /*见hardware.h中的hw_device_t的说明, 
    35. 要求自定义xxx_device_t的第一个成员必须是hw_device_t类型, 
    36. 其次才是其它的一些接口信息 
    37. */  

    @serial_runtimecn_com_farsight_SerialService_SerialService.cpp

    下面的代码用到JNI部分知识点,详情请看:

      > 深入浅出 - Android系统移植与平台开发(九)- JNI介绍

    http://blog.csdn.net/mr_raptor/article/details/8080606

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
      1. #include <hardware/hardware.h>  
      2. #include <fcntl.h>  
      3. #include <termios.h>  
      4. #include <errno.h>  
      5. #include <cutils/log.h>  
      6. #include <cutils/atomic.h>  
      7. #include <sys/ioctl.h>  
      8. #include <errno.h>  
      9. #include <string.h>  
      10. #include <dirent.h>  
      11. #include "../include/serial.h"  
      12.   
      13. int fd;  
      14.   
      15. static int serial_device_close(struct hw_device_t* device)  
      16. {  
      17.     LOGD("%s E", __func__);  
      18.     struct serial_control_device_t* ctx = (struct serial_control_device_t*)device;  
      19.     if (ctx) {  
      20.         free(ctx);  
      21.     }  
      22.     close(fd);  
      23.     LOGD("%s X", __func__);  
      24.     return 0;   
      25. }  
      26.   
      27. static int serial_read_drv(struct serial_control_device_t *dev, char *buf, int count)  
      28. {     
      29.     LOGD("%s E", __func__);  
      30.     int len = 0;  
      31.     len = read(fd, buf, count);  
      32.     if(len < 0)  
      33.     {  
      34.         perror("read");  
      35.     }  
      36.     LOGD("%s X", __func__);  
      37.     return len;  
      38. }  
      39.   
      40. static int serial_write_drv(struct serial_control_device_t *dev, char *buf, int size)  
      41. {     
      42.     LOGD("%s E", __func__);  
      43.     int len = write(fd, buf, size);  
      44.     if(len < 0)  
      45.     {  
      46.         perror("write");  
      47.     }  
      48.     LOGD("%s X", __func__);  
      49.     return len;  
      50. }  
      51.   
      52. static int serial_device_open(const struct hw_module_t* module, const char* name,  
      53.         struct hw_device_t** device)  
      54. {  
      55.     LOGD("%s E", __func__);  
      56.     struct serial_control_device_t *dev;  
      57.     struct termios opt;   
      58.   
      59.     dev = (struct serial_control_device_t *)malloc(sizeof(*dev));  
      60.     memset(dev, 0, sizeof(*dev));   
      61.   
      62.     //HAL must init property  
      63.     dev->common.tag= HARDWARE_DEVICE_TAG; //必须写这个  
      64.     dev->common.version = 0;  
      65.     dev->common.module= module;  
      66.   
      67.     dev->serial_read_hal = serial_read_drv;  
      68.   
      69.     dev->serial_write_hal = serial_write_drv;  
      70.     *device= &dev->common;  
      71.   
      72.     // MichaelTang add for open ttyUSBx   
      73.     char devname[PATH_MAX];  
      74.     DIR *dir;  
      75.     struct dirent *de;  
      76.     dir = opendir("/dev");  
      77.     if(dir == NULL)  
      78.         return -1;  
      79.     strcpy(devname, "/dev");  
      80.     char * filename = devname + strlen(devname);  
      81.     *filename++ = '/';  
      82.     while((de = readdir(dir))) {  
      83.         if(de->d_name[0] == '.' || strncmp(de->d_name, "ttyUSB", 6))        // start with . will ignor  
      84.             continue;  
      85.         strcpy(filename, de->d_name);  
      86.         if((fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY)) < 0)  
      87.         {         
      88.             LOGE("open error");  
      89.             return -1;  
      90.         }else {  
      91.             LOGD("open ok ");  
      92.             break;  
      93.         }  
      94.     }  
      95.   
      96.   
      97.     //初始化串口  
      98.     tcgetattr(fd, &opt);  
      99.     //tcflush(fd, TCIOFLUSH);  
      100.     cfsetispeed(&opt, B9600);  
      101.     cfsetospeed(&opt, B9600);  
      102.   
      103.     //tcflush(fd, TCIOFLUSH);  
      104.   
      105.     opt.c_cflag |= (CLOCAL | CREAD);  
      106.   
      107.     opt.c_cflag &= ~CSIZE;  
      108.     opt.c_cflag &= ~CRTSCTS;  
      109.     opt.c_cflag |= CS8;  
      110.   
      111.     /*  
      112.        opt.c_cflag |= PARENB;  // enable; 允许输入奇偶校验 
      113.        opt.c_cflag |= PARODD;  // J check     对输入使用奇校验           
      114.        opt.c_iflag |= (INPCK | ISTRIP);  //  
      115.        */   
      116.     opt.c_iflag |= IGNPAR;  
      117.   
      118.     opt.c_cflag &= ~CSTOPB;  
      119.   
      120.     opt.c_oflag = 0;  
      121.     opt.c_lflag = 0;  
      122.   
      123.     tcsetattr(fd, TCSANOW, &opt);  
      124.   
      125.     LOGD("%s X", __func__);  
      126.   
      127.     return 0;  
      128. }  
      129.   
      130. //定一个hw_module_methods_t结构体,关联入口函数  
      131. static struct hw_module_methods_t serial_module_methods = {  
      132. open: serial_device_open    
      133. };  
      134.   
      135. //定义Stub入口  
      136. //注意必须使用:  
      137. //1。hw_module_t继承类  
      138. //2。必须使用HAL_MODULE_INFO_SYM这个名字  
      139.   
      140. const struct serial_module_t HAL_MODULE_INFO_SYM = {  
      141. common: {  
      142. tag: HARDWARE_MODULE_TAG,  
      143.      version_major: 1,  
      144.      version_minor: 0,  
      145.      id: serial_HARDWARE_MODULE_ID,   
      146.      //模块ID,上层的Service通过这个ID应用当前Stub  
      147.      name: "serial HAL module",  
      148.      author: "farsight",  
      149.      methods: &serial_module_methods, //入口函数管理结构体  
      150.     },   
      151.     /* supporting APIs go here */  
      152. };  
  • 相关阅读:
    ios端点击document,input框不会失去焦点
    只能输入整数和小数
    Array.prototype.slice.call()方法详解 (调用方法中的参数截取出来)
    jquery自带的显示隐藏功能(有过渡效果)
    jquery鼠标事件
    JavaScript的switch循环
    JS获取当前时间
    jquery添加元素
    逻辑非(!)与(&&)或(||)
    css玩转文字
  • 原文地址:https://www.cnblogs.com/cliuwei/p/5856818.html
Copyright © 2020-2023  润新知