OpenHarmony学习笔记——I2C驱动0.96OLED屏幕
文章目录
- 前言
- 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屏幕相关推荐
- 【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)
[STM32CubeMX]教程二_IIC驱动0.96oled屏幕(SSD1306) 文章目录 [STM32CubeMX]教程二_IIC驱动0.96oled屏幕(SSD1306) 前言 一.IIC通讯 ...
- GD32F310G8 -【6】硬件I2C软件I2C驱动0.96OLED
GD32F310-硬件I2C&软件I2C驱动OLED I2C 简介及特点 并行总线至 I2C 总线协议的转换及接口: 同一接口既可实现主机功能又可实现从机功能: 主从机之间的双向数据传输: 支 ...
- OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度
文章目录 前言 DHT11简介 通信流程 硬件连接 编程实现 GPIO API简介 复位总线 DHT11应答 数据读取 效果一览 总结 目录 前言 此文主要是使用Hi3861的GPIO口,模拟1-Wi ...
- OpenHarmony学习笔记——Hi3861+ASR-01的语音识别助手
文章目录 前言 Hi3861的UART与PWM简介 UART简介 PWM ASR-01离线语音识别 天问官方介绍 硬件连接 软件部分 ASR-01代码 Hi3861端代码 初始化资源 串口指令识别 效 ...
- 树莓派学习笔记 ——I2C PCF8574 SysFs方式
1.前言 树莓派的GPIO端口数量有限,可通过IO扩展芯片增加GPIO的数量,使得树莓派可以适应更多的应用.PCF8574为一款通过I2C总线扩展IO的芯片,单个PCF8574可扩展8个IO,一个I2 ...
- 树莓派学习笔记——I2C设备载入和速率设置
1.载入设备 方法1--临时载入设备 sudo modprobe -r i2c_bcm2708 #卸载设备 -r代表removesudo modprobe i2c_bcm2708 #重新载入设备 方法 ...
- 数据结构与算法学习笔记之 从0编号的数组
数据结构与算法学习笔记之 从0编号的数组 前言 数组看似简单,但掌握精髓的却没有多少:他既是编程语言中的数据类型,又是最基础的数据结构: 一个小问题: 为什么数据要从0开始编号,而不是 从1开始呢? ...
- Unity DOTS 学习笔记1 - ECS 0.50介绍和安装
Unity DOTS 学习笔记1 - ECS 0.50介绍和安装 为什么学习这个技术 ECS的全称为Entity Component System,是最早由暴雪在GDC2017上提出的一个新的游戏设计 ...
- NRF52840学习历程(八)IIC协议0.96OLED屏幕
时间在2021年2月3日,寒假放假在家好好学一学nRF52840 昨天喉咙就不舒服,今天就感冒了,休息一波 开发板:初雪的100出头那块 NRF52840 EVAL KIT 下载工具:JINLK V1 ...
最新文章
- OKR和KPI有什么区别?一篇文章搞懂
- Python的itertools.product 方法
- IBASE object component的where use list
- 不宜过分炒作第三代半导体材料弯道超车
- 洛谷P1173:[NOI2016] 网格(tarjan、离散化)
- 外卖小哥是怎样炼成的?
- MouseColor | 颜色获取及转换工具
- 在工作中你卑微到什么程度?
- 【R语言实用技巧】类别变量的顺序自定义设置
- java hashmap value值_如何在Java中的HashMap中打印键的所有值
- 亮相云栖:这些被Gartner点名的2020年安全风向
- 大学心理学课本_大学心理学的教材依次(全部)都有哪些?
- Site App轻松创建移动开发
- 光场相机微透镜阵列排布方式以及其填充率比较
- 重庆大学非全日制计算机专业,2018年重庆大学非全日制研究生招生专业目录
- pynq 环境搭建_PYNQ系列学习(一): Pynq开发环境配置
- 5分钟快速掌握 Adam 优化算法
- 【网络驱动器的映射】
- 一文贯穿Redis-动力节点
- springboot 使用@Bean 好处与坏处
热门文章
- OpenFOAM不可压求解器pimpleFoam研究(一)粘度实现
- stm32H743can配置
- arm powerpc mips dsp
- 新手解决Connections could not be acquired from the underlying database!Java代码上传到服务器连接不上数据库
- HBase 在滴滴出行的应用场景和最佳实践
- 【渝粤题库】陕西师范大学165103 劳动经济学 作业
- 还行,OPPO Find X3 Pro评测:卖的是屏幕和这个超广角!
- 小学总结计算机,小学计算机教师年度工作总结
- OmniGraffle for mac(绘图软件)
- Android Studio报错:Incompatible types. Required:android.app.ActionBar及Android如何隐藏系统默认标题栏