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.rhkb.cn/news/484008.html

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

相关文章

Python 数据分析用库 获取数据(二)

Beautiful Soup Python的Beautiful Soup&#xff08;常被称为“美丽汤”&#xff09;是一个用于解析HTML和XML文档的第三方库&#xff0c;它在网页爬虫和数据提取领域具有广泛的应用。 作用 HTML/XML解析&#xff1a; Beautiful Soup能够解析HTML和XML文档&#xff0c;包括不…

数据链路层(四)---PPP协议的工作状态

1 PPP链路的初始化 通过前面几章的学习&#xff0c;我们学了了PPP协议帧的格式以及组成&#xff0c;那么对于使用PPP协议的链路是怎么初始化的呢&#xff1f; 当用户拨号上网接入到ISP后&#xff0c;就建立起了一条个人用户到ISP的物理链路。这时&#xff0c;用户向ISP发送一…

QT 实现QStackedWidget切换页面右移动画

1.实现效果 以下是一个QStackedWidget,放了两个QPushButton在上面,点击切换不同的界面。 为了方便查看动画特效,设置了每个界面的背景图片。 2.实现思路 首先截取当前界面的图片,渲染到一个QLabel上,然后设置QPropertyAnimation动画,动画的作用对象就是这个QLabel,不断…

开源C代码之路:一、Gitee

开源c代码之路&#xff1a;一&#xff0c;Gitee 前言1、开源项目2、从哪里找&#xff1f;3、举个例子4、总结&#xff1a; 本系列回顾清单开源代码示例 前言 从开源开发的角度&#xff0c;由浅入深&#xff0c;一步步初探C语言编程的入门之路。 本篇讲解&#xff1a;Gitee 1…

系统思考—战略决策

最近与一位企业创始人深入交流&#xff0c;聊到了他这几年来的多次尝试与探索。回顾过去&#xff0c;他尝试了很多方向&#xff0c;投入了大量的精力与资源&#xff0c;但今天他却感到&#xff0c;无论哪个业务模块&#xff0c;都没有真正突破&#xff0c;原本的业务也未见明显…

视频监控汇聚平台Liveweb视频安防监控实时视频监控系统操作方案

Liveweb国标GB28181视频平台是一种基于国标GB/T28181协议的安防视频流媒体能力平台。它支持多种视频功能&#xff0c;包括实时监控直播、录像、检索与回看、语音对讲、云存储、告警以及平台级联等功能。该平台部署简单、可扩展性强&#xff0c;支持全终端、全平台分发接入的视频…

HTML 添加 文本水印

body,html {margin: 0;height: 100vh;width: 100vw;} // 自定义文案const setting {text: "水印文案", // 水印内容innerDate: true, // 在水印下方增加日期width: 110, // 水印宽度};// 自定义文字水印const watermark (function () {return {build: function (a…

计算机的错误计算(一百七十四)

摘要 探讨 MATLAB 关于计算机的错误计算&#xff08;一百七十三&#xff09;中多项式的秦九韶&#xff08;或Horner&#xff09;形式的计算误差。 在计算机的错误计算&#xff08;一百七十三&#xff09;中&#xff0c;我们讨论了一个多项式的计算误差。本节探讨其对应秦九韶&…

扩展 SOC 的能力以应对更多威胁

过去 18 个月中&#xff0c;安全运营的一个主要趋势是注重“用更少的资源做更多的事情”。这种趋势一直延续到今天&#xff0c;尽管这一挑战并非安全领域独有——许多其他技术子领域也感受到了同样的压力——但安全领域可能是最不能有效吸收这种额外工作量的领域。 Exabeam 和…

堆叠的简析

堆叠 堆叠的概念 堆叠是指将一台以上的交换机组合起来共同工作&#xff0c;以便在有限的空间内提供尽可能多的端口。‌ 堆叠技术可以通过专用连接电缆将多台交换机连接成一个堆叠单元&#xff0c;从而增加端口密度和管理效率。‌12 堆叠与级联有所不同。级联的交换机之间可以…

vulnhub靶场之momentum-2

前言 靶机采用virtual box虚拟机&#xff0c;桥接网卡 攻击采用VMware虚拟机&#xff0c;桥接网卡 靶机&#xff1a;momentum-2 192.168.1.40 攻击&#xff1a;kali 192.168.1.16 主机发现 使用arp-scan -l扫描 信息收集 使用namp扫描 这里的命令对目标进行vulner中的漏…

【Elasticsearch】实现分布式系统日志高效追踪

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

【0x3D】HCI_Remote_Host_Supported_Features_Notification事件详解

目录 一、事件概述 二、事件格式及参数说明 2.1. HCI_Remote_Host_Supported_Features_Notification事件格式 2.2. BD_ADDR 2.3. Remote_Host_Supported_Features 三、事件作用 3.1. 设备特性沟通与理解 3.2. 功能协商与性能优化 3.3. 设备管理与配置更新 四、应用场…

【C++】栈和队列的模拟实现(适配器模式)

不论是C语言还是C&#xff0c;我们都用其对应的传统写法对栈和队列进行了模拟实现&#xff0c;现在我们要用新的方法模拟实现栈和队列&#xff0c;这个新方法就是适配器模式。 C语言传统写法&#xff1a; C语言模拟实现栈 C传统写法&#xff1a;C模拟实现栈 1.容器适配器 …

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

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

【HarmonyOS】鸿蒙应用地理位置获取,地理名称获取

【HarmonyOS】鸿蒙应用地理位置获取&#xff0c;地理名称获取 一、前言 首先要理解地理专有名词&#xff0c;当我们从系统获取地理位置&#xff0c;一般会拿到地理坐标&#xff0c;是一串数字&#xff0c;并不是地理位置名称。例如 116.2305&#xff0c;33.568。 这些数字坐…

【优选算法篇】寻找隐藏的宝藏:用二分查找打开算法世界的大门(上篇)

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

【后端面试总结】golang channel深入理解

在Go语言中&#xff0c;Channel是一种用于在goroutine之间进行通信和同步的重要机制。它提供了一种安全、类型安全的方式来传递数据&#xff0c;使得并发编程变得更加直观和简单。本文将详细介绍Golang中Channel的基本概念、创建与关闭、发送与接收操作&#xff0c;以及相关的使…

centos 手动安装libcurl4-openssl-dev库

下载源代码 curl downloadshttps://curl.se/download/ 选择需要下载的版本&#xff0c;我下载的是8.11.0 解压 tar -zxvf curl-8.11.0 查看安装命令 查找INSTALL.md&#xff0c;一般在docs文件夹下 –prefix &#xff1a;指定安装路径&#xff08;默认安装在/usr/local&…

基于TensorFlow框架的线性回归实现

目录 ​编辑 线性回归简介 TensorFlow简介 线性回归模型的TensorFlow实现 1. 安装TensorFlow 2. 导入必要的库 3. 准备数据 4. 定义模型 5. 定义损失函数 6. 定义优化器 7. 训练模型 8. 评估模型 9. 模型参数的可视化 10. 模型预测的准确性评估 结论 在统计学和…