IIC相关介绍及oled实验(二)

//模块:OLED显示屏

1. 0.96寸OLED屏幕介绍

0.96 寸 4P OLED 屏幕模块是一种显示屏模块,它包括一个 0.96 英寸的 OLED 显示屏和四个引脚。这种 OLED 屏幕模块通常用于嵌入式系统和小型电子设备中,可以显示文本、图像和其他类型的信息。由于其小 尺寸和低功耗,也常用于智能手表、健康追踪器和其他便携式设备中。

 0.96OLED 屏幕模块的优点有:

1. 高对比度和高亮度:OLED 屏幕模块可以提供深黑色背景和明亮的字色,因此可以实现高对比度和高亮 度的显示效果;

2. 自发光:OLED 屏幕模块不需要背光灯,因此可以实现更薄、更轻的设计;

3. 响应速度快:OLED 屏幕模块的响应速度非常快,可以实现流畅的动画和视频效果;

4. 视角宽:OLED 屏幕模块的视角非常宽,即使从不同角度观察,图像和文字也能保持清晰。

0.96OLED 屏幕模块的缺点有:

1. 显示寿命短:与 LCD 显示屏相比,OLED 的显示寿命相对较短,因为它的有机材料会随着时间的推移 而逐渐失效;

2. 显示面积小:0.96 寸 OLED 屏幕模块的显示面积相对较小,因此不适合用于需要大屏幕的应用。

2. 如何驱动OLED屏幕显示内容?

3. OLED通讯协议

4. SSD1306

 5. GDDRAM

页地址模式:  

水平地址模式:

垂直地址模式: 

 

6. OLED命令

 

7. 如何取模 

 小实验:OLED实验

实验目的 驱动 OLED 屏幕,显示点、线、字符、字符串、汉字、图片等内容。

 

实现---点、线、A 

/------oled.h---------/

#include "sys.h"//SCL配置
#define OLED_I2C_SCL_CLK()  __HAL_RCC_GPIOB_CLK_ENABLE();
#define OLED_I2C_SCL_PORT   GPIOB
#define OLED_I2C_SCL_PIN    GPIO_PIN_6//SDA配置
#define OLED_I2C_SDA_CLK()  __HAL_RCC_GPIOB_CLK_ENABLE();
#define OLED_I2C_SDA_PORT   GPIOB
#define OLED_I2C_SDA_PIN    GPIO_PIN_7//SCL引脚拉高拉低
#define OLED_SCL_RESET()   HAL_GPIO_WritePin(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN, GPIO_PIN_RESET)
#define OLED_SCL_SET()     HAL_GPIO_WritePin(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN, GPIO_PIN_SET)//SDA引脚使能
#define OLED_SDA_RESET()   HAL_GPIO_WritePin(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN, GPIO_PIN_RESET)
#define OLED_SDA_SET()     HAL_GPIO_WritePin(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN, GPIO_PIN_SET)void oled_init(void);
void oled_write_cmd(uint8_t cmd);
void oled_write_data(uint8_t data);
void oled_fill(uint8_t data);
void oled_set_cursor(uint8_t x, uint8_t y);

/------oled.c---------/

1、oled_gpio_init初始化函数

void oled_gpio_init(void)
{GPIO_InitTypeDef gpio_initstruct;OLED_I2C_SCL_CLK();OLED_I2C_SDA_CLK();gpio_initstruct.Pin = OLED_I2C_SCL_PIN; //PA7         gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             gpio_initstruct.Pull = GPIO_PULLUP;                     gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           HAL_GPIO_Init(OLED_I2C_SCL_PORT, &gpio_initstruct);//GPIOBgpio_initstruct.Pin = OLED_I2C_SDA_PIN;          HAL_GPIO_Init(OLED_I2C_SDA_PORT, &gpio_initstruct);
}

2、I2C起始信号:起始信号由主设备发起,用于通知总线上的所有设备即将开始数据传输

void oled_i2c_start(void)
{OLED_SCL_SET(); //确保scl在高电平为拉低做准备OLED_SDA_SET();//确保sda在高电平为拉低做准备OLED_SDA_RESET();//只有在sda拉低的条件是才能传输数据,拉低OLED_SCL_RESET();//当SCL为高电平时,SDA由高电平变为低电平,产生一个下降沿
}

3、I2C停止信号 由主设备发起,用于通知总线上的所有设备数据传输已经结束

void oled_i2c_stop(void)
{
/*当SCL为高电平时,SDA由低电平变为高电平,产生一个上升沿,表示停止信号的开始*/OLED_SCL_SET();OLED_SDA_RESET();OLED_SDA_SET();
}

4、I2C响应信号

每当一个字节的数据传输完成后,接收方会向发送方发送一个应答信号(ACK)或非应答信号 (NACK)。

应答信号在SCL的第9个时钟周期(当SCL为高电平时)发送。


void oled_i2c_ack(void)
{//默认低电平?OLED_SCL_SET();OLED_SCL_RESET();
}/*如果SDA线为低电平,则表示ACK(有效应答),
表示接收方已成功接收该字节。 如果SDA线为高电平
则表示NACK(非应答),通常表示接收方接收该字节没有成功*/

5、I2C写byte  ??

void oled_i2c_write_byte(uint8_t data)
{uint8_t i, tmp;tmp = data;for(i = 0; i < 8; i++){if((tmp & 0x80) == 0x80)OLED_SDA_SET();elseOLED_SDA_RESET();tmp = tmp << 1;OLED_SCL_SET();OLED_SCL_RESET();}
}

6、I2C写命令

void oled_write_cmd(uint8_t cmd)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x00);oled_i2c_ack();oled_i2c_write_byte(cmd);oled_i2c_ack();oled_i2c_stop();
}

7、I2C写数据


void oled_write_data(uint8_t data)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x40);oled_i2c_ack();oled_i2c_write_byte(data);oled_i2c_ack();oled_i2c_stop();
}

8、oled初始化

void oled_init(void)
{oled_gpio_init();delay_ms(100);oled_write_cmd(0xAE);    //设置显示开启/关闭,0xAE关闭,0xAF开启oled_write_cmd(0xD5);    //设置显示时钟分频比/振荡器频率oled_write_cmd(0x80);    //0x00~0xFFoled_write_cmd(0xA8);    //设置多路复用率oled_write_cmd(0x3F);    //0x0E~0x3Foled_write_cmd(0xD3);    //设置显示偏移oled_write_cmd(0x00);    //0x00~0x7Foled_write_cmd(0x40);    //设置显示开始行,0x40~0x7Foled_write_cmd(0xA1);    //设置左右方向,0xA1正常,0xA0左右反置oled_write_cmd(0xC8);    //设置上下方向,0xC8正常,0xC0上下反置oled_write_cmd(0xDA);    //设置COM引脚硬件配置oled_write_cmd(0x12);oled_write_cmd(0x81);    //设置对比度oled_write_cmd(0xCF);    //0x00~0xFFoled_write_cmd(0xD9);    //设置预充电周期oled_write_cmd(0xF1);oled_write_cmd(0xDB);    //设置VCOMH取消选择级别oled_write_cmd(0x30);oled_write_cmd(0xA4);    //设置整个显示打开/关闭oled_write_cmd(0xA6);    //设置正常/反色显示,0xA6正常,0xA7反色oled_write_cmd(0x8D);    //设置充电泵oled_write_cmd(0x14);oled_write_cmd(0xAF);    //开启显示
}

9、oled起始位置设施函数


void oled_set_cursor(uint8_t x, uint8_t y)
{oled_write_cmd(0xB0 + y);oled_write_cmd((x & 0x0F) | 0x00);oled_write_cmd(((x & 0xF0) >> 4) | 0x10);
}

10、oled清屏函数


void oled_fill(uint8_t data)
{uint8_t i, j;for(i = 0; i < 8; i++){oled_set_cursor(0, i);for(j = 0; j < 128; j++)oled_write_data(data);}
}

//指定位置 行和列,外循环选择page ,内循环写里面的内容
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size) //高度16 / 8
{//定义两个循环判断有几个pageuint8_t i,j,page;num = num - ' ';//做一个偏移显示我们的字符  空格的asci的值就是32page = size / 8; //取整是多少确定有多少个page模式取出来if(size % 8)//需要两个page,再判断余数是否为0保证至少有1个pagepage++;for(j = 0;j<page;j++){oled_set_cursor(x,y + j);//如果y没有加j会只显示上半部分  位置显示//数据是高度的一半//size / 2 * (j + 1)   j意思是第几个pagefor(i=size / 2 * j; i < size / 2 * (j + 1); i++)//高度的一半*j j=0时size从0开始,下半部分除外除8,从第八个开始{//对不同尺寸做一个判断if(size == 12)oled_write_data(ascii_6X12[num][i]);else if(size == 16)oled_write_data(ascii_8X16[num][i]);else if(size == 24)}}}

 

打印一个字符

//指定位置 行和列,外循环选择page ,内循环写里面的内容
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size) //高度16 / 8
{//定义两个循环判断有几个pageuint8_t i,j,page;num = num - ' ';//做一个偏移显示我们的字符  空格的asci的值就是32page = size / 8; //取整是多少确定有多少个page模式取出来if(size % 8)//需要两个page,再判断余数是否为0保证至少有1个pagepage++;for(j = 0;j<page;j++){oled_set_cursor(x,y + j);//如果y没有加j会只显示上半部分  位置显示//数据是高度的一半//size / 2 * (j + 1)   j意思是第几个pagefor(i=size / 2 * j; i < size / 2 * (j + 1); i++)//高度的一半*j j=0时size从0开始,下半部分除外除8,从第八个开始{//对不同尺寸做一个判断if(size == 12)oled_write_data(ascii_6X12[num][i]);else if(size == 16)oled_write_data(ascii_8X16[num][i]);else if(size == 24)oled_write_data(ascii_12X24[num][i]);		}}}

//显示一个字符串

void oled_show_string(uint8_t x, uint8_t y,char *p,uint8_t size)
{//遍历数组while(*p !=  '\0'){//遍历字符oled_show_char(x,y,*p,size);//偏移字符  字符的宽度是高度的一半x += size/2;p++;}
}

 显示汉字

void oled_show_chinese(uint8_t x, uint8_t y,uint8_t N,uint8_t size)
{uint16_t i,j;for(j=0;j < size/8; j++)//第几个page{oled_set_cursor(x,y+j);//??for(i = size * j;i < size * (j+1); i++)//判断尺寸{if(size == 16)oled_write_data(chinese_16x16[N][i]);else if(size == 24)oled_write_data(chinese_24x24[N][i]);}}}

图片显示,具体某图片

void oled_show_image(uint8_t x , uint8_t y, uint8_t width, uint8_t height, uint8_t *bmp)
{uint16_t i,j,idx;//idx是索引把bmp中的东西提取出来for(j = 0; j < height;j++){oled_set_cursor(x,y+j);for(i = 0;i < width; i++)//列{//指定坐标oled_write_data(bmp[idx++]);}}}

/-----main.c-----/ 

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "oled.h"extern const unsigned char shuai_data[];int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* 初始化LED灯 */uart1_init(115200);oled_init();printf("hello world!\r\n");oled_fill(0x00);oled_set_cursor(0, 0);
//    oled_write_cmd(0xB0);
//    oled_write_cmd(0x00);
//    oled_write_cmd(0x10);//    oled_write_data(0x80);//显示一个点/*显示字母   A    */oled_write_data(0x00);oled_write_data(0x00);oled_write_data(0xC0);oled_write_data(0x38);oled_write_data(0xE0);oled_write_data(0x00);oled_write_data(0x00);oled_write_data(0x00);oled_set_cursor(0, 1);//前面8个显示完后换到pageoled_write_data(0x20);oled_write_data(0x3C);oled_write_data(0x23);oled_write_data(0x02);oled_write_data(0x02);oled_write_data(0x27);oled_write_data(0x38);oled_write_data(0x20);uint8_t i;for(i = 0;i < 5;i++)oled_show_chinese(i*24,0,i,24);//假如显示24号字符,一个占用 从0 开始,一个宽度24个字符oled_show_image(0,0,128,8,(unsigned char*)shui_data);//8*8  64while(1){ }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/62994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【工具变量】上市公司企业所在地城市等级直辖市、副省级城市、省会城市 计划单列市(2005-2022年)

一、包含指标&#xff1a; 股票代码 股票代码 股票简称 年份 所属城市 直辖市&#xff1a;企业所在地是否属于直辖市。1是&#xff0c;0否。 副省级城市&#xff1a;企业所在地是否属于副省级城市。1是&#xff0c;0否。 省会城市&a…

计算机视觉——相机标定(Camera Calibration)

文章目录 1. 简介2. 原理3. 相机模型3.1 四大坐标系3.2 坐标系间的转换关系3.2.1 世界坐标系到相机坐标系3.2.2 相机坐标系到图像坐标系3.2.3 像素坐标系转换为图像坐标系3.2.4 世界坐标转换为像素坐标 3.3 畸变3.3.1 畸变类型3.3.1.1 径向畸变&#xff08;Radial Distortion&a…

Golang内存模型总结1(mspan、mcache、mcentral、mheap)

1.内存模型 1.1 操作系统存储模型 从上到下分别是寄存器、高速缓存、内存、磁盘&#xff0c;其中越往上速度越快&#xff0c;空间越小&#xff0c;价格越高。 关键词是多级模型和动态切换 1.2 虚拟内存与物理内存 虚拟内存是一种内存管理技术&#xff0c;允许计算机使用比…

Qt Quick开发基础+实战(持续更新中…)

最近更新日期&#xff1a;2024/12/4 一、Qt Quick简介 写在前面&#xff1a; 本篇文章虽然只是作为我的学习笔记&#xff0c;但也作为我日后复习之用&#xff0c;所以会认真并详细记录&#xff0c;但会分重点。 1.3 新建Qt Quick Application工程 这节主要讲2个知识点&#x…

elementui table滚动分页加载

文章目录 概要 简化的实现示例&#xff1a; 小结 概要 在使用 Element UI 的 Table 组件时&#xff0c;如果需要实现滚动分页加载的功能&#xff0c;可以通过监听 Table 的滚动事件来动态加载更多数据。 简化的实现示例&#xff1a; <template><el-table ref"…

使用GDI对象绘制UI时需要注意的若干细节问题总结

目录 1、一个bitmap不能同时被选进两个dc中 2、CreateCompatibleDC和CreateCompatibleBitmap要使用同一个dc作为参数 3、不能删除已经被选入DC中的GDI对象 4、使用完的GDI对象&#xff0c;要将之释放掉&#xff0c;否则会导致GDI对象泄漏 5、CreateCompatibleBitmap返回错…

基于频谱处理的音频分离方法

基于频谱处理的音频分离方法 在音频处理领域&#xff0c;音频分离是一个重要的任务&#xff0c;尤其是在语音识别、音乐制作和通信等应用中。音频分离的目标是从混合信号中提取出单独的音频源。通过频谱处理进行音频分离是一种有效的方法&#xff0c;本文将介绍其基本原理、公…

Java项目实战II基于微信小程序的电子竞技信息交流平台的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网技术的飞速发展…

【机器学习】—Transformers的扩展应用:从NLP到多领域突破

好久不见&#xff01;喜欢就关注吧~ 云边有个稻草人-CSDN博客 目录 引言 一、Transformer架构解析 &#xff08;一&#xff09;、核心组件 &#xff08;二&#xff09;、架构图 二、领域扩展&#xff1a;从NLP到更多场景 1. 自然语言处理&#xff08;NLP&#xff09; 2…

Linux 文本处理三剑客基本用法

Linux文本处理三剑客 - grep sed awk 1. 基本用法 grep 是一种强大的文本搜索工具&#xff0c;用于在文件中搜索指定的模式&#xff08;通常是字符串或正则表达式&#xff09;&#xff0c;并输出匹配的行。以下是 grep 的一些基本用法&#xff1a; 基本语法 grep [选项] 模式…

解决 Maven 部署中的 Artifact 覆盖问题:实战经验分享20241204

&#x1f6e0;️ 解决 Maven 部署中的 Artifact 覆盖问题&#xff1a;实战经验分享 &#x1f4cc; 引言 在软件开发过程中&#xff0c;持续集成和持续部署&#xff08;CI/CD&#xff09;是提高开发效率和代码质量的关键手段。Hudson 和 Maven 是两种广泛使用的工具&#xff0…

3DMAX星空图像生成器插件使用方法详解

3DMAX星空图像生成器插件&#xff0c;一键生成星空或夜空的二维图像。它可用于创建天空盒子或空间场景&#xff0c;或作为2D艺术的天空背景。 【主要特点】 -单击即可创建星空图像或夜空。 -星数、亮度、大小、形状等参数。 -支持任何图像大小&#xff08;方形&#xff09;。…

Linux权限机制深度解读:系统安全的第一道防线

文章目录 前言‼️一、Linux权限的概念‼️二、Linux权限管理❕2.1 文件访问者的分类&#xff08;人&#xff09;❕2.2 文件类型和访问权限&#xff08;事物属性&#xff09;✔️1. 文件类型✔️2. 基本权限✔️3. 权限值的表示方法 ❕2.3 文件访问权限的相关设置方法✔️1. ch…

C# 动态类型 Dynamic

文章目录 前言1. 什么是 Dynamic&#xff1f;2. 声明 Dynamic 变量3. Dynamic 的运行时类型检查4. 动态类型与反射的对比5. 使用 Dynamic 进行动态方法调用6. Dynamic 与 原生类型的兼容性7. 动态与 LINQ 的结合8. 结合 DLR 特性9. 动态类型的性能考虑10. 何时使用 Dynamic&…

Python毕业设计选题:基于大数据的淘宝电子产品数据分析的设计与实现-django+spark+spider

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 电子产品管理 系统管理 数据可视化分析看板展示 摘要 本…

用 NotePad++ 运行 Java 程序

安装包 网盘链接 下载得到的安装包: 安装步骤 双击安装包开始安装. 安装完成: 配置编码 用 NotePad 写 Java 程序时, 需要设置编码. 在 设置, 首选项, 新建 中进行设置, 可以对每一个新建的文件起作用. 之前写的文件不起作用. 在文件名处右键, 可以快速打开 CMD 窗口, 且路…

vxe-table 树形表格序号的使用

vxe-table 树形结构支持多种方式的序号&#xff0c;可以及时带层级的序号&#xff0c;也可以是自增的序号。 官网&#xff1a;https://vxetable.cn 带层级序号 <template><div><vxe-grid v-bind"gridOptions"></vxe-grid></div> <…

SQL SERVER 2016 AlwaysOn 无域集群+负载均衡搭建与简测

之前和很多群友聊天发现对2016的无域和负载均衡满心期待&#xff0c;毕竟可以简单搭建而且可以不适用第三方负载均衡器&#xff0c;SQL自己可以负载了。windows2016已经可以下载使用了&#xff0c;那么这回终于可以揭开令人憧憬向往的AlwaysOn2016 负载均衡集群的神秘面纱了。 …

Groom Blender to UE5

Groom Blender to UE5 - Character & Animation - Epic Developer Community Forums Hello, 你好&#xff0c; While exporting my “groom” from blender to UE5, I notice that the curves have a minimal resolution in Unreal. However I would like to get the same …

TCP/IP协议图--TCP/IP基础

1. TCP/IP 的具体含义 从字面意义上讲&#xff0c;有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议。实际生活当中有时也确实就是指这两种协议。然而在很多情况下&#xff0c;它只是利用 IP 进行通信时所必须用到的协议群的统称。具体来说&#xff0c;IP 或 ICMP、TCP 或 UDP、…