未验证 提交 d31322d7 编写于 作者: O openharmony_ci 提交者: Gitee

!19440 Platform文档刷新

Merge pull request !19440 from 贾子扬/master
...@@ -4,29 +4,30 @@ ...@@ -4,29 +4,30 @@
### 功能简介<a name="section2"></a> ### 功能简介<a name="section2"></a>
ADC(Analog to Digital Converter),即模拟-数字转换器,可将模拟信号转换成对应的数字信号,便于存储与计算等操作。除电源线和地线之外,ADC只需要1根线与被测量的设备进行连接,其物理连线如图1: ADC(Analog to Digital Converter),即模拟-数字转换器,可将模拟信号转换成对应的数字信号,便于存储与计算等操作。除电源线和地线之外,ADC只需要1根线与被测量的设备进行连接,其物理连线如图1所示
**图 1** ADC物理连线示意图<a name="fig1"></a> **图 1** ADC物理连线示意图<a name="fig1"></a>
![](figures/ADC物理连线示意图.png "ADC物理连线示意图") ![ADC物理连线示意图](figures/ADC物理连线示意图.png)
ADC接口定义了完成AD转换的通用方法集合,包括: ADC接口定义了完成AD转换的通用方法集合,包括:
- ADC设备管理:打开或关闭ADC设备。 - ADC设备管理:打开或关闭ADC设备。
- ADC读取转换结果:读取AD转换结果。 - ADC读取转换结果:读取AD转换结果。
### 基本概念<a name="section3"></a> ### 基本概念<a name="section3"></a>
- 分辨率 - 分辨率
分辨率指的是ADC模块能够转换的二进制位数,位数越多分辨率越高。 分辨率指的是ADC模块能够转换的二进制位数,位数越多分辨率越高。
- 转换误差 - 转换误差
转换误差通常是以输出误差的最大值形式给出。它表示A/D转换器实际输出的数字量和理论上的输出数字量之间的差别。常用最低有效位的倍数表示。 转换误差通常是以输出误差的最大值形式给出。它表示A/D转换器实际输出的数字量和理论上的输出数字量之间的差别。常用最低有效位的倍数表示。
- 转换时间 - 转换时间
转换时间是指A/D转换器从转换控制信号到来开始,到输出端得到稳定的数字信号所经过的时间。 转换时间是指A/D转换器从转换控制信号到来开始,到输出端得到稳定的数字信号所经过的时间。
### 运作机制<a name="section4"></a> ### 运作机制<a name="section4"></a>
...@@ -50,18 +51,18 @@ ADC模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/ ...@@ -50,18 +51,18 @@ ADC模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/
<a name="table1"></a> <a name="table1"></a>
| 接口名 | 接口描述 | | 接口名 | 接口描述 |
| -------- | ---------------- | | -------- | ---------------- |
| DevHandle AdcOpen(uint32_t number) | 打开ADC设备 | | DevHandle AdcOpen(uint32_t number) | 打开ADC设备 |
| void AdcClose(DevHandle handle) | 关闭ADC设备 | | void AdcClose(DevHandle handle) | 关闭ADC设备 |
| int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t \*val) | 读取AD转换结果值 | | int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t \*val) | 读取AD转换结果值 |
### 开发步骤<a name="section9"></a> ### 开发步骤<a name="section9"></a>
使用ADC设备的一般流程如图2所示。 使用ADC设备的一般流程如图2所示。
**图 2** ADC使用流程图<a name="fig2"></a> **图 2** ADC使用流程图<a name="fig2"></a>
![](figures/ADC使用流程图.png "ADC使用流程图") ![ADC使用流程图](figures/ADC使用流程图.png)
#### 打开ADC设备 #### 打开ADC设备
...@@ -76,23 +77,23 @@ DevHandle AdcOpen(int16_t number); ...@@ -76,23 +77,23 @@ DevHandle AdcOpen(int16_t number);
<a name="table2"></a> <a name="table2"></a>
| 参数 | 参数描述 | | 参数 | 参数描述 |
| ---------- | ----------------- | | ---------- | ----------------- |
| number | ADC设备号 | | number | int16_t类型,ADC设备号 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| NULL | 打开ADC设备失败 | | NULL | 打开ADC设备失败 |
| 设备句柄 | 打开的ADC设备句柄 | | 设备句柄 | 打开的ADC设备句柄 |
假设系统中存在2个ADC设备,编号从0到1,那么我们现在打开1号设备。 假设系统中存在2个ADC设备,编号从0到1,那么我们现在打开1号设备。
```c ```c
DevHandle adcHandle = NULL; /* ADC设备句柄 / DevHandle adcHandle = NULL; // ADC设备句柄
/* 打开ADC设备 */ // 打开ADC设备
adcHandle = AdcOpen(1); adcHandle = AdcOpen(1);
if (adcHandle == NULL) { if (adcHandle == NULL) {
HDF_LOGE("AdcOpen: fail\n"); HDF_LOGE("AdcOpen: fail\n");
return; return NULL;
} }
``` ```
...@@ -106,14 +107,14 @@ int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val); ...@@ -106,14 +107,14 @@ int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val);
<a name="table3"></a> <a name="table3"></a>
| 参数 | 参数描述 | | 参数 | 参数描述 |
| ---------- | -------------- | | ---------- | -------------- |
| handle | ADC设备句柄 | | handle | DevHandle类型,ADC设备句柄 |
| channel | ADC设备通道号 | | channel| uint32_t类型,ADC设备通道号 |
| val | AD转换结果 | | val | uint32_t类型指针,AD转换结果 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 读取成功 | | HDF_SUCCESS | 读取成功 |
| 负数 | 读取失败 | | 负数 | 读取失败 |
读取转换结果示例(以通道1为例): 读取转换结果示例(以通道1为例):
...@@ -122,9 +123,9 @@ uint32_t value; ...@@ -122,9 +123,9 @@ uint32_t value;
int32_t ret; int32_t ret;
ret = AdcRead(adcHandle, 1, &value); ret = AdcRead(adcHandle, 1, &value);
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("ADC read fail!\n"); HDF_LOGE("ADC read fail!\n");
return; return ret;
} }
``` ```
...@@ -138,16 +139,16 @@ void AdcClose(DevHandle handle); ...@@ -138,16 +139,16 @@ void AdcClose(DevHandle handle);
<a name="table4"></a> <a name="table4"></a>
| 参数 | 参数描述 | | 参数 | 参数描述 |
| ------ | ----------- | | ------ | ----------- |
| handle | ADC设备句柄 | | handle | DevHandle类型,ADC设备句柄 |
| 返回值 | 返回值描述 | | 返回值 | 返回值描述 |
| 无 | 无 | | 无 | 无 |
关闭ADC设备示例: 关闭ADC设备示例:
```c ```c
AdcClose(adcHandle); /* 关闭ADC设备 */ AdcClose(adcHandle); // 关闭ADC设备
``` ```
### 使用实例<a name="section10"></a> ### 使用实例<a name="section10"></a>
...@@ -163,15 +164,15 @@ AdcClose(adcHandle); /* 关闭ADC设备 */ ...@@ -163,15 +164,15 @@ AdcClose(adcHandle); /* 关闭ADC设备 */
示例如下: 示例如下:
```c ```c
#include "adc_if.h" /* ADC标准接口头文件 */ #include "adc_if.h" // ADC标准接口头文件
#include "hdf_log.h" /* 标准日志打印头文件 */ #include "hdf_log.h" // 标准日志打印头文件
/* 设备号0,通道号1 */ /// 设备号0,通道号1
#define ADC_DEVICE_NUM 0 #define ADC_DEVICE_NUM 0
#define ADC_CHANNEL_NUM 1 #define ADC_CHANNEL_NUM 1
#define ADC_TEST_NUM 30 #define ADC_TEST_NUM 30
/* ADC例程总入口 */ // ADC例程总入口
static int32_t TestCaseAdc(void) static int32_t TestCaseAdc(void)
{ {
int32_t i; int32_t i;
...@@ -179,14 +180,14 @@ static int32_t TestCaseAdc(void) ...@@ -179,14 +180,14 @@ static int32_t TestCaseAdc(void)
DevHandle adcHandle = NULL; DevHandle adcHandle = NULL;
uint32_t readBuf[ADC_TEST_NUM] = {0}; uint32_t readBuf[ADC_TEST_NUM] = {0};
/* 打开ADC设备 */ // 打开ADC设备
adcHandle = AdcOpen(ADC_DEVICE_NUM); adcHandle = AdcOpen(ADC_DEVICE_NUM);
if (adcHandle == NULL) { if (adcHandle == NULL) {
HDF_LOGE("%s: Open ADC%u fail!", __func__, ADC_DEVICE_NUM); HDF_LOGE("%s: Open ADC%u fail!", __func__, ADC_DEVICE_NUM);
return -1; return -1;
} }
/* 连续进行30次AD转换并读取转换结果 */ // 连续进行30次AD转换并读取转换结果
for (i = 0; i < ADC_TEST_NUM; i++) { for (i = 0; i < ADC_TEST_NUM; i++) {
ret = AdcRead(adcHandle, ADC_CHANNEL_NUM, &readBuf[i]); ret = AdcRead(adcHandle, ADC_CHANNEL_NUM, &readBuf[i]);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
...@@ -197,7 +198,7 @@ static int32_t TestCaseAdc(void) ...@@ -197,7 +198,7 @@ static int32_t TestCaseAdc(void)
} }
HDF_LOGI("%s: ADC read successful!", __func__); HDF_LOGI("%s: ADC read successful!", __func__);
/* 访问完毕关闭ADC设备 */ // 访问完毕关闭ADC设备
AdcClose(adcHandle); AdcClose(adcHandle);
return 0; return 0;
......
...@@ -7,29 +7,32 @@ ...@@ -7,29 +7,32 @@
DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备,主要用于: DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备,主要用于:
- 作为过程控制计算机系统的输出通道,与执行器相连,实现对生产过程的自动控制。 - 作为过程控制计算机系统的输出通道,与执行器相连,实现对生产过程的自动控制。
- 在利用反馈技术的模数转换器设计中,作为重要的功能模块呈现。 - 在利用反馈技术的模数转换器设计中,作为重要的功能模块呈现。
DAC接口定义了完成DAC传输的通用方法集合,包括: DAC接口定义了完成DAC传输的通用方法集合,包括:
- DAC设备管理:打开或关闭DAC设备。 - DAC设备管理:打开或关闭DAC设备。
- DAC设置目标值:设置DAC设备需要将数字信号转成模拟信号的目标值。 - DAC设置目标值:设置DAC设备需要将数字信号转成模拟信号的目标值。
### 基本概念 ### 基本概念
- 分辨率 - 分辨率
分辨率指的是DAC模块能够转换的二进制位数,位数越多分辨率越高。 分辨率指的是DAC模块能够转换的二进制位数,位数越多分辨率越高。
- 转换精度 - 转换精度
精度是指输入端加有最大数值时,DAC的实际输出值和理论计算值之差,DAC转换器的转换精度与DAC转换器的集成芯片结构和接口电路配置有关。理想情况下,DAC的转换精度越小越好,因此为了获得更高精度的DAC转换结果,首先要保证选择的DAC转换器具备足够高的分辨率。其次,接口电路的器件或电源存在误差时,会造成DAC转换的误差,若这些误差超过一定程度,就会导致DAC转换错误。 精度是指输入端加有最大数值时,DAC的实际输出值和理论计算值之差,DAC转换器的转换精度与DAC转换器的集成芯片结构和接口电路配置有关。理想情况下,DAC的转换精度越小越好,因此为了获得更高精度的DAC转换结果,首先要保证选择的DAC转换器具备足够高的分辨率。其次,接口电路的器件或电源存在误差时,会造成DAC转换的误差,若这些误差超过一定程度,就会导致DAC转换错误。
- 转换速度 - 转换速度
转换速度一般由建立时间决定。从输入由全0突变为全1时开始,到输出电压稳定在FSR±½LSB范围(或以FSR±x%FSR指明范围)内为止,这段时间称为建立时间,它是DAC的最大响应时间,所以用它衡量转换速度的快慢。 转换速度一般由建立时间决定。从输入由全0突变为全1时开始,到输出电压稳定在FSR±½LSB范围(或以FSR±x%FSR指明范围)内为止,这段时间称为建立时间,它是DAC的最大响应时间,所以用它衡量转换速度的快慢。
满量程范围FSR(Full Scale Range),是指DAC输出信号幅度的最大范围,不同的DAC有不同的满量程范围,该范围可以用正、负电流或者正、负电压来限制。 满量程范围FSR(Full Scale Range),是指DAC输出信号幅度的最大范围,不同的DAC有不同的满量程范围,该范围可以用正、负电流或者正、负电压来限制。
最低有效位LSB(Least Significant Byte),指的是一个二进制数字中的第0位(即最低位)。 最低有效位LSB(Least Significant Byte),指的是一个二进制数字中的第0位(即最低位)。
### 运作机制 ### 运作机制
...@@ -59,10 +62,10 @@ DAC模块提供的主要接口如下所示,具体API详见//drivers/hdf_core/f ...@@ -59,10 +62,10 @@ DAC模块提供的主要接口如下所示,具体API详见//drivers/hdf_core/f
**表 1** DAC驱动API接口功能介绍 **表 1** DAC驱动API接口功能介绍
| 接口名 | 接口描述 | | 接口名 | 接口描述 |
| ------------------------------------------------------------------ | ------------ | | ------------------------------------------------------------------ | ------------ |
| DevHandle DacOpen(uint32_t number) | 打开DAC设备。 | | DevHandle DacOpen(uint32_t number) | 打开DAC设备。|
| void DacClose(DevHandle handle) | 关闭DAC设备。 | | void DacClose(DevHandle handle) | 关闭DAC设备。|
| int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val) | 设置DA目标值。 | | int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val) | 设置DA目标值。 |
### 开发步骤 ### 开发步骤
...@@ -76,78 +79,80 @@ DAC模块提供的主要接口如下所示,具体API详见//drivers/hdf_core/f ...@@ -76,78 +79,80 @@ DAC模块提供的主要接口如下所示,具体API详见//drivers/hdf_core/f
在进行DA转换之前,首先要调用DacOpen打开DAC设备,打开函数如下所示: 在进行DA转换之前,首先要调用DacOpen打开DAC设备,打开函数如下所示:
```c++ ```c
DevHandle DacOpen(uint32_t number); DevHandle DacOpen(uint32_t number);
``` ```
**表 2** DacOpen参数和返回值描述 **表 2** DacOpen参数和返回值描述
| 参数 | 参数描述 | | 参数 | 参数描述 |
| --------- | ---------------- | | --------- | ---------------- |
| number | DAC设备号。 | | number | uint32_t类型,DAC设备号。 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| NULL | 打开DAC设备失败。 | | NULL | 打开DAC设备失败。 |
| 设备句柄 | 打开的DAC设备句柄。 | | 设备句柄 | 打开的DAC设备句柄。 |
假设系统中存在2个DAC设备,编号从0到1,现在打开1号设备。 假设系统中存在2个DAC设备,编号从0到1,现在打开1号设备。
```c++ ```c
DevHandle dacHandle = NULL; // DAC设备句柄 DevHandle dacHandle = NULL; // DAC设备句柄
/* 打开DAC设备 */ // 打开DAC设备
dacHandle = DacOpen(1); dacHandle = DacOpen(1);
if (dacHandle == NULL) { if (dacHandle == NULL) {
HDF_LOGE("DacOpen: failed\n"); HDF_LOGE("DacOpen: open dac fail.\n");
return; return NULL;
} }
``` ```
#### 设置DA目标值 #### 设置DA目标值
```c++ ```c
int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val); int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val);
``` ```
**表 3** DacWrite参数和返回值描述 **表 3** DacWrite参数和返回值描述
| 参数 | 参数描述 | | 参数 | 参数描述 |
| --------- | ------------ | | --------- | ------------ |
| handle | DAC设备句柄。 | | handle | DevHandle类型,DAC设备句柄。 |
| channel | DAC设备通道号。| | channel | uint32_t类型,DAC设备通道号。 |
| val | 设置DA的值。 | | val | uint32_t类型,设置DA的值。 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 写入成功。 | | HDF_SUCCESS | 写入DA目标值成功 |
| 负数 | 写入失败。 | | 负数 | 写入DA目标值失败 |
```c++ ```c
/* 通过DAC_CHANNEL_NUM设备通道写入目标val值 */ // 通过DAC_CHANNEL_NUM设备通道写入目标val值
int32_t ret;
ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val); ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret); HDF_LOGE("DacWrite: tp DAC write reg fail!,ret:%d", ret);
DacClose(dacHandle); DacClose(dacHandle);
return -1; return ret;
} }
``` ```
#### 关闭DAC设备 #### 关闭DAC设备
DAC通信完成之后,需要关闭DAC设备,关闭函数如下所示: DAC通信完成之后,需要关闭DAC设备,关闭函数如下所示:
```c++
```c
void DacClose(DevHandle handle); void DacClose(DevHandle handle);
``` ```
**表 4** DacClose参数和返回值描述 **表 4** DacClose参数和返回值描述
| 参数 | 参数描述 | | 参数 | 参数描述 |
| --------- | ------------ | | --------- | ------------ |
| handle | DAC设备句柄。 | | handle | DAC设备句柄。 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| void | 无 | | 无 | 无 |
关闭DAC设备示例: 关闭DAC设备示例:
```c++ ```c
DacClose(dacHandle); /* 关闭DAC设备 */ DacClose(dacHandle); // 关闭DAC设备
``` ```
## 使用实例 ## 使用实例
...@@ -155,20 +160,22 @@ DacClose(dacHandle); /* 关闭DAC设备 */ ...@@ -155,20 +160,22 @@ DacClose(dacHandle); /* 关闭DAC设备 */
DAC设备的具体使用方式可以参考如下示例代码,示例代码步骤主要如下: DAC设备的具体使用方式可以参考如下示例代码,示例代码步骤主要如下:
1. 根据设备号DAC_DEVICE_NUM打开DAC设备得到设备句柄。 1. 根据设备号DAC_DEVICE_NUM打开DAC设备得到设备句柄。
2. 通过DAC的设备号以及设备通道设置val的值,如果写入失败则关闭设备句柄。 2. 通过DAC的设备号以及设备通道设置val的值,如果写入失败则关闭设备句柄。
3. 访问完毕DAC设备后,则关闭该设备句柄。 3. 访问完毕DAC设备后,则关闭该设备句柄。
运行结果:根据输入的val通过打印日志得到输出的结果。 运行结果:根据输入的val通过打印日志得到输出的结果。
```c++ ```c
#include "dac_if.h" /* DAC标准接口头文件 */ #include "dac_if.h" // DAC标准接口头文件
#include "hdf_log.h" /* 标准日志打印头文件 */ #include "hdf_log.h" // 标准日志打印头文件
/* 设备号0,通道号1 */ // 设备号0,通道号1
#define DAC_DEVICE_NUM 0 #define DAC_DEVICE_NUM 0
#define DAC_CHANNEL_NUM 1 #define DAC_CHANNEL_NUM 1
/* DAC例程总入口 */ // DAC例程总入口
static int32_t TestCaseDac(void) static int32_t TestCaseDac(void)
{ {
// 设置要写入的val值 // 设置要写入的val值
...@@ -176,14 +183,14 @@ static int32_t TestCaseDac(void) ...@@ -176,14 +183,14 @@ static int32_t TestCaseDac(void)
int32_t ret; int32_t ret;
DevHandle dacHandle; DevHandle dacHandle;
/* 打开DAC设备 */ // 打开DAC设备
dacHandle = DacOpen(DAC_DEVICE_NUM); dacHandle = DacOpen(DAC_DEVICE_NUM);
if (dacHandle == NULL) { if (dacHandle == NULL) {
HDF_LOGE("%s: Open DAC%u fail!", __func__, DAC_DEVICE_NUM); HDF_LOGE("%s: Open DAC%u fail!", __func__, DAC_DEVICE_NUM);
return -1; return -1;
} }
/* 写入数据 */ // 写入数据
ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val); ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret); HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret);
...@@ -191,9 +198,9 @@ static int32_t TestCaseDac(void) ...@@ -191,9 +198,9 @@ static int32_t TestCaseDac(void)
return -1; return -1;
} }
/* 访问完毕关闭DAC设备 */ // 访问完毕关闭DAC设备
DacClose(dacHandle); DacClose(dacHandle);
HDF_LOGI("%s: function tests end.", __func__);
return 0; return 0;
} }
``` ```
\ No newline at end of file
...@@ -8,10 +8,13 @@ GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO ...@@ -8,10 +8,13 @@ GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO
GPIO接口定义了操作GPIO管脚的标准方法集合,包括: GPIO接口定义了操作GPIO管脚的标准方法集合,包括:
- 设置管脚方向:方向可以是输入或者输出(暂不支持高阻态)。 - 设置、获取管脚方向:方向可以是输入或者输出(暂不支持高阻态)。
- 读写管脚电平值:电平值可以是低电平或高电平。
- 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式。 - 读、写管脚电平值:电平值可以是低电平或高电平。
- 使能和禁止管脚中断:禁止或使能管脚中断。
- 设置、取消管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式。取消一个管脚的中断服务函数。
- 使能、禁止管脚中断:禁止或使能管脚中断。
### 基本概念 ### 基本概念
...@@ -19,11 +22,11 @@ GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。 ...@@ -19,11 +22,11 @@ GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。
- GPIO输入 - GPIO输入
输入是检测各个引脚上的电平状态,高电平或者低电平状态。常见的输入模式有:模拟输入、浮空输入、上拉输入、下拉输入。 输入是检测各个引脚上的电平状态,高电平或者低电平状态。常见的输入模式有:模拟输入、浮空输入、上拉输入、下拉输入。
- GPIO输出 - GPIO输出
输出是当需要控制引脚电平的高低时需要用到输出功能。常见的输出模式有:开漏输出、推挽输出、复用开漏输出、复用推挽输出。 输出是当需要控制引脚电平的高低时需要用到输出功能。常见的输出模式有:开漏输出、推挽输出、复用开漏输出、复用推挽输出。
### 运作机制 ### 运作机制
...@@ -34,7 +37,9 @@ GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。 ...@@ -34,7 +37,9 @@ GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。
GPIO模块各分层作用: GPIO模块各分层作用:
- 接口层提供操作GPIO管脚的标准方法。 - 接口层提供操作GPIO管脚的标准方法。
- 核心层主要提供GPIO管脚资源匹配,GPIO管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互,供芯片厂家快速接入HDF框架。 - 核心层主要提供GPIO管脚资源匹配,GPIO管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互,供芯片厂家快速接入HDF框架。
- 适配层主要是将钩子函数的功能实例化,实现具体的功能。 - 适配层主要是将钩子函数的功能实例化,实现具体的功能。
**图 1** GPIO统一服务模式结构图 **图 1** GPIO统一服务模式结构图
...@@ -45,36 +50,36 @@ GPIO模块各分层作用: ...@@ -45,36 +50,36 @@ GPIO模块各分层作用:
### 场景介绍 ### 场景介绍
GPIO仅是一个软件层面的概念,主要工作是GPIO管脚资源管理。开发者可以使用提供的GPIO操作接口,实现对管脚控制。 GPIO主要是对GPIO管脚资源进行管理。开发者可以使用提供的GPIO操作接口,实现对管脚控制的具体控制。
### 接口说明 ### 接口说明
GPIO模块提供的主要接口如表1所示。 GPIO模块提供的主要接口如表1所示。具体API详见//drivers/hdf_core/framework/include/platform/gpio_if.h。
**表1** GPIO驱动API接口功能介绍 **表 1** GPIO驱动API接口功能介绍
| 接口名 | 描述 | | 接口名 | 描述 |
| ------------------------------------------------------------ | ------------------------------ | | ------------------------------------------------------------ | ------------------------------ |
| GpioGetByName(const char *gpioName) | 获取GPIO管脚ID | | GpioGetByName(const char \*gpioName) | 获取GPIO管脚ID |
| int32_t GpioRead(uint16_t gpio, uint16_t *val) | 读GPIO管脚电平值 | | int32_t GpioRead(uint16_t gpio, uint16_t \*val) | 读GPIO管脚电平值 |
| int32_t GpioWrite(uint16_t gpio, uint16_t val) | 写GPIO管脚电平值 | | int32_t GpioWrite(uint16_t gpio, uint16_t val) | 写GPIO管脚电平值 |
| int32_t GpioGetDir(uint16_t gpio, uint16_t *dir) | 获取GPIO管脚方向 | | int32_t GpioGetDir(uint16_t gpio, uint16_t \*dir) | 获取GPIO管脚方向 |
| int32_t GpioSetDir(uint16_t gpio, uint16_t dir) | 设置GPIO管脚方向 | | int32_t GpioSetDir(uint16_t gpio, uint16_t dir) | 设置GPIO管脚方向 |
| int32_t GpioUnsetIrq(uint16_t gpio, void *arg); | 取消GPIO管脚对应的中断服务函数 | | int32_t GpioUnsetIrq(uint16_t gpio, void \*arg) | 取消GPIO管脚对应的中断服务函数 |
| int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg) | 设置GPIO管脚对应的中断服务函数 | | int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void \*arg) | 设置GPIO管脚对应的中断服务函数 |
| int32_t GpioEnableIrq(uint16_t gpio) | 使能GPIO管脚中断 | | int32_t GpioEnableIrq(uint16_t gpio) | 使能GPIO管脚中断 |
| int32_t GpioDisableIrq(uint16_t gpio) | 禁止GPIO管脚中断 | | int32_t GpioDisableIrq(uint16_t gpio) | 禁止GPIO管脚中断 |
>![](../public_sys-resources/icon-note.gif) **说明:**<br> >![](../public_sys-resources/icon-note.gif) **说明:**<br>
>本文涉及GPIO的所有接口,支持内核态及用户态使用。 >本文涉及GPIO的所有接口,支持内核态及用户态使用。
### 开发步骤 ### 开发步骤
GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如下图所示。 GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如图2所示。
**图1** GPIO使用流程图 **图 2** GPIO使用流程图
![image](figures/GPIO使用流程图.png "GPIO使用流程图") ![GPIO使用流程图](figures/GPIO使用流程图.png)
#### 确定GPIO管脚号 #### 确定GPIO管脚号
...@@ -82,31 +87,31 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流 ...@@ -82,31 +87,31 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流
- 根据SOC芯片规则进行计算 - 根据SOC芯片规则进行计算
不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。 不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。
- Hi3516DV300 - Hi3516DV300
控制器管理12组GPIO管脚,每组8个。 控制器管理12组GPIO管脚,每组8个。
GPIO号 = GPIO组索引 (0~11) \* 每组GPIO管脚数(8) + 组内偏移 GPIO号 = GPIO组索引 (0~11) \* 每组GPIO管脚数(8) + 组内偏移
举例:GPIO10_3的GPIO号 = 10 \* 8 + 3 = 83 举例:GPIO10_3的GPIO号 = 10 \* 8 + 3 = 83
- Hi3518EV300 - Hi3518EV300
控制器管理10组GPIO管脚,每组10个。 控制器管理10组GPIO管脚,每组10个。
GPIO号 = GPIO组索引 (0~9) \* 每组GPIO管脚数(10) + 组内偏移 GPIO号 = GPIO组索引 (0~9) \* 每组GPIO管脚数(10) + 组内偏移
举例:GPIO7_3的GPIO管脚号 = 7 \* 10 + 3 = 73 举例:GPIO7_3的GPIO管脚号 = 7 \* 10 + 3 = 73
- 通过管脚别名获取 - 通过管脚别名获取
调用接口GpioGetByName进行获取,入参是该管脚的别名,接口返回值是管脚的全局ID。 调用接口GpioGetByName进行获取,入参是该管脚的别名,接口返回值是管脚的全局ID。
```c ```c
GpioGetByName(const char *gpioName); GpioGetByName(const char *gpioName);
``` ```
#### 设置GPIO管脚方向 #### 设置GPIO管脚方向
...@@ -116,15 +121,15 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流 ...@@ -116,15 +121,15 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流
int32_t GpioSetDir(uint16_t gpio, uint16_t dir); int32_t GpioSetDir(uint16_t gpio, uint16_t dir);
``` ```
**表2** GpioSetDir参数和返回值描述 **表 2** GpioSetDir参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | ------------------ | | ---------- | ------------------ |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| dir | 待设置的方向值 | | dir | uint16_t类型,待设置的方向值 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | HDF_SUCCESS | 设置GPIO管脚方向成功 |
| 负数 | 设置失败 | | 负数 | 设置GPIO管脚方向失败 |
假设需要将GPIO管脚3的方向配置为输出,其使用示例如下: 假设需要将GPIO管脚3的方向配置为输出,其使用示例如下:
...@@ -132,8 +137,8 @@ int32_t GpioSetDir(uint16_t gpio, uint16_t dir); ...@@ -132,8 +137,8 @@ int32_t GpioSetDir(uint16_t gpio, uint16_t dir);
int32_t ret; int32_t ret;
ret = GpioSetDir(3, GPIO_DIR_OUT); // 将3号GPIO管脚配置为输出 ret = GpioSetDir(3, GPIO_DIR_OUT); // 将3号GPIO管脚配置为输出
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioSetDir: failed, ret %d\n", ret); HDF_LOGE("GpioSetDir: gpio set dir fail, ret:%d\n", ret);
return ret; return ret;
} }
``` ```
...@@ -146,15 +151,15 @@ if (ret != 0) { ...@@ -146,15 +151,15 @@ if (ret != 0) {
int32_t GpioGetDir(uint16_t gpio, uint16_t *dir); int32_t GpioGetDir(uint16_t gpio, uint16_t *dir);
``` ```
**表3** GpioGetDir参数和返回值描述 **表 3** GpioGetDir参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | ------------------ | | ---------- | ------------------ |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| dir | 获取到的方向值指针 | | dir | uint16_t类型指针,获取到的方向值 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | HDF_SUCCESS | 获取GPIO管脚方向成功 |
| 负数 | 设置失败 | | 负数 | 获取GPIO管脚方向失败 |
假设需要获取GPIO管脚3的方向,其使用示例如下: 假设需要获取GPIO管脚3的方向,其使用示例如下:
...@@ -163,8 +168,8 @@ int32_t ret; ...@@ -163,8 +168,8 @@ int32_t ret;
uin16_t dir; uin16_t dir;
ret = GpioGetDir(3, &dir); // 获取3号GPIO管脚方向 ret = GpioGetDir(3, &dir); // 获取3号GPIO管脚方向
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioGetDir: failed, ret %d\n", ret); HDF_LOGE("GpioGetDir: gpio get dir fail, ret:%d\n", ret);
return ret; return ret;
} }
``` ```
...@@ -177,15 +182,15 @@ if (ret != 0) { ...@@ -177,15 +182,15 @@ if (ret != 0) {
int32_t GpioRead(uint16_t gpio, uint16_t *val); int32_t GpioRead(uint16_t gpio, uint16_t *val);
``` ```
**表4** GpioRead参数和返回值描述 **表 4** GpioRead参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | -------------------- | | ---------- | -------------------- |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| val | 接收读取电平值的指针 | | val | uint16_t类型指针,接收读取电平值 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 读取成功 | | HDF_SUCCESS | 读取GPIO管脚电平值成功 |
| 负数 | 读取失败 | | 负数 | 读取GPIO管脚电平值失败 |
假设需要读取GPIO管脚3的电平值,其使用示例如下: 假设需要读取GPIO管脚3的电平值,其使用示例如下:
...@@ -194,8 +199,8 @@ int32_t ret; ...@@ -194,8 +199,8 @@ int32_t ret;
uint16_t val; uint16_t val;
ret = GpioRead(3, &val); // 读取3号GPIO管脚电平值 ret = GpioRead(3, &val); // 读取3号GPIO管脚电平值
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioRead: failed, ret %d\n", ret); HDF_LOGE("GpioRead: gpio read fail, ret:%d\n", ret);
return ret; return ret;
} }
``` ```
...@@ -208,15 +213,15 @@ if (ret != 0) { ...@@ -208,15 +213,15 @@ if (ret != 0) {
int32_t GpioWrite(uint16_t gpio, uint16_t val); int32_t GpioWrite(uint16_t gpio, uint16_t val);
``` ```
**表5** GpioWrite参数和返回值描述 **表 5** GpioWrite参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | ------------------ | | ---------- | ------------------ |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| val | 待写入的电平值 | | val | uint16_t类型,待写入的电平值 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 写入成功 | | HDF_SUCCESS | 写入GPIO管脚电平值成功 |
| 负数 | 写入失败 | | 负数 | 写入GPIO管脚电平值失败 |
假设需要给GPIO管脚3写入低电平值,其使用示例如下: 假设需要给GPIO管脚3写入低电平值,其使用示例如下:
...@@ -224,8 +229,8 @@ int32_t GpioWrite(uint16_t gpio, uint16_t val); ...@@ -224,8 +229,8 @@ int32_t GpioWrite(uint16_t gpio, uint16_t val);
int32_t ret; int32_t ret;
ret = GpioWrite(3, GPIO_VAL_LOW); // 给3号GPIO管脚写入低电平值 ret = GpioWrite(3, GPIO_VAL_LOW); // 给3号GPIO管脚写入低电平值
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioRead: failed, ret %d\n", ret); HDF_LOGE("GpioWrite: gpio write fail, ret:%d\n", ret);
return ret; return ret;
} }
``` ```
...@@ -238,17 +243,17 @@ if (ret != 0) { ...@@ -238,17 +243,17 @@ if (ret != 0) {
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg); int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);
``` ```
**表6** GpioSetIrq参数和返回值描述 **表 6** GpioSetIrq参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | ------------------------ | | ---------- | ------------------------ |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| mode | 中断触发模式 | | mode | uint16_t类型,中断触发模式 |
| func | 中断服务程序 | | func | 函数指针,中断服务程序 |
| arg | 传递给中断服务程序的入参 | | arg | 无类型指针,传递给中断服务程序的入参 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | HDF_SUCCESS | 设置GPIO管脚中断成功 |
| 负数 | 设置失败 | | 负数 | 设置GPIO管脚中断失败 |
> ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**<br> > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**<br>
> 同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。 > 同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。
...@@ -261,15 +266,15 @@ int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg); ...@@ -261,15 +266,15 @@ int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);
int32_t GpioUnsetIrq(uint16_t gpio, void *arg); int32_t GpioUnsetIrq(uint16_t gpio, void *arg);
``` ```
**表7** GpioUnsetIrq参数和返回值描述 **表 7** GpioUnsetIrq参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | -------------- | | ---------- | -------------- |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| arg | GPIO中断数据 | | arg | 无类型指针,GPIO中断数据 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 取消成功 | | HDF_SUCCESS | 取消GPIO管脚中断成功 |
| 负数 | 取消失败 | | 负数 | 取消GPIO管脚中断失败 |
#### 使能GPIO管脚中断 #### 使能GPIO管脚中断
...@@ -279,14 +284,14 @@ int32_t GpioUnsetIrq(uint16_t gpio, void *arg); ...@@ -279,14 +284,14 @@ int32_t GpioUnsetIrq(uint16_t gpio, void *arg);
int32_t GpioEnableIrq(uint16_t gpio); int32_t GpioEnableIrq(uint16_t gpio);
``` ```
**表8** GpioEnableIrq参数和返回值描述 **表 8** GpioEnableIrq参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| ---------- | -------------- | | ---------- | -------------- |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 使能成功 | | HDF_SUCCESS | 使能GPIO管脚中断成功 |
| 负数 | 使能失败 | | 负数 | 使能GPIO管脚中断失败 |
> ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**<br> > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**<br>
> 必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。 > 必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。
...@@ -298,51 +303,51 @@ int32_t GpioEnableIrq(uint16_t gpio); ...@@ -298,51 +303,51 @@ int32_t GpioEnableIrq(uint16_t gpio);
```c ```c
int32_t GpioDisableIrq(uint16_t gpio); int32_t GpioDisableIrq(uint16_t gpio);
``` ```
**表9** GpioDisableIrq参数和返回值描述 **表 9** GpioDisableIrq参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述**|
| ---------- | -------------- | | ---------- | -------------- |
| gpio | GPIO管脚号 | | gpio | uint16_t类型,GPIO管脚号 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 禁止成功 | | HDF_SUCCESS | 禁止GPIO管脚中断成功 |
| 负数 | 禁止失败 | | 负数 | 禁止GPIO管脚中断失败 |
中断相关操作示例: 中断相关操作示例:
```c ```c
/* 中断服务函数*/ // 中断服务函数
int32_t MyCallBackFunc(uint16_t gpio, void *data) int32_t MyCallBackFunc(uint16_t gpio, void *data)
{ {
HDF_LOGI("%s: gpio:%u interrupt service in data\n", __func__, gpio); HDF_LOGI("MyCallBackFunc: gpio:%u interrupt service in data.\n", gpio);
return 0; return HDF_SUCCESS;
} }
int32_t ret; int32_t ret;
/* 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发 */ // 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发
ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL); ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL);
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret); HDF_LOGE("GpioSetIrq: gpio set irq fail, ret:%d\n", ret);
return ret; return ret;
} }
/* 使能3号GPIO管脚中断 */ // 使能3号GPIO管脚中断
ret = GpioEnableIrq(3); ret = GpioEnableIrq(3);
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret); HDF_LOGE("GpioEnableIrq: gpio enable irq fail, ret:%d\n", ret);
return ret; return ret;
} }
/* 禁止3号GPIO管脚中断 */ // 禁止3号GPIO管脚中断
ret = GpioDisableIrq(3); ret = GpioDisableIrq(3);
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret); HDF_LOGE("GpioDisableIrq: gpio disable irqfail, ret:%d\n", ret);
return ret; return ret;
} }
/* 取消3号GPIO管脚中断服务程序 */ // 取消3号GPIO管脚中断服务程序
ret = GpioUnsetIrq(3, NULL); ret = GpioUnsetIrq(3, NULL);
if (ret != 0) { if (ret != HDF_SUCCESS) {
HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret); HDF_LOGE("GpioUnSetIrq: gpio unset irq fail, ret:%d\n", ret);
return ret; return ret;
} }
``` ```
...@@ -363,65 +368,66 @@ if (ret != 0) { ...@@ -363,65 +368,66 @@ if (ret != 0) {
static uint32_t g_irqCnt; static uint32_t g_irqCnt;
/* 中断服务函数*/ // 中断服务函数
static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data) static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data)
{ {
HDF_LOGE("%s: irq triggered! on gpio:%u, in data", __func__, gpio); HDF_LOGE("TestCaseGpioIrqHandler: irq triggered! on gpio:%u, in data", gpio);
g_irqCnt++; /* 如果中断服务函数触发执行,则将全局中断计数加1 */ g_irqCnt++; // 如果中断服务函数触发执行,则将全局中断计数加1
return GpioDisableIrq(gpio); return GpioDisableIrq(gpio);
} }
/* 测试用例函数 */ // 测试用例函数
static int32_t TestCaseGpioIrqEdge(void) static int32_t TestCaseGpioIrqEdge(void)
{ {
int32_t ret; int32_t ret;
uint16_t valRead; uint16_t valRead;
uint16_t mode; uint16_t mode;
uint16_t gpio = 83; /* 待测试的GPIO管脚号 */ uint16_t gpio = 84; // 待测试的GPIO管脚号
uint32_t timeout; uint32_t timeout;
/* 将管脚方向设置为输出 */ // 将管脚方向设置为输出
ret = GpioSetDir(gpio, GPIO_DIR_OUT); ret = GpioSetDir(gpio, GPIO_DIR_OUT);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret); HDF_LOGE("TestCaseGpioIrqEdge: set dir fail! ret:%d\n", ret);
return ret; return ret;
} }
/* 先禁止该管脚中断 */ // 先禁止该管脚中断
ret = GpioDisableIrq(gpio); ret = GpioDisableIrq(gpio);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret); HDF_LOGE("TestCaseGpioIrqEdge: disable irq fail! ret:%d\n", ret);
return ret; return ret;
} }
/* 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发 */ // 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发
mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING;
HDF_LOGE("%s: mode:%0x\n", __func__, mode); HDF_LOGE("TestCaseGpioIrqEdge: mode:%0x\n", mode);
ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL); ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret); HDF_LOGE("TestCaseGpioIrqEdge: set irq fail! ret:%d\n", ret);
return ret; return ret;
} }
/* 使能此管脚中断 */ // 使能此管脚中断
ret = GpioEnableIrq(gpio); ret = GpioEnableIrq(gpio);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret); HDF_LOGE("TestCaseGpioIrqEdge: enable irq fail! ret:%d\n", ret);
(void)GpioUnsetIrq(gpio, NULL); (void)GpioUnsetIrq(gpio, NULL);
return ret; return ret;
} }
g_irqCnt = 0; /* 清除全局计数器 */ g_irqCnt = 0; // 清除全局计数器
timeout = 0; /* 等待时间清零 */ timeout = 0; // 等待时间清零
/* 等待此管脚中断服务函数触发,等待超时时间为1000毫秒 */ // 等待此管脚中断服务函数触发,等待超时时间为1000毫秒
while (g_irqCnt <= 0 && timeout < 1000) { while (g_irqCnt <= 0 && timeout < 1000) {
(void)GpioRead(gpio, &valRead); (void)GpioRead(gpio, &valRead);
(void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
HDF_LOGE("%s: wait irq timeout:%u\n", __func__, timeout); HDF_LOGE("TestCaseGpioIrqEdge: wait irq timeout:%u\n", timeout);
OsalMDelay(200); /* wait for irq trigger */ OsalMDelay(200); // 等待中断触发
timeout += 200; timeout += 200;
} }
(void)GpioUnsetIrq(gpio, NULL); (void)GpioUnsetIrq(gpio, NULL);
HDF_LOGI("TestCaseGpioIrqEdge: function tests end, g_irqCnt:%u", g_irqCnt);
return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE;
} }
``` ```
\ No newline at end of file
# HDMI # HDMI
## 概述 ## 概述
...@@ -19,18 +18,25 @@ HDMI(High Definition Multimedia Interface),即高清多媒体接口,是H ...@@ -19,18 +18,25 @@ HDMI(High Definition Multimedia Interface),即高清多媒体接口,是H
- HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。 - HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。
### 运作机制 ### 运作机制
在HDF框架中,HDMI的接口适配模式采用独立服务模式(如图1)。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用率。 在HDF框架中,HDMI的接口适配模式拟采用独立服务模式(如图1)。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用率。
HDMI模块各分层作用:
- 接口层提供打开HDMI设备、启动HDMI传输、停止HDMI传输、声音图像消隐设置、设置色彩深度、获取色彩深度、设置视频属性、获取视频属性、设置HDR属性、读取Sink端原始EDID数据、注册HDMI热插拔检测回调函数、注销HDMI热插拔检测回调函数、关闭HDMI设备的接口。
- 核心层主要提供HDMI控制器的打开、关闭及管理的能力,通过钩子函数与适配层交互。
**图 1** HDMI独立服务模式 - 适配层主要是将钩子函数的功能实例化,实现具体的功能。
![image1](figures/独立服务模式结构图.png) **图 1** HDMI独立服务模式
![HDMI独立服务模式](figures/独立服务模式结构图.png)
### 约束与限制 ### 约束与限制
HDMI模块当前仅支持轻量和小型系统内核(LiteOS) HDMI模块当前仅支持轻量和小型系统内核(LiteOS),暂无实际适配驱动
## 开发指导 ## 开发指导
...@@ -41,6 +47,7 @@ HDMI具有体积小、传输速率高、传输带宽宽、兼容性好、能同 ...@@ -41,6 +47,7 @@ HDMI具有体积小、传输速率高、传输带宽宽、兼容性好、能同
### 接口说明 ### 接口说明
HdmiCntlrOps定义: HdmiCntlrOps定义:
```c ```c
struct HdmiCntlrOps { struct HdmiCntlrOps {
void (*hardWareInit)(struct HdmiCntlr *cntlr); void (*hardWareInit)(struct HdmiCntlr *cntlr);
...@@ -80,17 +87,17 @@ struct HdmiCntlrOps { ...@@ -80,17 +87,17 @@ struct HdmiCntlrOps {
}; };
``` ```
**表1** HdmiCntlrOps结构体成员的回调函数功能说明 **表 1** HdmiCntlrOps结构体成员的回调函数功能说明
| 函数成员 | 入参 | 出参 | 返回值 | 功能 | | 函数成员 | 入参 | 出参 | 返回值 | 功能 |
| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- | | ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- |
| hardWareInit | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 初始化HDMI硬件 | | hardWareInit | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 初始化HDMI硬件 |
| hardWareStatusGet | **cntlr**:结构体指针,核心层HDMI控制器<br /> | **status**:HDMI硬件状态 ; | 无 | 获取HDMI当前硬件状态 | | hardWareStatusGet | **cntlr**:结构体指针,核心层HDMI控制器<br /> | **status**:HDMI硬件状态 ; | 无 | 获取HDMI当前硬件状态 |
| controllerReset | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 复位HDMI控制器 | | controllerReset | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 复位HDMI控制器 |
| hotPlugStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool:HDMI热插拔状态 | 获取HDMI热插拔状态 | | hotPlugStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool:HDMI热插拔状态 | 获取HDMI热插拔状态 |
| hotPlugInterruptStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool:HDMI热插拔中断状态 | 获取HDMI热插拔中断状态 | | hotPlugInterruptStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool:HDMI热插拔中断状态 | 获取HDMI热插拔中断状态 |
| lowPowerSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能低功耗 | | lowPowerSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能低功耗 |
| tmdsModeSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**mode**:TMDS模式 | 无 | 无 | 设置TMDS模式 | | tmdsModeSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**mode**:TMDS模式 | 无 | 无 | 设置TMDS模式 |
| tmdsConfigSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**mode**:TMDS参数 | 无 | HDF_STATUS相关状态 | 配置TMDS参数 | | tmdsConfigSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**mode**:TMDS参数 | 无 | HDF_STATUS相关状态 | 配置TMDS参数 |
| infoFrameEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**infoFrameType**:packet类型<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能infoFrame | | infoFrameEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**infoFrameType**:packet类型<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能infoFrame |
| infoFrameSend | **cntlr**:结构体指针,核心层HDMI控制器<br />**infoFrameType**:packet类型<br />**data**:infoFrame数据<br />**len**:数据长度 | 无 | HDF_STATUS相关状态 | 发送infoFrame | | infoFrameSend | **cntlr**:结构体指针,核心层HDMI控制器<br />**infoFrameType**:packet类型<br />**data**:infoFrame数据<br />**len**:数据长度 | 无 | HDF_STATUS相关状态 | 发送infoFrame |
...@@ -120,20 +127,30 @@ struct HdmiCntlrOps { ...@@ -120,20 +127,30 @@ struct HdmiCntlrOps {
### 开发步骤 ### 开发步骤
HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以及实例化HDMI控制器对象。 HDMI模块适配包含以下四个步骤:
- 实例化驱动入口
- 实例化驱动入口:
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
- 配置属性文件: - 配置属性文件
- 在device_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加hdmi_config.hcs器件属性文件。 - 【可选】添加hdmi_config.hcs器件属性文件。
- 实例化HDMI控制器对象: - 实例化HDMI控制器对象
- 初始化HdmiCntlr成员。 - 初始化HdmiCntlr成员。
- 实例化HdmiCntlr成员HdmiCntlrOps方法集合。 - 实例化HdmiCntlr成员HdmiCntlrOps方法集合。
- 驱动调试
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,HDMI传输等。
1. 实例化驱动入口 1. 实例化驱动入口
驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
...@@ -148,16 +165,14 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -148,16 +165,14 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
.Bind = HdmiAdapterBind, .Bind = HdmiAdapterBind,
.Init = HdmiAdapterInit, .Init = HdmiAdapterInit,
.Release = HdmiAdapterRelease, .Release = HdmiAdapterRelease,
.moduleName = "adapter_hdmi_driver",//【必要】与HCS里面的名字匹配 .moduleName = "adapter_hdmi_driver", // 【必要且与HCS文件中里面的moduleName匹配】
}; };
HDF_INIT(g_hdmiDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 HDF_INIT(g_hdmiDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中
``` ```
2. 配置属性文件 2. 配置属性文件
完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在hdmi_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层HdmiCntlr相关成员的默认值或限制范围有密切关系。 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在hdmi_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层HdmiCntlr相关成员的默认值或限制范围有密切关系。从第一个节点开始配置具体HDMI控制器信息,此节点并不表示某一路HDMI控制器,而是代表一个资源性质设备,用于描述一类HDMI控制器的信息。本例只有一个HDMI控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在hdmi_config文件中增加对应的器件属性。
从第一个节点开始配置具体HDMI控制器信息,此节点并不表示某一路HDMI控制器,而是代表一个资源性质设备,用于描述一类HDMI控制器的信息。本例只有一个HDMI控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在hdmi_config文件中增加对应的器件属性。
- device_info.hcs配置参考 - device_info.hcs配置参考
...@@ -181,8 +196,8 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -181,8 +196,8 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
- hdmi_config.hcs 配置参考 - hdmi_config.hcs 配置参考
```c ```c
root { root {
platform { platform {
hdmi_config { hdmi_config {
template hdmi_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省。 template hdmi_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省。
match_attr = ""; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致。 match_attr = ""; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致。
...@@ -227,7 +242,7 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -227,7 +242,7 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
} }
``` ```
3. 实例化控制器对象 3. 实例化HDMI控制器对象
最后一步,完成驱动入口注册之后,要以核心层HdmiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化HdmiCntlr成员HdmiCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 最后一步,完成驱动入口注册之后,要以核心层HdmiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化HdmiCntlr成员HdmiCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
...@@ -245,7 +260,6 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -245,7 +260,6 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
uint32_t irqNum; //【必要】中断号 uint32_t irqNum; //【必要】中断号
}; };
/* HdmiCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值。 */
struct HdmiCntlr { struct HdmiCntlr {
struct IDeviceIoService service; struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj; struct HdfDeviceObject *hdfDevObj;
...@@ -320,16 +334,17 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -320,16 +334,17 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
**返回值:** **返回值:**
HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) HDF_STATUS相关状态 (表2为部分展示,如需使用其他状态,可参考//drivers/hdf_core/framework/include/utils/hdf_base.h中HDF_STATUS的定义)。
**表 2** HDF_STATUS相关状态说明
|状态(值)|状态描述| | 状态(值) | 问题描述 |
|:-|:-| | -------- | -------- |
|HDF_ERR_INVALID_OBJECT|控制器对象非法| | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
|HDF_ERR_INVALID_PARAM |参数非法| | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
|HDF_ERR_MALLOC_FAIL |内存分配失败| | HDF_ERR_IO | I/O&nbsp;错误 |
|HDF_ERR_IO |I/O错误| | HDF_SUCCESS | 初始化成功 |
|HDF_SUCCESS |传输成功| | HDF_FAILURE | 初始化失败 |
|HDF_FAILURE |传输失败|
**函数说明:** **函数说明:**
...@@ -358,13 +373,13 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -358,13 +373,13 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提
obj->service = &cntlr->service; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 obj->service = &cntlr->service; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提
ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】初始化cntlr,失败则goto __ERR。 ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】初始化cntlr,失败则goto __ERR。
... ......
ret = HdmiAdapterHostParse(host, obj); //【必要】初始化host对象的相关属性,失败则goto __ERR。 ret = HdmiAdapterHostParse(host, obj); //【必要】初始化host对象的相关属性,失败则goto __ERR。
... ......
ret = HdmiAdapterHostInit(host, cntlr); // 厂商自定义的初始化,失败则goto __ERR。 ret = HdmiAdapterHostInit(host, cntlr); // 厂商自定义的初始化,失败则goto __ERR。
... ......
ret = HdmiCntlrAdd(cntlr); // 调用核心层函数,失败则goto __ERR。 ret = HdmiCntlrAdd(cntlr); // 调用核心层函数,失败则goto __ERR。
... ......
HDF_LOGD("HdmiAdapterBind: success."); HDF_LOGD("HdmiAdapterBind: success.");
return HDF_SUCCESS; return HDF_SUCCESS;
__ERR: __ERR:
...@@ -416,11 +431,13 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以 ...@@ -416,11 +431,13 @@ HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以
static void HdmiAdapterRelease(struct HdfDeviceObject *obj) static void HdmiAdapterRelease(struct HdfDeviceObject *obj)
{ {
struct HdmiCntlr *cntlr = NULL; struct HdmiCntlr *cntlr = NULL;
... ......
cntlr = (struct HdmiCntlr *)obj->service; // 这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数。 cntlr = (struct HdmiCntlr *)obj->service; // 这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数。
... ......
HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// 厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化。 HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// 厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化。
} }
``` ```
4. 驱动调试
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,HDMI传输等。
# I2C # I2C
## 概述 ## 概述
### 功能简介 ### 功能简介
...@@ -16,12 +15,14 @@ I2C数据的传输必须以一个起始信号作为开始条件,以一个结 ...@@ -16,12 +15,14 @@ I2C数据的传输必须以一个起始信号作为开始条件,以一个结
I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。
I2C接口定义了完成I2C传输的通用方法集合,包括: I2C接口定义了完成I2C传输的通用方法集合,包括:
- I2C控制器管理:打开或关闭I2C控制器 - I2C控制器管理:打开或关闭I2C控制器
- I2C消息传输:通过消息传输结构体数组进行自定义传输 - I2C消息传输:通过消息传输结构体数组进行自定义传输
**图1** I2C物理连线示意图 **图 1** I2C物理连线示意图
![image](figures/I2C物理连线示意图.png "I2C物理连线示意图") ![I2C物理连线示意图](figures/I2C物理连线示意图.png)
## 使用指导 ## 使用指导
...@@ -33,9 +34,9 @@ I2C通常用于与各类支持I2C协议的传感器、执行器或输入输出 ...@@ -33,9 +34,9 @@ I2C通常用于与各类支持I2C协议的传感器、执行器或输入输出
I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/i2c_if.h。 I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/i2c_if.h。
**表1** I2C驱动API接口功能介绍 **表 1** I2C驱动API接口功能介绍
| 接口名 | 接口描述 | | 接口名 | 接口描述 |
| -------- | -------- | | -------- | -------- |
| DevHandle I2cOpen(int16_t number) | 打开I2C控制器 | | DevHandle I2cOpen(int16_t number) | 打开I2C控制器 |
| void I2cClose(DevHandle handle) | 关闭I2C控制器 | | void I2cClose(DevHandle handle) | 关闭I2C控制器 |
...@@ -45,9 +46,9 @@ I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/ ...@@ -45,9 +46,9 @@ I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/
使用I2C设备的一般流程如下图所示。 使用I2C设备的一般流程如下图所示。
**图2** I2C设备使用流程图 **图 2** I2C设备使用流程图
![image](figures/I2C设备使用流程图.png "I2C设备使用流程图") ![I2C设备使用流程图](figures/I2C设备使用流程图.png)
#### 打开I2C控制器 #### 打开I2C控制器
...@@ -58,11 +59,11 @@ I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/ ...@@ -58,11 +59,11 @@ I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/
DevHandle I2cOpen(int16_t number); DevHandle I2cOpen(int16_t number);
``` ```
**表2** I2cOpen参数和返回值描述 **表 2** I2cOpen参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| -------- | -------- | | -------- | -------- |
| number | I2C控制器号 | | number | int16_t类型,I2C控制器号 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| NULL | 打开I2C控制器失败 | | NULL | 打开I2C控制器失败 |
| 设备句柄 | 打开的I2C控制器设备句柄 | | 设备句柄 | 打开的I2C控制器设备句柄 |
...@@ -70,57 +71,55 @@ DevHandle I2cOpen(int16_t number); ...@@ -70,57 +71,55 @@ DevHandle I2cOpen(int16_t number);
假设系统中存在8个I2C控制器,编号从0到7,以下代码示例为获取3号控制器: 假设系统中存在8个I2C控制器,编号从0到7,以下代码示例为获取3号控制器:
```c ```c
DevHandle i2cHandle = NULL; /* I2C控制器句柄 / DevHandle i2cHandle = NULL; // I2C控制器句柄
/* 打开I2C控制器 */ // 打开I2C控制器
i2cHandle = I2cOpen(3); i2cHandle = I2cOpen(3);
if (i2cHandle == NULL) { if (i2cHandle == NULL) {
HDF_LOGE("I2cOpen: failed\n"); HDF_LOGE("I2cOpen: i2c open fail.\n");
return; return NULL;
} }
``` ```
#### 进行I2C通信 #### 进行I2C通信
消息传输 消息传输
```c ```c
int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count); int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count);
``` ```
**表3** I2cTransfer参数和返回值描述 **表 3** I2cTransfer参数和返回值描述
| **参数** | **参数描述** | | **参数** | **参数描述** |
| -------- | -------- | | -------- | -------- |
| handle | I2C控制器设备句柄 | | handle | DevHandle类型,I2C控制器设备句柄 |
| msgs | 待传输数据的消息结构体数组 | | msgs | 结构体指针,待传输数据的消息结构体数组 |
| count | 消息数组长度 | | count | int16_t类型,消息数组长度 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 正整数 | 成功传输的消息结构体数目 | | 正整数 | 成功传输的消息结构体数目 |
| 负数 | 执行失败 | | 负数 | 执行失败 |
I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。组合读写示例: I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。组合读写示例:
```c ```c
int32_t ret; int32_t ret;
uint8_t wbuff[2] = { 0x12, 0x13 }; uint8_t wbuff[2] = { 0x12, 0x13 };
uint8_t rbuff[2] = { 0 }; uint8_t rbuff[2] = { 0 };
struct I2cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ struct I2cMsg msgs[2]; // 自定义传输的消息结构体数组
msgs[0].buf = wbuff; /* 写入的数据 */ msgs[0].buf = wbuff; // 写入的数据
msgs[0].len = 2; /* 写入数据长度为2 */ msgs[0].len = 2; // 写入数据长度为2
msgs[0].addr = 0x5A; /* 写入设备地址为0x5A */ msgs[0].addr = 0x5A; // 写入设备地址为0x5A
msgs[0].flags = 0; /* 传输标记为0,默认为写 */ msgs[0].flags = 0; // 传输标记为0,默认为写
msgs[1].buf = rbuff; /* 要读取的数据 */ msgs[1].buf = rbuff; // 要读取的数据
msgs[1].len = 2; /* 读取数据长度为2 */ msgs[1].len = 2; // 读取数据长度为2
msgs[1].addr = 0x5A; /* 读取设备地址为0x5A */ msgs[1].addr = 0x5A; // 读取设备地址为0x5A
msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ置位 */ msgs[1].flags = I2C_FLAG_READ // I2C_FLAG_READ置位
/* 进行一次自定义传输,传输的消息个数为2 */ // 进行一次自定义传输,传输的消息个数为2
ret = I2cTransfer(i2cHandle, msgs, 2); ret = I2cTransfer(i2cHandle, msgs, 2);
if (ret != 2) { if (ret != 2) {
HDF_LOGE("I2cTransfer: failed, ret %d\n", ret); HDF_LOGE("I2cTransfer: i2c transfer fail, ret:%d\n", ret);
return; return HDF_FAILURE;
} }
``` ```
...@@ -142,19 +141,18 @@ I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所述: ...@@ -142,19 +141,18 @@ I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所述:
void I2cClose(DevHandle handle); void I2cClose(DevHandle handle);
``` ```
**表4** I2cClose参数和返回值描述 **表 4** I2cClose参数和返回值描述
| 参数 | 参数描述 | | 参数 | 参数描述 |
| -------- | -------- | | -------- | -------- |
| handle | I2C控制器设备句柄 | | handle | DevHandle类型,I2C控制器设备句柄 |
关闭I2C控制器示例: 关闭I2C控制器示例:
```c ```c
I2cClose(i2cHandle); /* 关闭I2C控制器 */ I2cClose(i2cHandle); // 关闭I2C控制器
``` ```
### 使用示例 ### 使用示例
本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册