OpenHarmony智能开发套件[驱动开发篇(下)

本章将介绍如何IO控制温湿度传感器,可燃气体传感器,RGB灯,人体红外传感器,光敏电阻,Oled显示
首页 新闻资讯 行业资讯 OpenHarmony智能开发套件[驱动开发篇(下)

166911d13819670bb47592a6eed40b9d7b090b.png

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

前言

前面介绍了OpenHarmony智能开发套件驱动开发篇·上,下面我们接着介绍驱动开发,本章将介绍如何IO控制温湿度传感器,可燃气体传感器,RGB灯,人体红外传感器,光敏电阻,Oled显示屏。

驱动开发

环境监测板

环境检测板上一共有三个模块,AHT20数字温湿度传感器,蜂鸣器,MQ-2可燃气体传感器。蜂鸣器的使用在上一篇已经提及过,为了方便学习,本次只介绍温湿度传感器,可燃气体传感器的IO控制,蜂鸣器的结合使用可以放在以后的综合案例中去说。

温湿度传感器

案例:每隔1s,获取一次温湿度,打印在终端

  1. 新建样例目录
    applications/sample/wifi-iot/app/aht20

  2. 新建源文件和gn文件
    applications/sample/wifi-iot/app/aht20/aht20Test.c
    applications/sample/wifi-iot/app/aht20/BUILD.gn

  3. 补充文件

applications/sample/wifi-iot/app/aht20/aht20.c

applications/sample/wifi-iot/app/aht20/aht20.h

aht20.c

/*
 * Copyright (C) 2021 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */#include"aht20.h"#include<stdio.h>#include<string.h>#include<unistd.h>#include"iot_i2c.h"#include"iot_errno.h"#defineAHT20_I2C_IDX0#defineAHT20_STARTUP_TIME20*1000// 上电启动时间#defineAHT20_CALIBRATION_TIME40*1000// 初始化(校准)时间#defineAHT20_MEASURE_TIME75*1000// 测量时间#defineAHT20_DEVICE_ADDR0x38#defineAHT20_READ_ADDR((0x38<<1)|0x1)#defineAHT20_WRITE_ADDR((0x38<<1)|0x0)#defineAHT20_CMD_CALIBRATION0xBE// 初始化(校准)命令#defineAHT20_CMD_CALIBRATION_ARG00x08#defineAHT20_CMD_CALIBRATION_ARG10x00/**
 * 传感器在采集时需要时间,主机发出测量指令(0xAC)后,延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。
 * 若状态比特位[Bit7]为0代表数据可正常读取,为1时传感器为忙状态,主机需要等待数据处理完成。
 **/#defineAHT20_CMD_TRIGGER0xAC// 触发测量命令#defineAHT20_CMD_TRIGGER_ARG00x33#defineAHT20_CMD_TRIGGER_ARG10x00// 用于在无需关闭和再次打开电源的情况下,重新启动传感器系统,软复位所需时间不超过20 毫秒#defineAHT20_CMD_RESET0xBA// 软复位命令#defineAHT20_CMD_STATUS0x71// 获取状态命令/**
 * STATUS 命令回复:
 * 1. 初始化后触发测量之前,STATUS 只回复 1B 状态值;
 * 2. 触发测量之后,STATUS 回复6B: 1B 状态值 + 2B 湿度 + 4b湿度 + 4b温度 + 2B 温度
 *      RH = Srh / 2^20 * 100%
 *      T  = St  / 2^20 * 200 - 50
 **/#defineAHT20_STATUS_BUSY_SHIFT7// bit[7] Busy indication#defineAHT20_STATUS_BUSY_MASK(0x1<<AHT20_STATUS_BUSY_SHIFT)#defineAHT20_STATUS_BUSY(status)((status&AHT20_STATUS_BUSY_MASK)>>AHT20_STATUS_BUSY_SHIFT)#defineAHT20_STATUS_MODE_SHIFT5// bit[6:5] Mode Status#defineAHT20_STATUS_MODE_MASK(0x3<<AHT20_STATUS_MODE_SHIFT)#defineAHT20_STATUS_MODE(status)((status&AHT20_STATUS_MODE_MASK)>>AHT20_STATUS_MODE_SHIFT)// bit[4] Reserved#defineAHT20_STATUS_CALI_SHIFT3// bit[3] CAL Enable#defineAHT20_STATUS_CALI_MASK(0x1<<AHT20_STATUS_CALI_SHIFT)#defineAHT20_STATUS_CALI(status)((status&AHT20_STATUS_CALI_MASK)>>AHT20_STATUS_CALI_SHIFT)// bit[2:0] Reserved#defineAHT20_STATUS_RESPONSE_MAX6#defineAHT20_RESLUTION(1<<20)// 2^20#defineAHT20_MAX_RETRY10// typedef struct {//     /** Pointer to the buffer storing data to send *///     unsigned char *sendBuf;//     /** Length of data to send *///     unsigned int  sendLen;//     /** Pointer to the buffer for storing data to receive *///     unsigned char *receiveBuf;//     /** Length of data received *///     unsigned int  receiveLen;// } IotI2cData;staticuint32_tAHT20_Read(uint8_t*buffer,uint32_tbuffLen){// IotI2cData data = { 0 };// data.receiveBuf = buffer;// data.receiveLen = buffLen;// uint32_t retval = I2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, data.receiveBuf );// if (retval != IOT_SUCCESS) {//     printf("I2cRead() failed, %0X!\n", retval);//     return retval;// }// return IOT_SUCCESS;uint32_tretval=IoTI2cRead(AHT20_I2C_IDX,AHT20_READ_ADDR,buffer,buffLen);if(retval!=IOT_SUCCESS){printf("I2cRead() failed, %0X!\n",retval);returnretval;}returnIOT_SUCCESS;}staticuint32_tAHT20_Write(uint8_t*buffer,uint32_tbuffLen){// IotI2cData data = { 0 };// data.sendBuf = buffer;// data.sendLen = buffLen;// uint32_t retval = IoTI2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, &data);// if (retval != IOT_SUCCESS) {//     printf("I2cWrite(%02X) failed, %0X!\n", buffer[0], retval);//     return retval;// }// return IOT_SUCCESS;uint32_tretval=IoTI2cWrite(AHT20_I2C_IDX,AHT20_READ_ADDR,buffer,buffLen);if(retval!=IOT_SUCCESS){printf("I2cRead() failed, %0X!\n",retval);returnretval;}returnIOT_SUCCESS;}// 发送获取状态命令staticuint32_tAHT20_StatusCommand(void){uint8_tstatusCmd[]={AHT20_CMD_STATUS};returnAHT20_Write(statusCmd,sizeof(statusCmd));}// 发送软复位命令staticuint32_tAHT20_ResetCommand(void){uint8_tresetCmd[]={AHT20_CMD_RESET};returnAHT20_Write(resetCmd,sizeof(resetCmd));}// 发送初始化校准命令staticuint32_tAHT20_CalibrateCommand(void){uint8_tclibrateCmd[]={AHT20_CMD_CALIBRATION,AHT20_CMD_CALIBRATION_ARG0,AHT20_CMD_CALIBRATION_ARG1};returnAHT20_Write(clibrateCmd,sizeof(clibrateCmd));}// 读取温湿度值之前, 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字),// 如果不为1,要发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。uint32_tAHT20_Calibrate(void){uint32_tretval=0;uint8_tbuffer[AHT20_STATUS_RESPONSE_MAX]={AHT20_CMD_STATUS};memset(&buffer,0x0,sizeof(buffer));retval=AHT20_StatusCommand();if(retval!=IOT_SUCCESS){returnretval;}retval=AHT20_Read(buffer,sizeof(buffer));if(retval!=IOT_SUCCESS){returnretval;}if(AHT20_STATUS_BUSY(buffer[0])||!AHT20_STATUS_CALI(buffer[0])){retval=AHT20_ResetCommand();if(retval!=IOT_SUCCESS){returnretval;}usleep(AHT20_STARTUP_TIME);retval=AHT20_CalibrateCommand();usleep(AHT20_CALIBRATION_TIME);returnretval;}returnIOT_SUCCESS;}// 发送 触发测量 命令,开始测量uint32_tAHT20_StartMeasure(void){uint8_ttriggerCmd[]={AHT20_CMD_TRIGGER,AHT20_CMD_TRIGGER_ARG0,AHT20_CMD_TRIGGER_ARG1};returnAHT20_Write(triggerCmd,sizeof(triggerCmd));}// 接收测量结果,拼接转换为标准值uint32_tAHT20_GetMeasureResult(float*temp,float*humi){uint32_tretval=0,i=0;if(temp==NULL||humi==NULL){returnIOT_FAILURE;}uint8_tbuffer[AHT20_STATUS_RESPONSE_MAX]={0};memset(&buffer,0x0,sizeof(buffer));retval=AHT20_Read(buffer,sizeof(buffer));// recv status command resultif(retval!=IOT_SUCCESS){returnretval;}for(i=0;AHT20_STATUS_BUSY(buffer[0])&&i<AHT20_MAX_RETRY;i++){// printf("AHT20 device busy, retry %d/%d!\r\n", i, AHT20_MAX_RETRY);usleep(AHT20_MEASURE_TIME);retval=AHT20_Read(buffer,sizeof(buffer));// recv status command resultif(retval!=IOT_SUCCESS){returnretval;}}if(i>=AHT20_MAX_RETRY){printf("AHT20 device always busy!\r\n");returnIOT_FAILURE;}uint32_thumiRaw=buffer[1];humiRaw=(humiRaw<<8)|buffer[2];humiRaw=(humiRaw<<4)|((buffer[3]&0xF0)>>4);*humi=humiRaw/(float)AHT20_RESLUTION*100;uint32_ttempRaw=buffer[3]&0x0F;tempRaw=(tempRaw<<8)|buffer[4];tempRaw=(tempRaw<<8)|buffer[5];*temp=tempRaw/(float)AHT20_RESLUTION*200-50;// printf("humi = %05X, %f, temp= %05X, %f\r\n", humiRaw, *humi, tempRaw, *temp);returnIOT_SUCCESS;}

aht20.h

/*
 * Copyright (C) 2021 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */#ifndefAHT20_H#defineAHT20_H#include<stdint.h>uint32_tAHT20_Calibrate(void);uint32_tAHT20_StartMeasure(void);uint32_tAHT20_GetMeasureResult(float*temp,float*humi);#endif// AHT20_H

这两个文件,相当于给我们提供了控制aht20数字温湿度传感器的API,通过网上各种温湿度传感器的学习也发现了,这两个文件是必备的,笔者也是直接从源码提供的demo中直接。贴出来了。下面也详细给大家介绍以下每一个函数怎么去使用。其中标号1至5是不需要我们手动去调用他的,6至8是我们比较常用的。

  1. 从传感器中读取数据。

staticuint32_tAHT20_Read(uint8_t*buffer,uint32_tbuffLen)

参数解释:

  • buffer:存储读取数据的缓冲区的指针。

  • buffLen:缓冲区的长度。

  • 返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于从传感器中读取数据。它使用 IoTI2cRead 函数从指定的地址读取数据到缓冲区中。

  1. 向传感器中写入数据。

staticuint32_tAHT20_Write(uint8_t*buffer,uint32_tbuffLen)

参数解释:

  • buffer:存储要写入传感器的数据的缓冲区的指针。

  • buffLen:缓冲区的长度。

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

实现过程:该函数用于向传感器写入数据。它使用 IoTI2cWrite 函数将数据从缓冲区写入指定的地址。

  1. 获取传感器状态

staticuint32_tAHT20_StatusCommand(void)

参数:无

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于发送获取状态命令给传感器。它构造一个包含命令的缓冲区,然后使用 AHT20_Write 函数发送该命令。

  1. 软复位传感器。

staticuint32_tAHT20_ResetCommand(void)

参数:无

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于发送软复位命令给传感器。它构造一个包含命令的缓冲区,然后使用 AHT20_Write 函数发送该命令。

  1. 初始化传感器。

staticuint32_tAHT20_CalibrateCommand(void)

参数:无

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于发送初始化校准命令给传感器。它构造一个包含命令和参数的缓冲区,然后使用 AHT20_Write 函数发送该命令。

  1. 校准传感器。

uint32_tAHT20_Calibrate(void)

参数:无

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于校准传感器。它首先发送获取状态命令,然后读取状态字并检查校准使能位。如果校准使能位不为1或传感器处于忙状态,它会发送软复位命令并等待一段时间后再发送初始化校准命令。

  1. 发送命令,传感器开始测量。

uint32_tAHT20_StartMeasure(void)

参数:无

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于发送触发测量命令给传感器,以开始测量过程。它构造一个包含命令和参数的缓冲区,然后使用 AHT20_Write 函数发送该命令。

  1. 获取传感器的测量结果。

uint32_tAHT20_GetMeasureResult(float*temp,float*humi)

参数解释:

  • temp:用于存储温度值的指针。

  • humi:用于存储湿度值的指针。

返回值:一个 uint32_t 类型的整数,表示执行操作的结果。

该函数用于接收测量结果并将其转换为标准值。它首先从传感器读取状态命令的结果,然后根据状态字判断传感器的忙闲状态。如果传感器忙碌,函数会等待一段时间后再次读取状态命令的结果。如果传感器一直忙碌,函数返回失败。如果传感器空闲,函数会从缓冲区中提取湿度和温度的原始值,并将其转换为标准值,然后存储在指定的变量中。最后,函数返回成功或失败的结果。

  1. 编写源文件aht20Test.c。

#include<stdio.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"#include"hi_gpio.h"#include"hi_io.h"// I2C控制器#include"hi_i2c.h"// aht20温湿度传感器#include"aht20.h"// 一些宏定义 如 IOT_SUCCESS#include"iot_errno.h"// 样例主函数staticvoidahtMain(void){// 设置引脚的功能,hi_io_set_func(HI_IO_NAME_GPIO_13,HI_IO_FUNC_GPIO_13_I2C0_SDA);hi_io_set_func(HI_IO_NAME_GPIO_14,HI_IO_FUNC_GPIO_14_I2C0_SCL);// 以特定的波特率初始化I2C设备hi_i2c_init(HI_I2C_IDX_0,4000);// 定义返回值uint32_tretval=0;retval=AHT20_Calibrate();while(retval!=IOT_SUCCESS){printf("传感器校准失败!\r\n");osDelay(50);}while(1){// 定义温湿度变量floattemp=0.0,humi=0.0;// 命令传感器开始工作retval=AHT20_StartMeasure();if(retval!=IOT_SUCCESS){printf("传感器工作异常!\r\n");}// 读取传感器的测量值retval=AHT20_GetMeasureResult(&temp,&humi);if(retval!=IOT_SUCCESS){printf("传感器数值读取失败!\r\n");}else{printf("当前温度:%.2f 当前湿度:%.2f.\r\n",temp,humi);}// 每隔1s读取一次传感器数据osDelay(100);}}// 样例测试入口staticvoidaht20Test(void){osThreadAttr_tattr={"ahtMain",0,NULL,0,NULL,1024,osPriorityNormal,0,0};osThreadNew((osThreadFunc_t)ahtMain,NULL,&attr);}APP_FEATURE_INIT(aht20Test);
  1. 编写BUILD.gn (app目录下的BUILD.gn文件记得也修改好,这里就不多演示了)。

static_library("aht20"){
    sources = [
        "aht20.c",
        "aht20Test.c",
    ]
    include_dirs = [
        "//commonlibrary/utils_lite/include/",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
        "//base/iothardware/peripheral/interfaces/inner_api",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
    ]
}
  1. 编译,烧录,串口调试,观察控制台上的输出。

OpenHarmony智能开发套件[驱动开发篇·下]-开源基础软件社区

那么到这里,温湿度传感器最简单的一个案例就介绍到这里。

可燃气体传感器

案例:每隔1s,获取一次可燃气体传感器测量的电阻值,打印在终端

他会用到hi_adc.h库下的hi_adc_read这个接口,从单个ADC通道读取一个数据。

hi_u32hi_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:要读取的ADC通道,类型为hi_adc_channel_index。

  • data:数据存储地址,类型为指向hi_u16类型的指针。

  • equ_model:平均算法模式,类型为hi_adc_equ_model_sel。

  • cur_bais:模拟电源控制,类型为hi_adc_cur_bais。

  • delay_cnt:从配置采样到启动采样的延时时间计数,每次计数为334纳秒,取值范围为0~0xFF0。

返回值:

  • HI_ERR_SUCCESS:成功。

  • 其他值:失败。

其中 hi_adc_equ_model_sel 定义为如下的枚举类型。

typedefenum{HI_ADC_EQU_MODEL_1,/**< 0:The average value is not used.
                                      CNcomment:1次平均,即不进行
                                      平均 CNend */HI_ADC_EQU_MODEL_2,/**< 1:2-time average algorithm mode.
                                      CNcomment:2次平均算法模式 CNend */HI_ADC_EQU_MODEL_4,/**< 2:4-time average algorithm mode.
                                      CNcomment:4次平均算法模式 CNend */HI_ADC_EQU_MODEL_8,/**< 3:8-time average algorithm mode.
                                      CNcomment:8次平均算法模式 CNend */HI_ADC_EQU_MODEL_BUTT,}hi_adc_equ_model_sel;

hi_adc_cur_bais

typedefenum{HI_ADC_CUR_BAIS_DEFAULT,/**< 0:Auto control.
                                      CNcomment:自动识别模式 */HI_ADC_CUR_BAIS_AUTO,/**< 1:Auto control.
                                      CNcomment:自动识别模式 */HI_ADC_CUR_BAIS_1P8V,/**< 2:Manual control, AVDD=1.8V.
                                      CNcomment:手动控制,AVDD=1.8V */HI_ADC_CUR_BAIS_3P3V,/**< 3:Manual control, AVDD=3.3V.
                                      CNcomment:手动控制,AVDD=3.3V */HI_ADC_CUR_BAIS_BUTT,}hi_adc_cur_bais;
  1. 新建样例目录
    applications/sample/wifi-iot/app/gas

  2. 新建源文件和gn文件
    applications/sample/wifi-iot/app/gas/gasTest.c
    applications/sample/wifi-iot/app/gas/BUILD.gn

  3. 编写源文件gasTest.c

#include<stdio.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"#include"hi_gpio.h"#include"hi_io.h"// adc#include"hi_adc.h"// 一些宏定义 如 IOT_SUCCESS#include"iot_errno.h"#defineGAS_SENSOR_CHAN_NAME5// 主函数staticvoidgasMain(void){// 定义数据变量floatgasSensorResistance=0.0f;while(1){unsignedshortdata=0;intretval;retval=hi_adc_read(GAS_SENSOR_CHAN_NAME,&data,2,0,0);if(retval==IOT_SUCCESS){floatVx=data*1.8*4/4096;gasSensorResistance=5/Vx-1;printf("当前可燃气体传感器获取的电阻值为:%.2f\r\n",gasSensorResistance);}else{printf("\r\n hi_adc_read fail, retval=%d",retval);}osDelay(100);}}// 样例测试入口staticvoidgasTest(void){osThreadAttr_tattr={"gasMain",0,NULL,0,NULL,1024,osPriorityNormal,0,0};osThreadNew((osThreadFunc_t)gasMain,NULL,&attr);}APP_FEATURE_INIT(gasTest);

while循环中的部分是从源码提供的demo中贴过来的,涉及到一些电路问题,还没有研究这一块。

// Vcc            ADC            GND
//  |    ______   |     ______   |
//  +---| MG-2 |---+---| 1kom |---+
//       ------         ------
// 查阅原理图,ADC 引脚位于 1K 电阻和燃气传感器之间,燃气传感器另一端接在 5V 电源正极上
// 串联电路电压和阻止成正比:
// Vx / 5 == 1kom / (1kom + Rx)
//   => Rx + 1 == 5/Vx
//   =>  Rx = 5/Vx - 1
  1. 编写BUILD.gn (app目录下的BUILD.gn文件记得也修改好,这里就不多演示了)。

static_library("gas"){
    sources = [
        "gasTest.c",
    ]
    include_dirs = [
        "//commonlibrary/utils_lite/include/",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
        "//base/iothardware/peripheral/interfaces/inner_api",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
    ]
}
  1. 编译,烧录,串口调试,观察控制台上的输出。

OpenHarmony智能开发套件[驱动开发篇·下]-开源基础软件社区

RGB板

三色灯

绝大多数可见光可用三色光(红、绿、蓝)的不同强度的混合来表示,即RGB颜色模型。

R/G/B取值范围:0~255。黑色(0,0,0),白色(255,255,255),红色(255,0,0)、绿色(0,255,0)、蓝色(0,0,255)。

  • 可表示颜色数:256256256=16777216色。

  • 红色:28引脚,GPIO-10 / PWM1。

  • 绿色:29引脚,GPIO-11 / PWM2。

  • 蓝色:30引脚,GPIO-12 / PWM3。

下面直接上案例吧,RGB的效果,实际上就是改变PWM的占空比,实现红绿蓝的混色效果。

  1. 新建样例目录
    applications/sample/wifi-iot/app/rgb

  2. 新建源文件和gn文件
    applications/sample/wifi-iot/app/rgb/rgb.c
    applications/sample/wifi-iot/app/rgb/BUILD.gn

  3. 编写源文件rgb.c

#include<stdio.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"#include"iot_gpio.h"#include"hi_io.h"#include"hi_pwm.h"staticvoidrgbDemo(){IoTGpioInit(HI_IO_NAME_GPIO_10);IoTGpioInit(HI_IO_NAME_GPIO_11);IoTGpioInit(HI_IO_NAME_GPIO_12);hi_io_set_func(HI_IO_NAME_GPIO_10,HI_IO_FUNC_GPIO_10_PWM1_OUT);hi_io_set_func(HI_IO_NAME_GPIO_11,HI_IO_FUNC_GPIO_11_PWM2_OUT);hi_io_set_func(HI_IO_NAME_GPIO_12,HI_IO_FUNC_GPIO_12_PWM3_OUT);IoTGpioSetDir(HI_IO_NAME_GPIO_10,IOT_GPIO_DIR_OUT);IoTGpioSetDir(HI_IO_NAME_GPIO_11,IOT_GPIO_DIR_OUT);IoTGpioSetDir(HI_IO_NAME_GPIO_12,IOT_GPIO_DIR_OUT);IoTPwmInit(HI_PWM_PORT_PWM1);// 红IoTPwmInit(HI_PWM_PORT_PWM2);// 绿IoTPwmInit(HI_PWM_PORT_PWM3);// 蓝while(1){for(inti=1;i<100;i++){IoTPwmStart(HI_PWM_PORT_PWM1,1,4000);IoTPwmStart(HI_PWM_PORT_PWM2,100-i,4000);IoTPwmStart(HI_PWM_PORT_PWM3,i,4000);usleep(20*1000);IoTPwmStop(HI_PWM_PORT_PWM1);IoTPwmStop(HI_PWM_PORT_PWM2);IoTPwmStop(HI_PWM_PORT_PWM3);}for(inti=1;i<100;i++){IoTPwmStart(HI_PWM_PORT_PWM1,i,4000);IoTPwmStart(HI_PWM_PORT_PWM2,1,4000);IoTPwmStart(HI_PWM_PORT_PWM3,100-i,4000);usleep(20*1000);IoTPwmStop(HI_PWM_PORT_PWM1);IoTPwmStop(HI_PWM_PORT_PWM2);IoTPwmStop(HI_PWM_PORT_PWM3);}for(inti=1;i<100;i++){IoTPwmStart(HI_PWM_PORT_PWM1,100-i,4000);IoTPwmStart(HI_PWM_PORT_PWM2,i,4000);IoTPwmStart(HI_PWM_PORT_PWM3,1,4000);usleep(20*1000);IoTPwmStop(HI_PWM_PORT_PWM1);IoTPwmStop(HI_PWM_PORT_PWM2);IoTPwmStop(HI_PWM_PORT_PWM3);}}}staticvoidrgbTest(void){osThreadAttr_tattr={"rgbDemo",0,NULL,0,NULL,1024,osPriorityNormal,0,0};osThreadNew((osThreadFunc_t)rgbDemo,NULL,&attr);}APP_FEATURE_INIT(rgbTest);
  1. 编写BUILD.gn (app目录下的BUILD.gn文件记得也修改好,这里就不多演示了)。

static_library("rgb"){
    sources = [
        "rgb.c"
    ]
    include_dirs = [
        "//commonlibrary/utils_lite/include/",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
        "//base/iothardware/peripheral/interfaces/inner_api",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
    ]
}
  1. 编译,烧录,重启开发板,观察三色灯,注意灯光可能比较强。

OpenHarmony智能开发套件[驱动开发篇·下]-开源基础软件社区

人体红外传感器

和控制可燃气体传感器一样,我们仍然使用的是hi_adc_read的一个API,不同的是,我们在获取可燃气体传感器时,用的是5,而人体红外传感器的标号是3,光敏电阻其实也是一样的,他的标号是4。

这里就直接贴个主体代码给大家了,看过上面可燃气体传感器的,可以直接拷贝一份案例,在上面直接修改。

#include<stdio.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"#include"hi_gpio.h"#include"hi_io.h"// adc#include"hi_adc.h"// 一些宏定义 如 IOT_SUCCESS#include"iot_errno.h"#defineINFRARED_SENSOR_CHAN_NAME3// 主函数staticvoidinfraredMain(void){while(1){unsignedshortdata=0;intretval;retval=hi_adc_read(INFRARED_SENSOR_CHAN_NAME,&data,2,0,0);if(retval==IOT_SUCCESS){printf("人体红外传感器获取数据:data = %d\r\n",data);if(data>1800){printf("检测到人体红外!\r\n");}}else{printf("\r\n hi_adc_read fail, retval=%d",retval);}osDelay(100);}}// 样例测试入口staticvoidinfraredTest(void){osThreadAttr_tattr={"infraredMain",0,NULL,0,NULL,1024,osPriorityNormal,0,0};osThreadNew((osThreadFunc_t)infraredMain,NULL,&attr);}APP_FEATURE_INIT(infraredTest);

串口调试效果如下:

在有红外是,值在1800的样子,没有红外时,值在120的样子。

OpenHarmony智能开发套件[驱动开发篇·下]-开源基础软件社区

光敏电阻

#include<stdio.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"#include"hi_gpio.h"#include"hi_io.h"// adc#include"hi_adc.h"// 一些宏定义 如 IOT_SUCCESS#include"iot_errno.h"#defineSHINE_SENSOR_CHAN_NAME4// 主函数staticvoidshineMain(void){while(1){unsignedshortdata=0;intretval;retval=hi_adc_read(SHINE_SENSOR_CHAN_NAME,&data,2,0,0);if(retval==IOT_SUCCESS){printf("光敏电阻传感器获取数据:data = %d\r\n",data);}else{printf("\r\n hi_adc_read fail, retval=%d",retval);}osDelay(100);}}// 样例测试入口staticvoidshineTest(void){osThreadAttr_tattr={"shineMain",0,NULL,0,NULL,1024,osPriorityNormal,0,0};osThreadNew((osThreadFunc_t)shineMain,NULL,&attr);}APP_FEATURE_INIT(shineTest);

串口调试效果如下:

在没有光时,值在1800的样子,有光时,值在120的样子。

OpenHarmony智能开发套件[驱动开发篇·下]-开源基础软件社区

Oled显示屏

最后我们讲讲如何Oled板,主要是如何点亮他,让他能代替终端为我们显示一些东西,下方的两个按钮暂且不介绍了。

案例:在Oled板上打印“Hello,World”

  1. 新建样例目录
    applications/sample/wifi-iot/app/oled

  2. 新建源文件和gn文件
    applications/sample/wifi-iot/app/oled/oledTest.c
    applications/sample/wifi-iot/app/oled/BUILD.gn

  3. 补充文件

applications/sample/wifi-iot/app/oled/oled_ssd1306.c

applications/sample/wifi-iot/app/oled/oled_ssd1306.h

applications/sample/wifi-iot/app/oled/oled_fonts.h

oled_ssd1306.c

/*
 * Copyright (C) 2021 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */#include<stddef.h>#include<stdio.h>#include"oled_ssd1306.h"#include"iot_gpio.h"#include"iot_i2c.h"#include"iot_errno.h"#include"oled_fonts.h"#defineARRAY_SIZE(a)sizeof(a)/sizeof(a[0])#defineOLED_I2C_IDX0#defineOLED_WIDTH(128)#defineOLED_I2C_ADDR0x78// 默认地址为 0x78#defineOLED_I2C_CMD0x00// 0000 0000       写命令#defineOLED_I2C_DATA0x40// 0100 0000(0x40) 写数据#defineOLED_I2C_BAUDRATE(400*1000)// 400k#defineDELAY_100_MS(100*1000)// unsigned int I2cSetBaudrate(WifiIotI2cIdx id, unsigned int baudrate);typedefstruct{/** Pointer to the buffer storing data to send */unsignedchar*sendBuf;/** Length of data to send */unsignedintsendLen;/** Pointer to the buffer for storing data to receive */unsignedchar*receiveBuf;/** Length of data received */unsignedintreceiveLen;}IotI2cData;staticuint32_tI2cWiteByte(uint8_tregAddr,uint8_tbyte){unsignedintid=OLED_I2C_IDX;uint8_tbuffer[]={regAddr,byte};IotI2cData i2cData={0};i2cData.sendBuf=buffer;i2cData.sendLen=sizeof(buffer)/sizeof(buffer[0]);returnIoTI2cWrite(id,OLED_I2C_ADDR,i2cData.sendBuf,i2cData.sendLen);}/**
 * @brief Write a command byte to OLED device.
 *
 * @param cmd the commnad byte to be writen.
 * @return Returns {@link IOT_SUCCESS} if the operation is successful;
 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
 */staticuint32_tWriteCmd(uint8_tcmd){returnI2cWiteByte(OLED_I2C_CMD,cmd);}/**
 * @brief Write a data byte to OLED device.
 *
 * @param cmd the data byte to be writen.
 * @return Returns {@link IOT_SUCCESS} if the operation is successful;
 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
 */staticuint32_tWriteData(uint8_tdata){returnI2cWiteByte(OLED_I2C_DATA,data);}/**
 * @brief ssd1306 OLED Initialize.
 */uint32_tOledInit(void){staticconstuint8_tinitCmds[]={0xAE,// --display off0x00,// ---set low column address0x10,// ---set high column address0x40,// --set start line address0xB0,// --set page address0x81,// contract control0xFF,// --1280xA1,// set segment remap0xA6,// --normal / reverse0xA8,// --set multiplex ratio(1 to 64)0x3F,// --1/32 duty0xC8,// Com scan direction0xD3,// -set display offset0x00,//0xD5,// set osc division0x80,//0xD8,// set area color mode off0x05,//0xD9,// Set Pre-Charge Period0xF1,//0xDA,// set com pin configuartion0x12,//0xDB,// set Vcomh0x30,//0x8D,// set charge pump enable0x14,//0xAF,// --turn on oled panel};IoTGpioInit(13);hi_io_set_func(13,6);IoTGpioInit(14);hi_io_set_func(14,6);IoTI2cInit(0,OLED_I2C_BAUDRATE);for(size_ti=0;i<ARRAY_SIZE(initCmds);i++){uint32_tstatus=WriteCmd(initCmds[i]);if(status!=IOT_SUCCESS){returnstatus;}}returnIOT_SUCCESS;}voidOledSetPosition(uint8_tx,uint8_ty){WriteCmd(0xb0+y);WriteCmd(((x&0xf0)>>4)|0x10);WriteCmd(x&0x0f);}/*全屏填充*/voidOledFillScreen(uint8_tfillData){uint8_tm=0;uint8_tn=0;for(m=0;m<8;m++){WriteCmd(0xb0+m);WriteCmd(0x00);WriteCmd(0x10);for(n=0;n<128;n++){WriteData(fillData);}}}/**
 * @brief 8*16 typeface
 * @param x: write positon start from x axis 
 * @param y: write positon start from y axis
 * @param ch: write data
 * @param font: selected font
 */voidOledShowChar(uint8_tx,uint8_ty,uint8_tch,Font font){uint8_tc=0;uint8_ti=0;c=ch-' ';//得到偏移后的值if(x>OLED_WIDTH-1){x=0;y=y+2;}if(font==FONT8x16){OledSetPosition(x,y);for(i=0;i<8;i++){WriteData(F8X16[c*16+i]);}OledSetPosition(x,y+1);for(i=0;i<8;i++){WriteData(F8X16[c*16+i+8]);}}else{OledSetPosition(x,y);for(i=0;i<6;i++){WriteData(F6x8[c][i]);}}}voidOledShowString(uint8_tx,uint8_ty,constchar*str,Font font){uint8_tj=0;if(str==NULL){printf("param is NULL,Please check!!!\r\n");return;}while(str[j]){OledShowChar(x,y,str[j],font);x+=8;if(x>120){x=0;y+=2;}j++;}}

oled_ssd1306.h

/*
 * Copyright (C) 2021 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */#ifndefOLED_SSD1306_H#defineOLED_SSD1306_H#include<stdint.h>/**
 * @brief ssd1306 OLED Initialize.
 */uint32_tOledInit(void);/**
 * @brief Set cursor position
 *
 * @param x the horizontal posistion of cursor
 * @param y the vertical position of cursor 
 * @return Returns {@link WIFI_IOT_SUCCESS} if the operation is successful;
 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
 */voidOledSetPosition(uint8_tx,uint8_ty);voidOledFillScreen(uint8_tfillData);enumFont{FONT6x8=1,FONT8x16};typedefenumFontFont;voidOledShowChar(uint8_tx,uint8_ty,uint8_tch,Font font);voidOledShowString(uint8_tx,uint8_ty,constchar*str,Font font);#endif// OLED_SSD1306_H

oled_fonts.h

/*
 * Copyright (C) 2021 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */#ifndefOLOED_FONTS_H#defineOLOED_FONTS_H/************************************6*8的点阵************************************/staticunsignedcharF6x8[][6]={{0x00,0x00,0x00,0x00,0x00,0x00},// sp{0x00,0x00,0x00,0x2f,0x00,0x00},// !{0x00,0x00,0x07,0x00,0x07,0x00},// "{0x00,0x14,0x7f,0x14,0x7f,0x14},// #{0x00,0x24,0x2a,0x7f,0x2a,0x12},// ${0x00,0x62,0x64,0x08,0x13,0x23},// %{0x00,0x36,0x49,0x55,0x22,0x50},// &{0x00,0x00,0x05,0x03,0x00,0x00},// '{0x00,0x00,0x1c,0x22,0x41,0x00},// ({0x00,0x00,0x41,0x22,0x1c,0x00},// ){0x00,0x14,0x08,0x3E,0x08,0x14},// *{0x00,0x08,0x08,0x3E,0x08,0x08},// +{0x00,0x00,0x00,0xA0,0x60,0x00},// ,{0x00,0x08,0x08,0x08,0x08,0x08},// -{0x00,0x00,0x60,0x60,0x00,0x00},// .{0x00,0x20,0x10,0x08,0x04,0x02},// /{0x00,0x3E,0x51,0x49,0x45,0x3E},// 0{0x00,0x00,0x42,0x7F,0x40,0x00},// 1{0x00,0x42,0x61,0x51,0x49,0x46},// 2{0x00,0x21,0x41,0x45,0x4B,0x31},// 3{0x00,0x18,0x14,0x12,0x7F,0x10},// 4{0x00,0x27,0x45,0x45,0x45,0x39},// 5{0x00,0x3C,0x4A,0x49,0x49,0x30},// 6{0x00,0x01,0x71,0x09,0x05,0x03},// 7{0x00,0x36,0x49,0x49,0x49,0x36},// 8{0x00,0x06,0x49,0x49,0x29,0x1E},// 9{0x00,0x00,0x36,0x36,0x00,0x00},// :{0x00,0x00,0x56,0x36,0x00,0x00},// ;{0x00,0x08,0x14,0x22,0x41,0x00},// <{0x00,0x14,0x14,0x14,0x14,0x14},// ={0x00,0x00,0x41,0x22,0x14,0x08},// >{0x00,0x02,0x01,0x51,0x09,0x06},// ?{0x00,0x32,0x49,0x59,0x51,0x3E},// @{0x00,0x7C,0x12,0x11,0x12,0x7C},// A{0x00,0x7F,0x49,0x49,0x49,0x36},// B{0x00,0x3E,0x41,0x41,0x41,0x22},// C{0x00,0x7F,0x41,0x41,0x22,0x1C},// D{0x00,0x7F,0x49,0x49,0x49,0x41},// E{0x00,0x7F,0x09,0x09,0x09,0x01},// F{0x00,0x3E,0x41,0x49,0x49,0x7A},// G{0x00,0x7F,0x08,0x08,0x08,0x7F},// H{0x00,0x00,0x41,0x7F,0x41,0x00},// I{0x00,0x20,0x40,0x41,0x3F,0x01},// J{0x00,0x7F,0x08,0x14,0x22,0x41},// K{0x00,0x7F,0x40,0x40,0x40,0x40},// L{0x00,0x7F,0x02,0x0C,0x02,0x7F},// M{0x00,0x7F,0x04,0x08,0x10,0x7F},// N{0x00,0x3E,0x41,0x41,0x41,0x3E},// O{0x00,0x7F,0x09,0x09,0x09,0x06},// P{0x00,0x3E,0x41,0x51,0x21,0x5E},// Q{0x00,0x7F,0x09,0x19,0x29,0x46},// R{0x00,0x46,0x49,0x49,0x49,0x31},// S{0x00,0x01,0x01,0x7F,0x01,0x01},// T{0x00,0x3F,0x40,0x40,0x40,0x3F},// U{0x00,0x1F,0x20,0x40,0x20,0x1F},// V{0x00,0x3F,0x40,0x38,0x40,0x3F},// W{0x00,0x63,0x14,0x08,0x14,0x63},// X{0x00,0x07,0x08,0x70,0x08,0x07},// Y{0x00,0x61,0x51,0x49,0x45,0x43},// Z{0x00,0x00,0x7F,0x41,0x41,0x00},// [{0x00,0x55,0x2A,0x55,0x2A,0x55},// 55{0x00,0x00,0x41,0x41,0x7F,0x00},// ]{0x00,0x04,0x02,0x01,0x02,0x04},// ^{0x00,0x40,0x40,0x40,0x40,0x40},// _{0x00,0x00,0x01,0x02,0x04,0x00},// '{0x00,0x20,0x54,0x54,0x54,0x78},// a{0x00,0x7F,0x48,0x44,0x44,0x38},// b{0x00,0x38,0x44,0x44,0x44,0x20},// c{0x00,0x38,0x44,0x44,0x48,0x7F},// d{0x00,0x38,0x54,0x54,0x54,0x18},// e{0x00,0x08,0x7E,0x09,0x01,0x02},// f{0x00,0x18,0xA4,0xA4,0xA4,0x7C},// g{0x00,0x7F,0x08,0x04,0x04,0x78},// h{0x00,0x00,0x44,0x7D,0x40,0x00},// i{0x00,0x40,0x80,0x84,0x7D,0x00},// j{0x00,0x7F,0x10,0x28,0x44,0x00},// k{0x00,0x00,0x41,0x7F,0x40,0x00},// l{0x00,0x7C,0x04,0x18,0x04,0x78},// m{0x00,0x7C,0x08,0x04,0x04,0x78},// n{0x00,0x38,0x44,0x44,0x44,0x38},// o{0x00,0xFC,0x24,0x24,0x24,0x18},// p{0x00,0x18,0x24,0x24,0x18,0xFC},// q{0x00,0x7C,0x08,0x04,0x04,0x08},// r{0x00,0x48,0x54,0x54,0x54,0x20},// s{0x00,0x04,0x3F,0x44,0x40,0x20},// t{0x00,0x3C,0x40,0x40,0x20,0x7C},// u{0x00,0x1C,0x20,0x40,0x20,0x1C},// v{0x00,0x3C,0x40,0x30,0x40,0x3C},// w{0x00,0x44,0x28,0x10,0x28,0x44},// x{0x00,0x1C,0xA0,0xA0,0xA0,0x7C},// y{0x00,0x44,0x64,0x54,0x4C,0x44},// z{0x14,0x14,0x14,0x14,0x14,0x14},// horiz lines};/****************************************8*16的点阵************************************/staticconstunsignedcharF8X16[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 00x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 10x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 20x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 30x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 40xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 50x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 60x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 70x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 80x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 90x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 100x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 110x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 120x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 130x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 140x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 150x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 160x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 170x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 180x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 190x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 200x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 210x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 220x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 230x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 240x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 250x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 260x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 270x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 280x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 290x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 300x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 310xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 320x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 330x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 340xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 350x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 360x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 370x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 380xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 390x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 400x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 410x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 420x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 430x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 440x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 450x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 460xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 470x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 480xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 490x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 500x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 510x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 520x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 530x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 540xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 550x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 560x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 570x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 580x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 590x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 600x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 610x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 620x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 630x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 640x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 650x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 660x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 670x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 680x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 690x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 700x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 710x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 720x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 730x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 740x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 750x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 760x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 770x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 780x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 790x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 800x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 810x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 820x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 830x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 840x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 850x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 860x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 870x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 880x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 890x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 900x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 910x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 920x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 930x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94};#endif

具体介绍一下c文件中提供的一些API,其中标号1至3不需要我们手动调用,4至8比较常用。

  1. 写入数据字节。

uint32_tI2cWiteByte(uint8_tregAddr,uint8_tbyte)

参数解释:

  • regAddr:寄存器地址,要写入的寄存器地址。

  • byte:字节值,要写入的数据字节。

返回值:

  • 返回值类型为uint32_t,表示操作的结果。返回IOT_SUCCESS表示操作成功,否则返回定义在wifiiot_errno.h中的错误代码。

该函数封装了通过I2C总线向OLED设备写入一个字节数据的操作。它使用了一个结构体变量IotI2cData,并将要写入的寄存器地址和字节值存储在一个缓冲区buffer中。函数内部调用了IoTI2cWrite函数,通过I2C总线向OLED设备发送数据。

  1. 命令写入。

uint32_tWriteCmd(uint8_tcmd)

参数解释:

  • cmd:命令字节,要写入的命令字节。

返回值:

  • 返回值类型为uint32_t,表示操作的结果。返回IOT_SUCCESS表示操作成功,否则返回定义在wifiiot_errno.h中的错误代码。

该函数用于向OLED设备写入命令字节。它调用了I2cWiteByte函数,将命令字节和OLED_I2C_CMD作为参数传递给I2cWiteByte函数进行发送。

  1. 数据写入。

uint32_tWriteData(uint8_tdata)

参数解释:

  • data:数据字节,要写入的数据字节。

返回值:

  • 返回值类型为uint32_t,表示操作的结果。返回IOT_SUCCESS表示操作成功,否则返回定义在wifiiot_errno.h中的错误代码。

该函数用于向OLED设备写入数据字节。它调用了I2cWiteByte函数,将数据字节和OLED_I2C_DATA作为参数传递给I2cWiteByte函数进行发送。

  1. 初始化。

uint32_tOledInit(void)

参数解释:无

返回值:

  • 返回值类型为uint32_t,表示操作的结果。返回IOT_SUCCESS表示操作成功,否则返回定义在wifiiot_errno.h中的错误代码。

该函数用于初始化SSD1306 OLED显示屏。首先,它初始化GPIO引脚,并将其配置为I2C功能。然后调用IoTI2cInit函数初始化I2C控制器。接下来,通过循环发送一系列的初始化命令字节到OLED设备,以完成OLED的初始化过程。

  1. 设置数据起始位置。

voidOledSetPosition(uint8_tx,uint8_ty)

参数解释:

  • x:X轴位置,写入数据的起始列位置。

  • y:Y轴位置,写入数据的起始行位置。

返回值:无

该函数用于设置写入数据的起始位置。它调用WriteCmd函数向OLED设备发送命令字节,设置OLED设备的行和列地址。

  1. 填充屏幕。

voidOledFillScreen(uint8_tfillData)

参数解释:

  • fillData:填充数据,要用于填充屏幕的数据字节。

返回值:无

该函数用于全屏填充屏幕。通过循环遍历所有行和列,调用WriteData函数向OLED设备发送填充数据字节。

  1. 输出字符。

voidOledShowChar(uint8_tx,uint8_ty,uint8_tch,Font font)

参数解释:

  • x:X轴位置,写入字符的起始列位置。

  • y:Y轴位置,写入字符的起始行位置。

  • ch:字符,要写入的字符。

  • font:字体,选择使用的字体。

返回值:无

该函数用于显示一个字符。根据所选字体,它调用WriteData函数向OLED设备发送对应字体的字形数据。

  1. 输出字符串。

voidOledShowString(uint8_tx,uint8_ty,constchar*str,Font font)

参数解释:

  • x:X轴位置,写入字符串的起始列位置。

  • y:Y轴位置,写入字符串的起始行位置。

  • str:字符串,要写入的字符串。

  • font:字体,选择使用的字体。

返回值:无

该函数用于显示一个字符串。它遍历字符串中的每个字符,调用OledShowChar函数逐个显示字符,并根据需要更新X和Y轴位置。

  1. 编写源文件oledTest.c。

#include<stdio.h>#include<stdint.h>#include<string.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"#include"oled_ssd1306.h"staticvoidoledMain(void){OledInit();OledFillScreen(0);OledShowString(0,0,"Hello,World",1);}staticvoidoledTest(void){osThreadAttr_tattr={"oledMain",0,NULL,0,NULL,1024,osPriorityNormal,0,0};osThreadNew((osThreadFunc_t)oledMain,NULL,&attr);}APP_FEATURE_INIT(oledTest);
  1. 编写BUILD.gn (app目录下的BUILD.gn文件记得也修改好,这里就不多演示了)。

static_library("oled") {
    sources = [
        "oled_ssd1306.c", 
        "oledTest.c",
    ]
    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//device/hisilicon/hispark_pegasus/sdk_liteos/include",
        "//base/iothardware/peripheral/interfaces/inner_api",
    ]
}
  1. 编译,烧录,重启开发板,观察oled显示屏。

OpenHarmony智能开发套件[驱动开发篇·下]-开源基础软件社区

结束语

至此驱动模块就给大家介绍到这里,大家可以结合内核编程驱动编程自行开发一些小案例。后面也会给大家带来一些综合案例的演示。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

19    2023-05-30 14:58:05    智能开发 鸿蒙