文章目录

  • 前言
  • I2C简介
  • 硬件连接
  • 编程实现
    • 创建代码框架
    • 初始化并复用GPIO
    • 初始化I2C0
    • 初始化OLED
      • 从机地址
      • OLED初始化配置
      • 功能代码
  • 总结
  • 目录

前言

前面介绍了一些关于在Hi3861上使用OpenHarmony的系统框架,别看Hi3861的IO口数量不多,但是其资源是相当丰富的,单片机有的复用功能他都有I2C、SPI、UART、ADC、PWM都支持,本文将在之前的框架基础上用Hi3861使用I2C协议驱动0.96寸的OLED屏幕显示图片、字符、数字以及汉字。

I2C简介

I2C是南向开发中使用频率很高的一个协议,有关它的简介笔者在之前的文章中有过介绍,大家可以去参考——树莓派4B学习笔记——IO通信篇(I2C)。在这里只需要知道以下几点:
1.I2C有一个时钟线SCL,用来连接主从,使得主从机的时钟同步;还有一个数据线SDA,用来串行传输数据;
2.I2C通信中没有片选,选中从机是通过地址来判断的;
由于Hi3861提供了I2C的API接口,所以底层的数据传输方式、起始信号、结束信号、应答信号这些东西不需要去纠结,在操作器件时使用API的接口格式即可。

硬件连接

Hi3861的IO口中有两组I2C,分别是I2C0和I2C1,笔者在此使用的是I2C0,需要确定好自己使用的是1还是0,后面编程要用。

然后这两组又可以分别复用到两组IO,也就是说有四组I2C接口,复用引脚是GPIO9(I2C0 SCL)和GPIO10(I2C0 SDA)。
所以笔者的硬件连接如下:

编程实现

创建代码框架

结合前面两篇介绍的工程建立,首先在工程系统目录下新建一个文件夹,然后添加一个c文件和一个BUILD.gn的编译构建文件;新建完成后,开始搭建代码框架,本文借用上一篇的任务创建的框架,采用线程创建的方式来实现。

创建代码如下:

//任务实现函数
static void OLEDTask(void)
{}
//任务创建函数
static void OLEDExampleEntry(void)
{osThreadAttr_t attr;attr.name = "OLEDTask";//任务名attr.attr_bits = 0U;attr.cb_mem = NULL;attr.cb_size = 0U;attr.stack_mem = NULL;attr.stack_size = I2C_TASK_STACK_SIZE;//堆栈大小attr.priority = I2C_TASK_PRIO;if (osThreadNew((osThreadFunc_t)OLEDTask, NULL, &attr) == NULL){printf("Falied to create OLEDTask!\n");}printf("Create I2CTask Successful!!\n");
}APP_FEATURE_INIT(OLEDExampleEntry);

初始化并复用GPIO

完成了代码框架的搭建后,需要根据硬件的GPIO接线方式对GPIO9以及GPIO10进行初始化,参考前面的点灯流程可以知道,Hi3861的IO初始化和STM32类似,首先初始化GPIO,然后复用为I2CSCL和SDA,初始化的命令已经在gpio_ex.h中标明,每个IO的复用功能,选择自己所需的即可。

GPIO9与GPIO10的初始化代码如下:

在任务函数中添加此代码,初始化GPIO口GpioInit();//GPIO_10复用为I2C0_SDAIoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_I2C0_SDA);//GPIO_9复用为I2C0_SCLIoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_I2C0_SCL);//baudrate: 400kbps

初始化I2C0

上面提到过Hi3861中有两组I2C,这里笔者使用的I2C0,根据使用STM32的经验,肯定是需要指向和初始化的。这里官方已经封装好了API接口函数,调用“wifiiot_i2c.h”和“wifiiot_i2c_ex.h”即可看见里面的API函数,可以看见里面一共有六个函数。


对比STM32的I2C可以发现,这四个函数STM32的底层函数及其相似。使用方式也基本是套娃。

不同的是Hi3861的I2C接口初始化时需要设定传输速率,这里笔者选择了400Kbps,初始化代码如下:

  //baudrate: 400kbpsI2cInit(WIFI_IOT_I2C_IDX_0, 400000);I2cSetBaudrate(WIFI_IOT_I2C_IDX_0, 400000);printf("I2C Test Start\n");

初始化OLED

截止到上一步,Hi3861作为主机的初始化已经完成了,接下来需要主机利用总线发送指令初始化从机用来实现功能。

从机地址

如下图所示,笔者使用的OLED地址是0X78,I2C的地址最后一位是读写标志位,由于OLED作为从机,主机不需要读取数据,只需要向OLED写入指令和数据即可,所以我们在编程时,可以直接使用这个地址0x78即可。(写操作是最低位是0)。

OLED初始化配置

整个初始化过程需要配置的指令数据很多,笔者在此不做赘述,直接使用了中景园的代码套娃,注意源代码中GPIO初始化的部分需要删掉。
初始化代码如下:

//OLED的初始化
void OLED_Init(void)
{OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panelOLED_WR_Byte(0x00,OLED_CMD);//---set low column addressOLED_WR_Byte(0x10,OLED_CMD);//---set high column addressOLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control registerOLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current BrightnessOLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常OLED_WR_Byte(0xA6,OLED_CMD);//--set normal displayOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 dutyOLED_WR_Byte(0xD3,OLED_CMD);//-set display offset  Shift Mapping RAM Counter (0x00~0x3F)OLED_WR_Byte(0x00,OLED_CMD);//-not offsetOLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequencyOLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/SecOLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge periodOLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configurationOLED_WR_Byte(0x12,OLED_CMD);OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomhOLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect LevelOLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)OLED_WR_Byte(0x02,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disableOLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disableOLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_Clear();OLED_WR_Byte(0xAF,OLED_CMD);
}

功能代码

完成上述初始化后,屏幕已经可以正常显示了,接下来需要编写执行函数,显示图片,汉字字符串这些。这些功能说到底还是调用I2C写API,给从机数据,让它显示内容。这里笔者还是用了中景园的代码,由于I2C底层代码的改动,需要将源代码中的IIC接收和发送部分修改成API函数的模式才能正常使用。也就是说需要将下面左边的发送字节的函数修改为右边的API接口发送函数。

右边的API函数的三个参数分别是:1.I2C通道号,这个和前面初始化的通道号一致;2.从机的地址,笔者此处是0X78;3.发送的数据,这里需要注意,接口韩式定义的是一个结构体指针,在使用过程中需要将发送的数据做一个处理。
API调用举例如下:

#define NT3H1X_SLAVE_ADDRESS 0x55 //器件地址
static bool writeTimeout(  uint8_t *data, uint8_t dataSend) {uint32_t status = 0;WifiIotI2cData nt3h1101_i2c_data1 = {0};//定义结构体变量nt3h1101_i2c_data1.sendBuf = data;//赋值nt3h1101_i2c_data1.sendLen = dataSend;//数据长度status = I2cWrite(WIFI_IOT_I2C_IDX_1, (NT3H1X_SLAVE_ADDRESS<<1)|0x00, &nt3h1101_i2c_data1);if (status != 0){printf("===== Error: I2C write status1 = 0x%x! =====\r\n", status);return 0;}usleep(300000);return 1;
}

参考这个例子,可以修改出是和此OLED的代码,这里笔者参考了此篇博文——Hispark-3861_oled显示。
代码如下:

u32 my_i2c_write(WifiIotI2cIdx id, u16 device_addr, u32 send_len)
{u32 status;WifiIotI2cData oled_i2c_data = { 0 };oled_i2c_data.sendBuf = g_send_data;oled_i2c_data.sendLen = send_len;status = I2cWrite(id, device_addr, &oled_i2c_data);if (status != 0) {printf("===== Error: I2C write status = 0x%x! =====\r\n", status);return status;}return 0;
}/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{g_send_data[0] = 0x00;g_send_data[1] = IIC_Command;my_i2c_write(WIFI_IOT_I2C_IDX_0, 0x78, 2);
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{g_send_data[0] = 0x40;g_send_data[1] = IIC_Data;my_i2c_write(WIFI_IOT_I2C_IDX_0, 0x78, 2);
}void OLED_WR_Byte(unsigned dat,unsigned cmd)
{if(cmd){Write_IIC_Data(dat);}else{Write_IIC_Command(dat);}}

修改这个接口函数之后,其他的功能代码直接copy中景园的即可。
笔者的最后的任务函数如下:

static void OLEDTask(void)
{GpioInit();//GPIO_10复用为I2C0_SDAIoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_I2C0_SDA);//GPIO_9复用为I2C0_SCLIoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_I2C0_SCL);//baudrate: 400kbpsI2cInit(WIFI_IOT_I2C_IDX_0, 400000);I2cSetBaudrate(WIFI_IOT_I2C_IDX_0, 400000);printf("I2C Test Start\n");OLED_Init();OLED_ColorTurn(0);//0正常显示,1 反色显示OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示usleep(500000);while (1){OLED_Clear();OLED_ShowString(1,0,"ABC",8);//6*8 “ABC”OLED_ShowString(1,8,"ABC",12);//6*12 “ABC”OLED_ShowString(1,20,"ABC",16);//8*16 “ABC”OLED_ShowString(1,36,"openharmony",16);OLED_Refresh();usleep(500000);OLED_ShowPicture(1,0,128,64,BMP1);OLED_Refresh();usleep(500000);OLED_ShowPicture(1,0,128,64,BMP2);OLED_Refresh();usleep(500000);OLED_ShowPicture(1,0,128,64,BMP3);OLED_Refresh();usleep(500000);OLED_ShowPicture(1,0,128,64,BMP4);OLED_Refresh();usleep(500000);}
}

然后是编译,下载,这些就步骤不做记载了。
最后来看看笔者移植后的效果:


Hi3861+oled播放动画片头
感谢立创EDA提供的白嫖活动。

总结

有关Hi3861使用I2C驱动0.96寸OLED的介绍就记录到此,文中如有不妥之处欢迎指出。需要代码的同学可以私信笔者获取。

目录

OpenHarmony学习笔记——南向开发环境搭建
OpenHarmony学习笔记——编辑器访问Linux服务器进行编译
OpenHarmony学习笔记——点亮你的LED
OpenHarmony学习笔记——多线程的创建
OpenHarmony学习笔记——I2C驱动0.96OLED屏幕
OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度
OpenHarmony学习笔记——Hi3861接入OneNET
手把手教你OneNET数据可视化
OpenHarmony学习笔记——Hi386+ASR-01的语音识别助手

OpenHarmony学习笔记——I2C驱动0.96OLED屏幕相关推荐

  1. 【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)

    [STM32CubeMX]教程二_IIC驱动0.96oled屏幕(SSD1306) 文章目录 [STM32CubeMX]教程二_IIC驱动0.96oled屏幕(SSD1306) 前言 一.IIC通讯 ...

  2. GD32F310G8 -【6】硬件I2C软件I2C驱动0.96OLED

    GD32F310-硬件I2C&软件I2C驱动OLED I2C 简介及特点 并行总线至 I2C 总线协议的转换及接口: 同一接口既可实现主机功能又可实现从机功能: 主从机之间的双向数据传输: 支 ...

  3. OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度

    文章目录 前言 DHT11简介 通信流程 硬件连接 编程实现 GPIO API简介 复位总线 DHT11应答 数据读取 效果一览 总结 目录 前言 此文主要是使用Hi3861的GPIO口,模拟1-Wi ...

  4. OpenHarmony学习笔记——Hi3861+ASR-01的语音识别助手

    文章目录 前言 Hi3861的UART与PWM简介 UART简介 PWM ASR-01离线语音识别 天问官方介绍 硬件连接 软件部分 ASR-01代码 Hi3861端代码 初始化资源 串口指令识别 效 ...

  5. 树莓派学习笔记 ——I2C PCF8574 SysFs方式

    1.前言 树莓派的GPIO端口数量有限,可通过IO扩展芯片增加GPIO的数量,使得树莓派可以适应更多的应用.PCF8574为一款通过I2C总线扩展IO的芯片,单个PCF8574可扩展8个IO,一个I2 ...

  6. 树莓派学习笔记——I2C设备载入和速率设置

    1.载入设备 方法1--临时载入设备 sudo modprobe -r i2c_bcm2708 #卸载设备 -r代表removesudo modprobe i2c_bcm2708 #重新载入设备 方法 ...

  7. 数据结构与算法学习笔记之 从0编号的数组

    数据结构与算法学习笔记之 从0编号的数组 前言 数组看似简单,但掌握精髓的却没有多少:他既是编程语言中的数据类型,又是最基础的数据结构: 一个小问题: 为什么数据要从0开始编号,而不是 从1开始呢? ...

  8. Unity DOTS 学习笔记1 - ECS 0.50介绍和安装

    Unity DOTS 学习笔记1 - ECS 0.50介绍和安装 为什么学习这个技术 ECS的全称为Entity Component System,是最早由暴雪在GDC2017上提出的一个新的游戏设计 ...

  9. NRF52840学习历程(八)IIC协议0.96OLED屏幕

    时间在2021年2月3日,寒假放假在家好好学一学nRF52840 昨天喉咙就不舒服,今天就感冒了,休息一波 开发板:初雪的100出头那块 NRF52840 EVAL KIT 下载工具:JINLK V1 ...

最新文章

  1. OKR和KPI有什么区别?一篇文章搞懂
  2. Python的itertools.product 方法
  3. IBASE object component的where use list
  4. 不宜过分炒作第三代半导体材料弯道超车
  5. 洛谷P1173:[NOI2016] 网格(tarjan、离散化)
  6. 外卖小哥是怎样炼成的?
  7. MouseColor | 颜色获取及转换工具
  8. 在工作中你卑微到什么程度?
  9. 【R语言实用技巧】类别变量的顺序自定义设置
  10. java hashmap value值_如何在Java中的HashMap中打印键的所有值
  11. 亮相云栖:这些被Gartner点名的2020年安全风向
  12. 大学心理学课本_大学心理学的教材依次(全部)都有哪些?
  13. Site App轻松创建移动开发
  14. 光场相机微透镜阵列排布方式以及其填充率比较
  15. 重庆大学非全日制计算机专业,2018年重庆大学非全日制研究生招生专业目录
  16. pynq 环境搭建_PYNQ系列学习(一): Pynq开发环境配置
  17. 5分钟快速掌握 Adam 优化算法
  18. 【网络驱动器的映射】
  19. 一文贯穿Redis-动力节点
  20. springboot 使用@Bean 好处与坏处

热门文章

  1. OpenFOAM不可压求解器pimpleFoam研究(一)粘度实现
  2. stm32H743can配置
  3. arm powerpc mips dsp
  4. 新手解决Connections could not be acquired from the underlying database!Java代码上传到服务器连接不上数据库
  5. HBase 在滴滴出行的应用场景和最佳实践
  6. 【渝粤题库】陕西师范大学165103 劳动经济学 作业
  7. 还行,OPPO Find X3 Pro评测:卖的是屏幕和这个超广角!
  8. 小学总结计算机,小学计算机教师年度工作总结
  9. OmniGraffle for mac(绘图软件)
  10. Android Studio报错:Incompatible types. Required:android.app.ActionBar及Android如何隐藏系统默认标题栏