写点什么

OpenHarmony 设备开发常用接口

作者:鸿蒙之旅
  • 2023-04-26
    广东
  • 本文字数:3346 字

    阅读完需:约 11 分钟

作者:鸿蒙元气

团队:坚果派

欢迎通过主页或者私信联系我或者联系坚果,加入坚果派,一起学习 OpenHarmony/HarmonyOS 应用开发。

今天在学习设备开发的时候,也是遇到一些问题,按照我的风格,肯定是要记录一下的,那么我们就开始今天的内容

有时候,接口不够用,针对 GPIO 口复用,

这时候就需要使用 hi_io_set_func 函数;以 GPIO9 为例,设为普通 IO;

#define TEST_GPIO 9 // for hispark_pegasus#define GPIO_FUNC 0 // for hispark_pegasushi_io_set_func(TEST_GPIO,GPIO_FUNC);
复制代码

1.基本 IO 功能

输出

分两步,使能、配置输出值;

IoTGpioInit(GPIO_idx); IoTGpioSetDir(GPIO_idx,1);//1-输出 0-输入IoTGpioSetOutputVal(GPIO_idx,1); //0-低 1-高
复制代码

输入

分三步,使能、配置输入方式(上下拉)、获取 io 电平;

IoTGpioInit(GPIO_idx); IoTGpioSetDir(GPIO_idx,0);//1-输出 0-输入hi_io_set_pull(GPIO_idx, HI_IO_PULL_UP); //==上拉输入IoSetPull(GPIO_idx, HI_IO_PULL_UP); //自行封装在iot_gpio.h IoTGpioGetInputVal(GPIO_idx,1); //0-低 1-高
复制代码

系统延时

系统延时函数比较多,具体区别看使用效果。常用的有

usleep(us); //   delay usosDelay(us);//   delay ushi_udelay(us);// delay_us int32
复制代码

2.PWM 输出

Hi3861 共有 6 路 PWM。Hi3861-2.0 版本 PWM 使用流程:

  1. 初始化 io

  2. io 复用为 pwm

  3. 使能 pwm 通道

  4. 开始输出 pwm

  5. 停止输出 pwm

//==初始化 GPIO9 IoTGpioInit(PWM0_TEST_GPIO); //==初始化 GPIO9 的pwm复用功能hi_io_set_func(PWM0_TEST_GPIO,HI_IO_FUNC_GPIO_9_PWM0_OUT); //==初始化pwm通道0IoTPwmInit(PWM0); //==配置pwm0输出参数:占空比50%、频率160M/80000=2KHz IoTPwmStart(PWM0,50,80000); IoTPwmStop(PWM0);  //以上pwm操作基于iot_pwm.h 封装的函数,实质是封装hi_pwm.hhi_pwm_init(hi_pwm_port port);hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq);hi_pwm_stop(hi_pwm_port port); //以上pwm操作基于hi_pwm.h 封装的函数
复制代码

2.1 PWM 常用 API

iot_pwm.h 封装的函数中,与 hi_pwm.h 封装的函数入口参数不同

iot_pwm.h 中定义的 IoTPwmStart();

unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq) port:0-5  pwm通道号 duty:1-99 占空比,不可为0\100 freq:>160M/65535 = 2441 与pwm频率有关,不是直接设置unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq){    unsigned short hiDuty;    unsigned short hiFreq;    hiFreq = (unsigned short)(CLK_160M / freq);    hiDuty = (duty * hiFreq) / DUTY_MAX;    return hi_pwm_start((hi_pwm_port)port, hiDuty, freq);    // 源码: return hi_pwm_start((hi_pwm_port)port, hiDuty, hiFreq);     //最后一个参数为分频系数,传入时不能先使用160M/freq 这样不对, 2021.09.26 自信修正}
复制代码


hi_pwm.h 中定义的 hi_pwm_start();

按配置的参数输出PWM信号。PWM信号占空比=duty/freq。频率=时钟源频率/freq。* @param  port [IN] PWM端口号。* @param  duty [IN] PWM占空比计数值。取值范围为:[1, 65535]。默认值为750。CNend* @param  freq [IN] 分频倍数。取值范围为:[1, 65535]。默认值为1500。hi_u32 hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq);
复制代码


可以看出,函数封装后可更方便的使用PWM,直接设置占空比(1-99)。但发现iot_pwm.h封装的IoTPwmStart()频率有错误,导致pwm不正常,原因是在IoTPwmStart()中,hiFreq已经是计算后的实际频率,不是分频系数。给hi_pwm_start()传入数据时,不应该传入hiFreq,应该还是最初的freq。我已修正该封装,顺利驱动了蜂鸣器。1.
复制代码

pwm 总结,无论使用 IoTPwmStart()还是 hi_pwm_start(),实际输出频率 hiFreq

hiFreq = (unsigned short)(CLK_160M / freq);//注:hi_u32 hi_pwm_set_clock(hi_pwm_clk_source clk_type); //==设置时钟源,默认160M
复制代码


pwm 总结,使用 IoTPwmStart(port,duty,freq)实际占空比 hiDuty:

hiFreq = (unsigned short)(CLK_160M / freq);hiDuty = (duty * hiFreq) / 100;   //所占总周期的百分比
复制代码


pwm 总结,使用 hi_pwm_start(port,duty,freq)实际占空比 hiDuty:

hiDuty = (duty) / 65535;
复制代码


2.2 如何控制舵机

hi3861-PWM 其他信息 –理论频率 [1, 65.535]KHz (CLK_160M / freq) < 0xFFFF(65535) 分频系数 freq [2442,160M] –实际频率不会很低,具体没测,没示波器, 数字舵机(T=20ms)无法控制。 模拟低频 pwm: 延时+io 输出(0-1)模拟实现 控制精度要求不是很高可以这么做。期待官方出解决方案。

3.ADC 实现

Hi3861 共有 7 路 ADC , 各通道见 hi3861 手册表 6.2(截取如下) 一共 8 个 ADC 通道,ADC0–ADC7 但通道 7 为参考电压,不能 adc 转换。

3.1 ADC 常用 API

Hi3861-2.0 版本 ADC 使用流程:1.初始化 io、2. io 为输入、3. 配置输入模式、4. 读取 AD 数据

  IoTGpioInit(pinID);  IoTGpioSetDir(pinID,IOT_GPIO_DIR_IN);  hi_io_set_func(pinID,HI_IO_FUNC_GPIO_pinID_GPIO);  //可选,上拉等:  //IoSetPull(pinID, HI_IO_PULL_UP);  hi_io_set_pull(pinID,HI_IO_PULL_UP);  hi_adc_read(HI_ADC_CHANNEL_0,&data,HI_ADC_EQU_MODEL_1,HI_ADC_CUR_BAIS_DEFAULT, 0);     
复制代码


3.2 ADC 使用注意事项

Hi3861-2.0 版本 i2c hi_adc_read()参数解析

hi_u32 hi_adc_read(hi_adc_channel_index channel, hi_u16 *data, hi_adc_equ_model_sel equ_model, hi_adc_cur_bais cur_bais, hi_u16 delay_cnt);channel: 0-7,通道0-7 *data :采集的AD数据equ_model:平均算法模式,将采集后的数据平均再使用,取1就是原始数据,不平均。cur_bais: 模拟电源控制,一般设置为默认delay_cnt:从配置采样到启动采样的延时时间计数,一次计数是334ns,其值需在0~0xFF0之间
复制代码

获取数据是指针传值。

4. 驱动 i2c

4.1 i2c API

Hi3861-2.0 版本 i2c 使用流程(两路 i2c):1.初始化 io、2. 复用 io 为 i2c、3. 初始化对应 i2c 通道、4. 读取/发送数据。

//==i2c1     IoTGpioInit(I2C1_SDA_IO13);     IoTGpioInit(I2C1_SCL_IO14); //初始化io接口    hi_io_set_func(I2C1_SDA_IO13, HI_IO_FUNC_GPIO_13_I2C0_SDA);    hi_io_set_func(I2C1_SCL_IO14 , HI_IO_FUNC_GPIO_14_I2C0_SCL); //==GPIO 复用为I2C0    hi_i2c_init(OLED_I2C_IDX, OLED_I2C_BAUDRATE);                //==使能i2c1设置传输速率 OLED_I2C_IDX值为1    hi_i2c_write((hi_i2c_idx)id, OLED_I2C_ADDR, &i2cData);//==i2c0     IoTGpioInit(MPU_SDA_IO0);    IoTGpioInit(MPU_SCL_IO1);    hi_io_set_func(MPU_SDA_IO0, HI_IO_FUNC_GPIO_13_I2C0_SDA);    hi_io_set_func(MPU_SCL_IO1, HI_IO_FUNC_GPIO_14_I2C0_SCL);    hi_i2c_init(MPU_I2C_IDX, MPU_I2C_BAUDRATE); //==使能i2c1设置传输速率 OLED_I2C_IDX值为0    hi_i2c_write((hi_i2c_idx)id, ((MPU_ADDR<<1)|0), &i2cData);  //==发送器件地址+写命令+目标寄存器reg + 写入的data    hi_i2c_read((hi_i2c_idx)id,((MPU_ADDR<<1)|1), &i2cData);    //==发送器件地址+读命令+目标寄存器reg + 读取的data
复制代码


4.2 i2c 使用提示

Hi3861-2.0 版本 i2c 一些重要定义:

读取、发送的数据是一个结构体; 数据均使用指针的形式传值; 定义的函数每次只能收、发 8 位数据;

i2c 函数的一些思考:

如果读取一个寄存器地址为 16bit 的器件怎么办?----截断,分两次发送; 对 mpu6050 发、收数据一次需要发送两个地址(设备地址、目标寄存器地址),如何实现?---把第二个地址当作数据发送。


小总结

  • 基本 IO 功能

  • I2C 相关 API

  • PWM 相关 API

  • ADC 相关 API 常用的头文件

#include <stdio.h>#include <unistd.h>#include "ohos_init.h"#include "cmsis_os2.h"  //==系统依赖 包括usleep() osdelay()#include "iot_gpio.h"  //==IoTGpioInit()、IoTGpioSetDir()、IoTGpioSetOutPutVal()#include "iot_pwm.h"   //==IoTPwmStart()、IoTPwmInit()#include "hi_io.h"     //==hi_io_set_func()、hi_io_set_pull()#include "hi_pwm.h"    //==hi_pwm_start()#include "hi_adc.h"    //==hi_adc_read()#include "hi_time.h"  //==hi_udelay()
复制代码


发布于: 刚刚阅读数: 2
用户头像

鸿蒙之旅

关注

还未添加个人签名 2022-10-26 加入

还未添加个人简介

评论

发布
暂无评论
OpenHarmony设备开发常用接口_OpenHarmony_鸿蒙之旅_InfoQ写作社区