Difference between revisions of "APITestPage"

From FriendlyELEC WiKi
Jump to: navigation, search
(updated by API)
(updated by API)
Line 1: Line 1:
{{libfriendlyarm-hardware.so Installation Guide/zh}}
+
[[Android Hardware Programming for RK3399|English]]
  
==函数库(libfriendlyarm-hardware.so)接口说明==
+
==简介==
下面中列出HardwareControler类中的接口的定义,这些接口都是类方法,因此不需要创建HardwareControler对象实例:
+
友善电子开发了一个名为libfriendlyarm-hardware.so的函数库,用于Android应用程序访问开发板上的硬件资源,该函数库基于Android-NDK技术开发,提供便利的硬件访问接口,开发者无需掌握过多的嵌入式知识便可使用,有效提高开发进度。<br /><br />
=== 通用的输入输出接口 ===
+
本篇文章仅适用于RK3399开发板,包括 NanoPi-NEO4, NanoPi-M4 和 NanoPC-T4。<br />
'''支持平台:全平台'''
+
其他平台也有相应的支持,请移步这里查看:[[Android Hardware Access APIs/zh]]
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int open(
+
String devName
+
, int flags)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
devName: 要写入数据的<br />
+
flags: 打开文件的方式,例如可读可写还是只读打开,可选值需参考 FileCtlEnum.java<br />
+
<br />
+
返回值说明:<br />
+
成功返回文件描述符,出错返回-1。<br />
+
||
+
打开设备。
+
|-
+
  
|-
+
==支持如下RK3399官方Android BSP==
|
+
* Android 7.1.2
<syntaxhighlight lang="java">
+
* Android 8.1
int ioctlWithIntValue (
+
int fd,
+
int cmd,
+
int value)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd:设备文件描述符<br />
+
cmd: ioctl命令<br />
+
value:命令参数,限整数<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,出错返回-1。<br />
+
||
+
执行设备的ioctl操作
+
|-
+
  
|-
+
==支持如下RK3399硬件资源==
|
+
* Serial Port
<syntaxhighlight lang="java">
+
* GPIO
ioctl(int fd,
+
* ADC
int cmd
+
* PWM
, byte[] buf)
+
* I2C
</syntaxhighlight>
+
* RTC
||
+
* Watch dog
参数说明:<br />
+
* SPI
fd:设备文件描述符<br />
+
等等, 接口包括I2C, SPI, GPIO常用的接口。<br />
cmd: ioctl命令<br />
+
[[File:NanoPC-T4+OLED.jpg|frameless|450px|Smart4418SDK+OLED]]
buf:命令的参数<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,出错返回-1。<br />
+
||
+
执行设备的ioctl操作, <br />
+
如果 ioctl是一个结构体,<br />
+
你需要将结构体的数据转换成字节流 <br />
+
|-
+
  
|-
+
==支持的开发板==
|
+
* NanoPi-NEO4
<syntaxhighlight lang="java">
+
* NanoPi-M4
int write(
+
* NanoPC-T4
int fd,
+
* 其他开发板请移步这里查看:[[Android Hardware Access APIs/zh]]
byte[] data)
+
 
</syntaxhighlight>
+
==开源Android示例==
||
+
所有硬件访问的示例程序均已集成到 Android 的源代码当中,位于 Android7.1.2 和 Android8.1 源代码的以下目录:vendor/friendlyelec/apps,也可以单独网上下载,下表中列出各个 Demo 的源代码地址:
参数说明:<br />
+
{{libfriendlyarm-hardware.so Android8 Demos}}
fd: 要写入数据的文件描述符<br />
+
{{libfriendlyarm-hardware.so Android7 Demos}}
data: 要写入的数据<br />
+
{{libfriendlyarm-hardware.so Installation Guide/zh}}
<br />
+
返回值说明:<br />
+
成功返回写入的字节数,出错返回-1。<br />
+
||
+
向打开的设备或文件中写数据。
+
|-
+
  
 +
==RK3399平台Android硬件资源的程序访问==
 +
===Serial Port===
 +
目前可用的串口是UART4,设备名称为/dev/ttyS4,其他串口资源如下表所示,你也可以使用USB转串口来扩展:
 +
::{| class="wikitable"
 
|-
 
|-
|
+
|串口设备 || 串口资源占用情况
<syntaxhighlight lang="java">
+
int read(
+
int fd,
+
byte[] buf,
+
int len)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: 要读出数据的文件描述符<br />
+
buf: 存储数据的缓冲区<br />
+
len: 要读取的字节数<br />
+
<br />
+
返回值说明:<br />
+
成功返回读取的字节数,出错返回-1,如果在调read之前已到达文件末尾,则这次read返回0。<br />
+
||
+
从打开的设备或文件中读取数据。
+
 
|-
 
|-
 
+
|UART0  || 已被蓝牙占用
 
|-
 
|-
|
+
|UART1  || 已被千兆以太网占用 
<syntaxhighlight lang="java">
+
int select(
+
int fd,
+
int sec,
+
int usec)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: 要查询的文件描述符<br />
+
sen: 阻塞等待数据多长时间(单位:秒)<br />
+
usec: 阻塞等待数据多长时间 (单位:纳秒,1毫秒=1000纳秒)<br />
+
<br />
+
返回值说明:<br />
+
如果fd有数据可读,返回1, 如果没有数据可读,返回0,出错时返回-1。<br />
+
||
+
查询打开的设备或文件是否有数据可读。
+
 
|-
 
|-
 
+
|UART2  ||  已被作为调试串口
 
|-
 
|-
|
+
|UART3  || 已被千兆以太网占用
<syntaxhighlight lang="java">
+
void close(int fd)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: 要关闭的文件描述符<br />
+
<br />
+
返回值说明:<br />
+
无<br />
+
||
+
关闭指定的文件描述符
+
 
|-
 
|-
 +
|UART4  ||  空闲,设备名称为 /dev/ttyS4 (注:需使用20180618之后的ROM)
 +
|}
  
 
+
Android硬件库为串口API:
|}
+
=== 串口通讯的接口说明 ===
+
'''支持平台:全平台'''
+
 
::{| class="wikitable"
 
::{| class="wikitable"
 
|-
 
|-
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''  
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''  
 
| style="background: PaleTurquoise; color: black" |'''功能说明'''
 
| style="background: PaleTurquoise; color: black" |'''功能说明'''
 
|-
 
|-
Line 155: Line 62:
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
int openSerialPortEx(
 
int openSerialPortEx(
String devName,
+
String devName,  
 
long baud,
 
long baud,
 
int dataBits,
 
int dataBits,
Line 165: Line 72:
 
||
 
||
 
参数说明:<br />
 
参数说明:<br />
devName: 串口设备文件名<br />
+
devName: 串口设备文件名,可选的值有:<br />
 +
/dev/ttyS4<br />
 
baud:    波特率 <br />
 
baud:    波特率 <br />
 
dataBits: 数据位 (取值 5~8,一般用8 )<br />
 
dataBits: 数据位 (取值 5~8,一般用8 )<br />
Line 177: Line 85:
 
|-
 
|-
 
|}
 
|}
接口的使用说明:<br />
 
<br />
 
先通过调用openSerialPortEx 打开串口设备,然后可以在线程中、或者用 timer 通过调用 select 接口轮询串口设备是否有数据到来,如果有,则调用 read 接口读取数据。<br />
 
<br />
 
要往串口中写入数据,调用 write 接口即可。<br />
 
串口使用完毕后,需要调用 close 关闭串口。<br />
 
<br />
 
  
=== 板载LED的接口说明 ===
+
串口的读写使用以下通用接口:
'''支持平台:此接口仅适用于Tiny和Smart系列的核心板,例如Tiny4412,Smart4412,Smart4418'''
+
<syntaxhighlight lang="c">
::{| class="wikitable"
+
HardwareControler.select  //轮询串口是否有数据可写或可读
|-
+
HardwareControler.read    //读取串口数据
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
HardwareControler.write    //写数据到串口
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
HardwareControler.close    //关闭设备
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setLedState(
+
int ledID,
+
int ledState )
+
 
</syntaxhighlight>
 
</syntaxhighlight>
||
+
===GPIO===
参数说明:<br />
+
ledID: 指定要开关哪一个LED (取值0~3)<br />
+
ledState: 1表示亮,0表示灭<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
||
+
该接口用于开关LED灯。
+
|-
+
|}
+
  
=== 让PWM蜂鸣器发声和停止发声的接口说明 ===
+
===ADC===
'''支持平台:此接口仅适用于带蜂鸣器的Tiny和Smart系列底板,例如Tiny4412,Smart4412,Smart4418'''
+
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int PWMPlay(int frequency);
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
frequency: 要发声的频率<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
||
+
按指定的频率让蜂鸣器发声
+
|-
+
  
|-
+
===PWM===
|
+
<syntaxhighlight lang="java">
+
int PWMStop();
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
无<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
||
+
让蜂鸣器停止发声
+
|-
+
|}
+
  
=== 读取ADC的转换结果的接口说明 ===
+
===I2C===
'''支持平台:仅适用于三星平台的开发板,包括6410、210、4412'''
+
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int readADC()
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
无<br />
+
<br />
+
返回值说明:<br />
+
成功返回ADC转换的结果,失败返回-1<br />
+
||
+
读取第一个通道的ADC转换结果
+
|-
+
  
|-
+
===RTC===
|
+
可以直接使用cat和echo操作/sys/class/rtc/rtc0/下面的接口。
<syntaxhighlight lang="java">
+
比如查看当前RTC的日期和时间:
int readADCWithChannel(int channel)
+
<syntaxhighlight lang="bash">
 +
cat /sys/class/rtc/rtc0/date
 +
# 2018-10-20                                                             
 +
cat /sys/class/rtc/rtc0/time                                           
 +
# 08:20:14
 
</syntaxhighlight>
 
</syntaxhighlight>
||
+
设置开机时间,如设置120秒后开机:
参数说明:<br />
+
<syntaxhighlight lang="bash">
channel: 读取指定通道的ADC的值<br />
+
#120秒后定时开机
<br />
+
echo +120 >  /sys/class/rtc/rtc0/wakealarm
返回值说明:<br />
+
成功返回ADC转换的结果,失败返回-1<br />
+
||
+
读取指定通道的ADC转换的结果
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int[] readADCWithChannels(int[] channels);
+
 
</syntaxhighlight>
 
</syntaxhighlight>
||
 
参数说明:<br />
 
channels: 要读取通道的ADC频道数组<br />
 
<br />
 
返回值说明:<br />
 
成功返回多个ADC结果(数组),错误返回空<br />
 
||
 
一次性读取多个频道的结果,性能好
 
|-
 
|}
 
  
=== I2C接口说明 ===
+
===Watch dog===
'''支持平台:全平台'''
+
在使用如下接口之前,首先需要使用open接口打开I2C设备,如下所示, 操作完成后,记得用HardwareControler.close关闭:<br />
+
<syntaxhighlight lang="java">
+
int fd = HardwareControler.open("/dev/i2c-0", FileCtlEnum.O_RDWR);
+
</syntaxhighlight>
+
以下接口需要该fd作来参数进行操作:<br />
+
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setI2CSlave(int fd, int slave);
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: I2C设备的文件描述符<br />
+
slave: I2C设备地址,例如EEPROM设备一般是0x50<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
||
+
设置要操作的I2C设备地址,例如EEPROM设备一般是0x50
+
|-
+
  
|-
+
===SPI===
|
+
<syntaxhighlight lang="java">
+
int setI2CTimeout(int fd, int timeout)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: I2C设备的文件描述符<br />
+
timeout: 超时时间<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
<br />
+
||
+
设置超时时间(ioctl I2C_TIMEOUT)
+
|-
+
  
|-
 
|
 
<syntaxhighlight lang="java">
 
int setI2CRetries(int fd, int retries)
 
</syntaxhighlight>
 
||
 
参数说明:<br />
 
fd: I2C设备的文件描述符<br />
 
retries: 重试次数<br />
 
<br />
 
返回值说明:<br />
 
成功返回0,失败返回-1<br />
 
<br />
 
||
 
设置重试次数(ioctl I2C_RETRIES)
 
|-
 
  
|-
+
==函数库(libfriendlyarm-hardware.so)接口说明==
|
+
请参考这份WiKi文档:[[Android Hardware Access APIs/zh]]
<syntaxhighlight lang="java">
+
int writeByteToI2C(int fd
+
, int pos
+
byte byteData
+
, int wait_ms)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: I2C设备的文件描述符<br />
+
pos: 字节位置<br />
+
byteData:要写入的数据<br />
+
wait_ms: 等待指定的时间(毫秒)<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
<br />
+
||
+
写一个字节的数据到I2C设备的指定位置,并等待指定的时间(毫秒)
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int readByteFromI2C(int fd
+
, int pos
+
, int wait_ms);
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
fd: I2C设备的文件描述符<br />
+
pos: 字节位置<br />
+
wait_ms: 等待指定的时间(毫秒)<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回-1<br />
+
<br />
+
||
+
从I2C设备指定的位置读一个字节的数据,并等待指定的时间(毫秒)
+
|-
+
 
+
|}
+
 
+
=== SPI接口说明 ===
+
'''支持平台:全平台'''
+
在使用如下接口之前,首先需要使用open接口打开SPI设备,如下所示, 操作完成后,记得用HardwareControler.close关闭:<br />
+
<syntaxhighlight lang="java">
+
int spi_fd = HardwareControler.open("/dev/spidev1.0", FileCtlEnum.O_RDWR );
+
</syntaxhighlight>
+
以下接口需要该spi_fd作来参数进行操作:<br />
+
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setSPIWriteBitsPerWord( int spi_fd, int bits )
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
bits: 字长,单位是比特<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
<br />
+
||
+
设置每次读SPI设备的字长,单位是比特。<br />
+
虽然大部分SPI接口的字长是8或者16,仍然会有一些特殊的例子。<br />
+
需要说明的是,如果这个成员为零的话,默认使用8作为字长(ioctl SPI_IOC_WR_BITS_PER_WORD)
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setSPIReadBitsPerWord( int spi_fd
+
, int bits )
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
bits: 字长,单位是比特<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
<br />
+
||
+
设置每次写SPI设备的字长,单位是比特 (ioctl SPI_IOC_RD_BITS_PER_WORD)
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setSPIBitOrder( int spi_fd
+
, int order)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
order: 传SPIEnum.MSBFIRST或SPIEnum.LSBFIRST<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
设备SPI传输时是先传输低比特位还是高比特位,可选的参数有SPIEnum.MSBFIRST和SPIEnum.LSBFIRST
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setSPIClockDivider( int spi_fd
+
, int divider)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
divider: 分频系数,传入在SPIEnum.java中定义的以SPI_CLOCK_开头的常量,例如:<br />
+
SPIEnum.SPI_CLOCK_DIV128<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
设置SPI的分频系数
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setSPIDataMode( int spi_fd
+
, int mode)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
mode: SPI设备的模式,可传入SPIEnum.SPI_MODE0 ~ SPIEnum.SPI_MODE3<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
设置SPI设备的模式
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int SPItransferOneByte( int spi_fd
+
, byte byteData
+
, int spi_delay
+
, int spi_speed
+
, int spi_bits)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
byteData:要写入SPI设备的数据<br />
+
spi_delay:延时<br />
+
spi_speed:传输速度<br />
+
spi_bits:字长,单位是比特<br />
+
<br />
+
返回值说明:<br />
+
成功返回读到的数据,失败返回负数<br />
+
<br />
+
||
+
同时发送与接收一个字节的数据,调用示例:
+
int byteRet = SPItransferOneByte(spi_fd
+
, 0xAA
+
, 0 /*delay*/
+
, 500000/*speed*/
+
,8/*bits*/)
+
;
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int SPItransferBytes(int spi_fd
+
, byte[] writeData
+
, byte[] readBuff
+
, int spi_delay
+
, int spi_speed
+
, int spi_bits)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
writeData:要写入的数据<br />
+
readBuff: 存放读取数据的缓冲区<br />
+
spi_delay:延时<br />
+
spi_speed:传输速度<br />
+
spi_bits:字长,单位是比特<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
<br />
+
||
+
同时发送与接收多个字节的数据
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int writeBytesToSPI(int spi_fd
+
, byte[] writeData
+
, int spi_delay
+
, int spi_speed
+
, int spi_bits)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
spi_fd: SPI设备的文件描述符<br />
+
writeData:要写入的数据<br />
+
spi_delay:延时<br />
+
spi_speed:传输速度<br />
+
spi_bits:字长,单位是比特<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
<br />
+
||
+
写多个字节的数据到SPI设备
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int readBytesFromSPI(int spi_fd
+
, byte[] readBuff
+
, int spi_delay
+
, int spi_speed
+
, int spi_bits)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
readBuff: 存放读取数据的缓冲区<br />
+
spi_delay:延时<br />
+
spi_speed:传输速度<br />
+
spi_bits:字长,单位是比特<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
<br />
+
||
+
从SPI设备读取多个字节
+
|-
+
|}
+
 
+
 
+
=== GPIO接口说明 ===
+
'''支持平台:全平台'''
+
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int exportGPIOPin(int pin)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
pin: GPIO引脚编号<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
通知系统需要导出控制的GPIO引脚编号,<br />
+
相当于执行命令 echo pin > /sys/class/gpio/export
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int unexportGPIOPin(int pin)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
pin: GPIO引脚编号<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
通知系统取消导出某个GPIO引脚,<br />
+
相当于执行命令 echo pin > /sys/class/gpio/unexport
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setGPIOValue(int pin, int value)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
pin: GPIO引脚编号<br />
+
value: 传入GPIOEnum.LOW表示输出低电平,传入GPIOEnum.HIGH表示输出高电平<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
对某个引脚输出高或低电平
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int getGPIOValue(int pin)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
pin: GPIO引脚编号<br />
+
<br />
+
返回值说明:<br />
+
成功返回GPIOEnum.LOW表示输出低电平,<br />
+
返回GPIOEnum.HIGH表示输出高电平,失败返回负数<br />
+
||
+
查询某个引脚的状态(高或低电平)
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int setGPIODirection(int pin, int direction)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
pin: GPIO引脚编号<br />
+
direction: 传入GPIOEnum.IN表示输入, <br />
+
GPIOEnum.OUT表示输出<br />
+
<br />
+
返回值说明:<br />
+
成功返回0,失败返回负数<br />
+
||
+
配置引脚功能为输出或者输入
+
|-
+
 
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int getGPIODirection(int pin)
+
</syntaxhighlight>
+
||
+
参数说明:<br />
+
pin: GPIO引脚编号<br />
+
<br />
+
成功返回GPIOEnum.IN表示输入,<br />
+
返回 GPIOEnum.OUT表示输出,失败返回负数<br />
+
||
+
查询引脚功能 (为输出或者输入)
+
|-
+
|}
+
 
+
=== 查询开发板型号 ===
+
::{| class="wikitable"
+
|-
+
| style="background: PaleTurquoise; color: black" | '''接口名称'''
+
| style="background: PaleTurquoise; color: black" |'''参数与返回值说明'''
+
| style="background: PaleTurquoise; color: black" |'''功能说明'''
+
|-
+
|
+
<syntaxhighlight lang="java">
+
int getBoardType()
+
</syntaxhighlight>
+
||
+
成功返回一个代表开发板型号的数字,<br />
+
数字的含义在 BoardType.java 中定义,<br />
+
如果开发板无法识别,将失败负数 <br />
+
||
+
查询开发板型号, 调用示例:<br />
+
<syntaxhighlight lang="java">
+
private int mBoardType = HardwareControler.getBoardType();
+
if (mBoardType == BoardType.NanoPC_T4) {
+
    // do something...
+
}
+
</syntaxhighlight>
+
|-
+
|}
+

Revision as of 09:35, 22 October 2018

English

1 简介

友善电子开发了一个名为libfriendlyarm-hardware.so的函数库,用于Android应用程序访问开发板上的硬件资源,该函数库基于Android-NDK技术开发,提供便利的硬件访问接口,开发者无需掌握过多的嵌入式知识便可使用,有效提高开发进度。

本篇文章仅适用于RK3399开发板,包括 NanoPi-NEO4, NanoPi-M4 和 NanoPC-T4。
其他平台也有相应的支持,请移步这里查看:Android Hardware Access APIs/zh

2 支持如下RK3399官方Android BSP

  • Android 7.1.2
  • Android 8.1

3 支持如下RK3399硬件资源

  • Serial Port
  • GPIO
  • ADC
  • PWM
  • I2C
  • RTC
  • Watch dog
  • SPI

等等, 接口包括I2C, SPI, GPIO常用的接口。
Smart4418SDK+OLED

4 支持的开发板

5 开源Android示例

所有硬件访问的示例程序均已集成到 Android 的源代码当中,位于 Android7.1.2 和 Android8.1 源代码的以下目录:vendor/friendlyelec/apps,也可以单独网上下载,下表中列出各个 Demo 的源代码地址:

5.1 Android8.1

5.1.1 Applicable Boards

  • NanoPC-T4/NanoPi-M4/NanoPi-NEO4
Android8.1 Demos
Serial Port

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/SerialPortDemo

GPIO

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/GPIO_LED_Demo

ADC

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/ADCDemo

PWM

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/PWMDemo

I2C

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/I2C_LCD1602_Demo

RTC

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/RTC_Demo-RK3399

Watch dog

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/WatchDogDemo-RK3399

SPI

https://gitlab.com/friendlyelec/rk3399-android-8.1/tree/master/vendor/friendlyelec/apps/SPI_OLED_Demo

5.2 Android7.1.2

5.2.1 Applicable Boards

  • NanoPC-T4/NanoPi-M4/NanoPi-NEO4
Android7.1.2 Demos
Serial Port

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/SerialPortDemo

GPIO

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/GPIO_LED_Demo

ADC

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/ADCDemo

PWM

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/PWMDemo

I2C

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/I2C_LCD1602_Demo

RTC

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/RTC_Demo-RK3399

Watch dog

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/WatchDogDemo-RK3399

SPI

https://gitlab.com/friendlyelec/rk3399-nougat/tree/nanopc-t4-nougat/vendor/friendlyelec/apps/SPI_OLED_Demo

6 快速使用入门

6.1 (第1步) 集成libfriendlyarm-things.so到你的app

克隆以下仓库到本地:

git clone https://github.com/friendlyarm/friendlythings-sdk

接着复制 libs 目录下的所有内容到你的工程目录下,然后在你的Android项目的src目录下创建com/friendlyarm目录,将java/FriendlyThings目录拷贝进去即可,最后的目录的结构看上去是这样的 (注:AndroidStudio的项目可能会稍有不同,但大致如此):

YourProject/
├── AndroidManifest.xml
├── libs
│   ├── arm64-v8a
│   │   └── libfriendlyarm-things.so
│   └── armeabi
│       └── libfriendlyarm-things.so
├── src
│   └── com
│       └── friendlyarm
│           ├── FriendlyThings
│           │   ├── BoardType.java
│           │   ├── FileCtlEnum.java
│           │   ├── GPIOEnum.java
│           │   ├── HardwareControler.java
│           │   ├── SPIEnum.java
│           │   ├── SPI.java
│           │   └── WatchDogEnum.java

使用以下方法导入它们,主要的接口都集中在 HardwareControler.java文件中:

import com.friendlyarm.FriendlyThings.HardwareControler;
import com.friendlyarm.FriendlyThings.SPIEnum;
import com.friendlyarm.FriendlyThings.GPIOEnum;
import com.friendlyarm.FriendlyThings.FileCtlEnum;
import com.friendlyarm.FriendlyThings.BoardType;

6.2 (第2步) 让你的app拥有system权限

你的app需要拥有system权限,才能访问硬件资源;
请参考下面的方法修改你 app 的 AndroidManifest.xml 和 Android.mk这两个文件;
并且最好将你的app放到Android源码中去编译,这一步不是必需的,但是建议这么做,如果你的app在外部编译,你需要对apk进行签名才能让你的app拥有system权限(新手不太建议,过程比较繁琐)。

6.2.1 修改AndroidManifest.xml

在应用程序的AndroidManifest.xml中的manifest节点中加入以下属性:

android:sharedUserId="android.uid.system"

6.2.2 修改Android.mk

编写一个Android.mk文件(最简单的方法就是拷贝示例中的Android.mk文件),修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
LOCAL_PACKAGE_NAME := 你的项目名
 
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -lfriendlyarm-hardware
 
include $(BUILD_PACKAGE)

6.3 (最后1步) 在 Android源代码中编译你的app

先在 Android源代码根目录调用 setenv.sh 导出环境变量,然后进入你的 app 目录,使用mm命令编译;
例子:编译 GPIO_LED_Demo,以RK3399平台为例:

cd rk3399-android-8.1
. setenv.sh
cd vendor/friendlyelec/apps/GPIO_LED_Demo
mm

6.4 一个Android Studio的示例项目

https://github.com/friendlyarm/AndroidStudio-GPIODemo

7 RK3399平台Android硬件资源的程序访问

7.1 Serial Port

目前可用的串口是UART4,设备名称为/dev/ttyS4,其他串口资源如下表所示,你也可以使用USB转串口来扩展:

串口设备 串口资源占用情况
UART0 已被蓝牙占用
UART1 已被千兆以太网占用
UART2 已被作为调试串口
UART3 已被千兆以太网占用
UART4 空闲,设备名称为 /dev/ttyS4 (注:需使用20180618之后的ROM)

Android硬件库为串口API:

接口名称 参数与返回值说明 功能说明
int openSerialPortEx(
String devName, 
long baud,
int dataBits,
int stopBits,
String parityBit,
String flowCtrl
)

参数说明:
devName: 串口设备文件名,可选的值有:
/dev/ttyS4
baud: 波特率
dataBits: 数据位 (取值 5~8,一般用8 )
stopBits: 停止位 (取值 1~2,一般用1 )
parityBit: 奇偶校验位(取值为单个字母,O表示奇校验,E表示偶校验,N表示无校验)
flowCtrl: 数据流控制(取值为单个字母,H表示硬件流控制,S表示软件流控制,N表示不使用数据流控制)
返回值说明:
成功打开串口时,将返回串口的文件描述符,用该描述符可进行 read、write和select等操作,如果打开失败,则返回 -1

打开指定的串口设备,并返回文件描述符。

串口的读写使用以下通用接口:

HardwareControler.select   //轮询串口是否有数据可写或可读
HardwareControler.read     //读取串口数据
HardwareControler.write    //写数据到串口
HardwareControler.close    //关闭设备

7.2 GPIO

7.3 ADC

7.4 PWM

7.5 I2C

7.6 RTC

可以直接使用cat和echo操作/sys/class/rtc/rtc0/下面的接口。 比如查看当前RTC的日期和时间:

cat /sys/class/rtc/rtc0/date
# 2018-10-20                                                              
cat /sys/class/rtc/rtc0/time                                            
# 08:20:14

设置开机时间,如设置120秒后开机:

#120秒后定时开机
echo +120 >  /sys/class/rtc/rtc0/wakealarm

7.7 Watch dog

7.8 SPI

8 函数库(libfriendlyarm-hardware.so)接口说明

请参考这份WiKi文档:Android Hardware Access APIs/zh