IIC 通信协议之stm32 驱动OLED

前言

    使用stm32 驱动4 Pin 的OLED, 现在网上开源的资料多的是,但是为了锻炼自己使用第一手资料的能力,今天我还是从数据手册开始,从头造一波轮子,同时也是为了加深自己对 IIC 协议的理解 ,本系列内容我会从单片机和linux两个板子做一些OLED的 验证,希望后面大家在学习IIC 相关内容的时候,可以少走一些弯路。为了大家学习方面,这些文章也会在我的微信公众号同步,方便大家随时查看,欢迎大家扫码关注。

在这里插入图片描述

1. 查阅数据手册

   在我们实际工作中,需要我们从头造轮子的机会其实并不多,但是作为搞嵌入式这个行业的,阅读一些简单的数据手册的能力还是要有的,万一碰到碰到一个比较棘手的问题,说不定就需要我们不得不去看芯片的参考手册了。本篇我就以4Pin 的OLED 使用的SSD1306为例,通过stm32 实现对他的驱动。我们 打开他的数据手册,首先不要被全英文的吓到了,现在网上各种的翻译软件都比较给力。再说了,这个手册其实并不需要从头到尾一字不落的读完,首先我们看一下芯片的简单说明,了解芯片的大致的特性。其次:根据自己选择的芯片,使用的通讯方式,着重去看相对应的章节,比如我们本次使用的就是4 Pin的 IIC通信的,所以我们直接去找参考手册中介绍IIC 的.

在这里插入图片描述
a. IIC 从机地址是有SA0 决定的,并且R/W# 决定是读取数据还是写入数据。R/W# = 0 为写模式,R/W# = 1 为读数据。

IIC 通信协议:
在这里插入图片描述
S 信号 和 P 信号:
在这里插入图片描述
ACK 信号 和NAck 信号:
在这里插入图片描述
数据传输的时候要保证SDA 总线上数据稳定:
在这里插入图片描述
发送数据还是命令室友D/C# 引脚决定的: D/C# = 1 发送data , D/C# = 0 发送的是命令;

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

SSD 1306 显存大小: 128列 * 64行

在这里插入图片描述
如果要驱动SSD1306 首先要实现IIC 总线的驱动代码,即IIC 协议的实现,如果使用的是stm32单片机 来驱动的话,其实可以直接使用硬件IIC,当然了软件IIC也是可以的,本篇我们就先以软件模拟IIC来驱动他。

2. 软件模拟IIC 实现

2.1

#define SCL_Pin GPIO_Pin_6
#define SDA_Pin GPIO_Pin_7
#define IIC_GPIO_Port GPIOB#define OLED_SCLK_LOW   GPIO_ResetBits(GPIOB,GPIO_Pin_6)
#define OLED_SCLK_HIGH  GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define OLED_SDA_LOW    GPIO_ResetBits(GPIOB,GPIO_Pin_7)
#define OLED_SDA_HIGH   GPIO_SetBits(GPIOB,GPIO_Pin_7)void OLED_Config(void)
{              GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); GPIO_InitStructure.GPIO_Pin = SCL_Pin|SDA_Pin;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(IIC_GPIO_Port, &GPIO_InitStructure);
}/*IIC  起始信号*/
void i2c_start()
{OLED_SCLK_HIGH;OLED_SDA_HIGH;OLED_SDA_LOW;OLED_SCLK_LOW;
}/*IIC 停止信号*/
void i2c_stop()
{OLED_SCLK_HIGH;OLED_SDA_LOW;OLED_SDA_HIGH;}/*等待应答:提供一个scl 时钟周期*/
void i2c_wait_ack(void)
{OLED_SCLK_HIGH;OLED_SCLK_LOW;
}void Write_IIC_Byte(unsigned char IIC_Byte)
{unsigned char i;unsigned char m,da;da=IIC_Byte;OLED_SCLK_LOW;for(i=0;i<8;i++)		{m=da;m=m&0x80;if(m==0x80){OLED_SDA_HIGH;}else OLED_SDA_LOW;da=da<<1;OLED_SCLK_HIGH;OLED_SCLK_LOW;}
}/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{i2c_start();Write_IIC_Byte(0x78);       //Slave address,SA0=0i2c_wait_ack();	Write_IIC_Byte(0x00);		//write commandi2c_wait_ack();	Write_IIC_Byte(IIC_Command); i2c_wait_ack();	i2c_stop();
}/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{i2c_start();Write_IIC_Byte(0x78);			//D/C#=0; R/W#=0i2c_wait_ack();	Write_IIC_Byte(0x40);			//write datai2c_wait_ack();	Write_IIC_Byte(IIC_Data);i2c_wait_ack();	i2c_stop();
}void OLED_WR_Byte(unsigned dat,unsigned cmd)
{if(cmd){Write_IIC_Data(dat);}else {Write_IIC_Command(dat);	}
}

3. OLED 设备驱动程序


void OLED_Init(void)
{ OLED_Config();GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);	delay_ms(100);OLED_WR_Byte(0xAE,OLED_CMD);//--display offOLED_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  OLED_WR_Byte(0xB0,OLED_CMD);//--set page addressOLED_WR_Byte(0x81,OLED_CMD); // contract controlOLED_WR_Byte(0xFF,OLED_CMD);//--128   OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverseOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 dutyOLED_WR_Byte(0xC8,OLED_CMD);//Com scan directionOLED_WR_Byte(0xD3,OLED_CMD);//-set display offsetOLED_WR_Byte(0x00,OLED_CMD);//OLED_WR_Byte(0xD5,OLED_CMD);//set osc divisionOLED_WR_Byte(0x80,OLED_CMD);//OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode offOLED_WR_Byte(0x05,OLED_CMD);//OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge PeriodOLED_WR_Byte(0xF1,OLED_CMD);//OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartionOLED_WR_Byte(0x12,OLED_CMD);//OLED_WR_Byte(0xDB,OLED_CMD);//set VcomhOLED_WR_Byte(0x30,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enableOLED_WR_Byte(0x14,OLED_CMD);//OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}  void OLED_Set_Pos(unsigned char x, unsigned char y)
{OLED_WR_Byte(0xb0+y,OLED_CMD);OLED_WR_Byte(((x&0xF0) >> 4)|0x10, OLED_CMD);OLED_WR_Byte( (x&0x0F), OLED_CMD);
}void OLED_Display_On(void)
{OLED_WR_Byte(0x8D,OLED_CMD);  //设置电荷泵OLED_WR_Byte(0x14,OLED_CMD);  //开启电荷泵OLED_WR_Byte(0xAF,OLED_CMD);  //OLED唤醒
}void OLED_Display_Off(void)
{OLED_WR_Byte(0x8D,OLED_CMD);	//设置电荷泵OLED_WR_Byte(0x10,OLED_CMD);    //关闭电荷泵OLED_WR_Byte(0xAE,OLED_CMD);    //关闭屏幕显示
}void OLED_Clear(void)
{u8 i = 0, n = 0; for(i = 0; i < 8; i++){OLED_WR_Byte(0xb0+i,OLED_CMD);	//设置页地址OLED_WR_Byte(0x00,OLED_CMD);    // 设置显示位置-列低地址OLED_WR_Byte(0x10,OLED_CMD);    // 设置显示位置-列高地址for(n = 0; n < 128; n++) OLED_WR_Byte(0,OLED_DATA);}
}void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 Char_size)
{unsigned char c = 0, i = 0;c = chr - ' ';if(x > 128 - 1){x = 0;y += 2;}if(Char_size == 8){OLED_Set_Pos(x,y);for(i = 0; i < 8; i++)OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);		//显示低字节OLED_Set_Pos(x,y+1);for(i = 0; i < 8; i++ )OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);   //显示高字节}else {字体为6号OLED_Set_Pos(x,y);for(i=0;i<6;i++)OLED_WR_Byte(F6x8[c][i],OLED_DATA);}
}void OLED_ShowString(u8 x, u8 y,u8* chr, u8 Char_size)
{while(*chr != '\0'){OLED_ShowChar(x,y,*chr, Char_size);x+=Char_size;if(x > 120){x = 0;y += 2;}	chr++;}
}

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

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

相关文章

Transformer ZOO

Natural Language Processing Transformer:Attention is all you need URL(46589)2017.6 提出Attention机制可以替代卷积框架。引入Position Encoding&#xff0c;用来为序列添加前后文关系。注意力机制中包含了全局信息自注意力机制在建模序列数据中的长期依赖关系方面表现出…

Linux调试器:gdb的使用

我们知道在Visual Studio2022中&#xff0c;我们可以对编好的代码进行调试来分析dug的位置&#xff0c;那Linux环境下如何进行程序的调试呢&#xff1f;那就是使用Linux调试器&#xff1a;gdb。 目录 1.背景 2. 开始使用 1.背景 程序的发布方式有两种&#xff0c;debug模式…

Java Web 实战 20 - HTTP PK HTTPS ? HTTPS 大获全胜 ?

HTTP VS HTTPS 一 . HTTPS1.1 臭名昭著的运营商劫持1.2 加密是什么 ?1.3 HTTPS 的加密过程对称加密非对称加密引入 "证书" 机制 1.4 HTTP VS HTTPS Hello , 大家好 , 好久没有更新 JavaWeb 模块的内容了 . 博主这篇文章主要给大家讲解一下 HTTPS 以及与 HTTP 的区别…

Spring IOC/DI和MVC及若依对应介绍

文章目录 一、Spring IOC、DI注解1.介绍2.使用 二、Spring MVC注解1.介绍2.使用 一、Spring IOC、DI注解 1.介绍 什么是Spring IOC/DI&#xff1f; IOC(Inversion of Control&#xff1a;控制反转)是面向对象编程中的一种设计原则。其中最常见的方式叫做依赖注入&#xff08;…

Backtrader绘图cerebro.plot报错问题的处理

Backtrader绘图cerebro.plot报错问题的处理 1.问题描述 在jupyter 中使用BackTrader &#xff0c;使用绘图功能时&#xff1a; cerebro.plot() 提示错误&#xff1a;ValueError: Axis limits cannot be NaN or Inf 由于backtrader 要求有7列数据&#xff0c;最后一列openint…

(数据结构)算法的时间复杂度

注意语句频度和时间复杂度的区别&#xff0c;语句频度是指语句执行的次数&#xff0c;不可以像时间复杂度一样近似次数和省略常数项

图书管理系统(图文详解,附源码)

前言&#xff1a;本文旨在用面向对象的思想编程实现图书管理系统&#xff0c;功能包括增删查找&#xff0c;完整源码放在文末&#xff0c;大家有需自取 目录 一.整体框架 二.书籍和书架 书籍(Book) 书架(BookRack) 三.对书籍的相关操作 操作接口(IOperation) 新增图书(A…

支付、结算、对账流程

1、支付过程概览 2、微信支付流程 以微信支付为例,用户使用北京银行,商户收款银行为工行银行,列出机构名 用户在商户处选购商品或服务,选择使用微信支付进行付款。用户打开微信支付,输入支付密码或进行指纹识别等身份验证。微信支付系统将支付请求发送给北京银行。北京银行…

校园服装定制服务预约小程序的效果如何

对校园服装定制商家而言&#xff0c;如今线下流量稀缺&#xff0c;同行多且竞争激烈&#xff0c;同时这一行面对的消费者非大众&#xff0c;因此各品牌间都在通过各种方式进行同城或多地的客户拓展&#xff0c;但线下方式无疑是比较低效的。线上是一个不错的选择&#xff0c;不…

用cmd看星球大战大电影,c++版本全集星球大战,超长多细节

用cmd看星球大战 最近发现了一个有趣的指令。 是不是感觉很insteresting呢 教程 进入控制面板&#xff0c;点击系统与安全 然后&#xff0c;进入以后&#xff0c;点击启用或关闭 Windows 功能 启用Telnet Client并点击确定 用快捷键winr打开我们的cmd 输入指令 telnet towe…

腾讯云CVM服务器标准型/高IO/计算/大数据使用场景及选择说明

腾讯云CVM服务器多种机型使用场景说明&#xff0c;如标准型、内存型、高 IO 型、计算型、大数据型、异构型和批量型&#xff0c;腾讯云百科txybk.com分享不同CVM实例规格配置适合使用场景说明&#xff1a; 腾讯云CVM云服务器 标准型&#xff1a;适合中小型 Web 应用、中小型数据…

图解系列--认证

单向散列函数 1.什么是单向散列函数 单向散列函数有一个输入和一个输出&#xff0c;其中输入称为消息&#xff0c;输出称为散列值。单向散列函数可以根据消息的内容计算出散列值&#xff0c;而散列值就可以被用来检查消息的完整性。 在指定的散列函数处理下&#xff0c;无论输…