鸿蒙OS2.0 设备开发之Hi3861-基础功能汇总 原创 精华

发布于 2021-9-28 12:34
浏览
12收藏

@toc

这是一篇讲解在鸿蒙2.0全量源码中开发Hi3861的常用功能汇总,可帮助我们快速配置GPIO 如,如何实现PWM、I2C、ADC等。

1.基本IO功能

1.1 输出

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

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

需要注意的是,有些GPIO还需要设置复用功能,可能默认不是普通GPIO模式。
这时候就需要使用hi_io_set_func函数;以GPIO9为例,设为普通IO;

hi_io_set_func(BEEP_IO,HI_IO_FUNC_GPIO_9_GPIO_OUT);

1.2 输入

分三步,使能、配置输入方式(上下拉)、获取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 2021.09.23
IoTGpioGetInputVal(GPIO_idx,1); //0-低 1-高

1.3 系统延时

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

usleep(us); //   delay us
osDelay(us);//   delay us
hi_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通道0
IoTPwmInit(PWM0); 
//==配置pwm0输出参数:占空比50%、频率160M/80000=2KHz 
IoTPwmStart(PWM0,50,80000); 
IoTPwmStop(PWM0);  //以上pwm操作基于iot_pwm.h 封装的函数,实质是封装hi_pwm.h

hi_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。我已修正该封装,顺利驱动了蜂鸣器。

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转换。
鸿蒙OS2.0 设备开发之Hi3861-基础功能汇总-开源基础软件社区

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发、收数据一次需要发送两个地址(设备地址、目标寄存器地址),如何实现?---把第二个地址当作数据发送。

小总结

  • [x] 基本IO功能
  • [x] I2C相关API
  • [x] PWM相关API
  • [x] 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()

我写了开发记录PPT,需要的可以去我B站私信自提点我拿资料
鸿蒙OS2.0 设备开发之Hi3861-基础功能汇总-开源基础软件社区
鸿蒙OS2.0 设备开发之Hi3861-基础功能汇总-开源基础软件社区

5.演示案例及其链接

学会使用以上API之后,就可以实现各种功能,比如在HiSpark Wi-Fi IOT智能家居套件中提供的各种拓展板(炫彩板、环境监测板、交通灯板),学习过程中做了一些演示视频,有兴趣可点击查看:
i2c通信–连接MPU6050点我见演示视频
ADC、PWM控制LED、蜂鸣器、舵机、各种拓展板点我见演示视频

6.其他功能(wifi入网、web编程)

鸿蒙OS的目标是万物互联,其实更有意思的是Hi3861支持鸿蒙OS-轻量化小型系统并且具备wifi入网能力,连接上网,就可以说做很多事儿。比如视频末尾使用手机控制舵机,想想还能做啥呢? 无钥匙开门、开关灯、控制家电、控制设备……
下一期讲讲wifi入网,实现无钥匙开宿舍门。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-9-28 12:34:00修改
13
收藏 12
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐