31.硬件 - IIC
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了31.硬件 - IIC相关的知识,希望对你有一定的参考价值。
参考技术A 1、I2C(Inter-Integrated Circuit BUS) 集成电路总线。该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。2、IIC的物理层:
①、只要求两条总线线路:串行数据线 SDA,串行时钟线 SCL。IIC 是半双工,而不是全双工。
②、连接到总线的器件可通过其唯一地址和其它器件通信。主/从机角色和地址可配置,主机可作为主机发送器和主机接收器。
③、传输速率在标准模式下可以达到100kb/s,快速模式下可以达到400kb/s。
④、连接到总线的设备数量,只受总线的最大负载电容400pf限制。
⑤、IIC 是真正的多主机总线,它可在通讯过程中改变主机。如果多个主机同时请求总线,可通过冲突检测和仲裁,防止总线数据被破坏。而 SPI 每次通信前要把主机定死。
⑥、一个三极管,使用开集(极电集开发出去作为输出)电路。
⑦、发送原理:
3、IIC 协议:
①、I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。
②、数据的有效性:时钟SCL在高电平周期内,SDA线上的数据必须保持稳定。数据线仅可在时钟SCL为低电平时改变。
③、起始和结束条件:
④、起始和终止信号都是由主机发出。需要进行数据的收或发也是由主机所控制的。
⑤、应答:每当传输完一个字节的数据,主机需等待从机给出应答信号 ACK。从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期。(即接收器 接收到8位数据后,在第9个时钟周期,拉低 SDA)
4、数据帧格式:
1、实例框图:
2、发送流程:
①、发出start信号
②、把地址数据写入到发送寄存器,一写入就会自动的发出时钟,并把这8位数据从SDA发送给从设备。
③、第九个时钟会收到回应信号,查询寄存器看是否有ACK。有ACK表示数据发送成功了。
④、第九个时钟后会产生中断,IIC 控制器会拉低 CSL 信号,阻止主或从使用总线。
⑤、如果还需传输数据,则随后清中断来恢复时钟,使总线恢复使用来重复发送数据。否则结束(应该是结束流程中进行清中断操作,而非手动操作)。
⑤、发完后设置寄存器,让它发出终止信号。
3、初始化步骤:
①、设置时钟:时钟源PCLK(50MHZ)太快,需设置分频系数降低时钟至需要的 SCL。
②、
STM32使用IIC总线通讯协议在OLED屏幕上显示字符串汉字图像(硬件IIC)
参照:基于STM32-Oled(IIC)的使用
作者:奋斗的小殷
发布时间: 2021-05-07 13:09:26
网址:https://blog.csdn.net/boybs/article/details/116465668
目录
IIC简介
IIC协议简介
IIC通讯协议(Inter----Integrted Circuit)是由Phiips飞利浦公司开发的,由于他引脚少,硬件实现简单,可拓展性强,不需要UASRT(串口需要ch340进行电平转换),CAN通讯协议的外部收发设备,现在被广泛使用在系统内多个集成电路IC(芯片)间的通讯(芯片级的通讯一般都是使用IIC通讯)。
IIC是半双工的通讯方式(SPI是全双工,速度更快,不过线要多)
SDA:数据线
SCL:时钟线
IIC总线系统结构
-
项目他是一个支持多设备的总线。”总线”指多个设备共用的信号线,在一个IIC通讯总线中,可连接多个IIC通讯设备(最多同时连接127个),支持多个通讯主机及多个通讯从机。
-
项目项目一个IIC总线只使用两条总线线路,一条双向串行数据线(SDA),一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
-
每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备直接的访问。
IIC总线物理层特点
-
总线通过上拉电阻接到电源。当IIC设备空闲时,会输出高阻态(电阻很大,等效于断开,前面在讲GPIO四种输出模式里有提过),而当所有设备都空闲,都输出高阻态,由上拉电阻把总线拉成高电平。
-
多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式(CAN总线就是,类似单片机中断优先级)决定哪个设备占用总线。
-
具有三种传输模式:标准模式传输速率为100kbit/s,快速模式为400kbit/s,高速模式下可达3.4M/s,但目前大多IIC设备尚不支持高速模式。
硬件IIC、软件IIC
硬件IIC: 对应芯片上的IIC外设,有相对应的IIC驱动电路,其所使用的IIC管脚也是专用的(类似的PA9和PA10专门用于串口的收和发)
软件IIC: 一般是用普通的GPIO管脚,用软件控制管脚状态以及模拟IIC通信波形实现IIC的功能
区别:
硬件IIC的效率要远高于软件的(专门的硬件驱动电路都集成好了的),而软件IIC不受引脚限制(想要用哪个引脚作为IIC通讯都可以),接口比较灵活。
软件IIC是通过GPIO,软件模拟寄存器的工作方式,而硬件IIC是直接调用内部寄存器进行配置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件IIC的端口是固定的,所以会有所区别。
如何区分?
1.硬件IIC用法复杂,模拟IIC流程更加清楚
2.硬件IIC速度比模拟快,并且可以用DMA(DMA是一种通道,目前不用了解太多)
3.模拟IIC可以在任何管脚上,硬件IIC在固定管脚上
IIC通讯协议层
IIC协议层
IIC的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。
主机(单片机)写数据到从机(外设)
阴影部分代表主机给从机发送信号
白色部分代表从机给主机发送信号
-
S:数据由主机传输至从机(是个起始信号)
-
SLAVE ADDRESS(从机地址): 起始信号产生后,所有从机就开始紧接下来广播的从机地址信号。IIC总线,每个设备的地址都是唯一的,当主机广播的地址与某个设备的地址相同时,这个设备就被选中了,没被选中的设备讲会忽略之后的数据信号。根据IIC协议,这个从机地址可以是7位或10位。
-
R/W(读/写)传输方向选择位,为0:表示数据传输方向是由主机传输至从机,即主机向从机写数据。为1:则相反。
-
P:数据传输结束
-
从机接收传输方向选择位后,主机或从机会返回一个应答(ACK 上图A)或非应答(NACK 上图A/A)信号,只有接收到应答信号后,主机才能继续发送或接收数据。
从机(外设)写数据到主机(单片机)
阴影部分代表主机给从机发送信号
白色部分代表从机给主机发送信号
主机读从机数据:
配置方向传输位为”读数据”方向(主机读)。广播完地址后,接收到应答信号后,从机开始向主机返回数据(DATA),数据包大小也为8位,从机每发送完一个数,都会等待主机的应答信号(ACK),重复这个过程,可以返回N个数据,N没有限制大小。当主机希望停止接收数据时,就向从机返回一个非应答信号(NCAK),则从机自动停止数据传输。
通讯复合格式
阴影部分代表主机给从机发送信号
白色部分代表从机给主机发送信号
复合格式,该传输过程有两次起始信号(S),在第一次传输过程中,主机通过SLAVE_ADDRESS寻找到从设备后,发送一段”数据”,这段数据通常用于表示从设备内部的寄存器或存储器地址;第二次传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。
IIC通信过程
①空闲状态
②开始信号
③停止信号
④应答信号
⑤数据的有效性
⑥数据传输
① 空闲状态
IIC总线的SDA和SCL两条信号线同时处于高电平时,规定位总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
②开始信号③停止信号
起始信号:当SCL为高电平期间,SDA有高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
停止信号:当SCL为高电平期间,SDA由低到高的跳变;停止信号也是一种高电平跳变时序信号,而不是一个电平信号。
串口也有起始信号和停止信号,只不过串口是没有同步的
起始信号和停止信号一般由主机产生
④应答信号
发送器每发送一个字节(一个字节是8位),就在时钟脉冲9期间(下图所示)释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位)表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。
如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。
⑤数据的有效性
IIC总线进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。SDA数据线在SCL的每个时钟周期传输一位数据。
即:数据在SCL的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定
⑥数据传输
在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
STM32的IIC特性及架构
①软件模拟协议: 使用CPU直接控制通讯引脚的电平,产生出符合通讯协议标准的逻辑。可移植性强,用的最多。
②硬件实现协议: 由STM32的IIC片上外设专门负责实现IIC通讯协议(),只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器,就能完成数据收发。这种由硬件外设处理IIC协议的方式减轻了CPU的工作,且使软件设计更加简单(感觉和定时器/计数器很像)。
无论如何,芯片总还是会需要外接一些设备实现某种系统,为了与那些外设相区别,就将集成在芯片内,但是又不属于芯片本身(比如DSP,是一种微处理器,因此芯片中不属于微处理器的部分都是外设)的称为“片上外设”
STM32的IIC外设可用作通讯的主机及从机,支持100Kbit/s和400Kbits/s的速率,支持7位、10位设备地址,支持DMA数据传输,并具有数据校验功能。
其中SMBA:数据传输方式,是从高位开始传还是从低位开始传。
1.通讯引脚
STM32芯片有多个IIC外设,它们的IIC通讯信号引出到不同的GPIO引脚上,使用时必须配置这些指定的引脚(硬件IIC)。下图中有三组外设IIC引脚,如果我们使用软件方式的话,任何一个IO口都可以作为IIC通讯接口。
2.时钟控制逻辑
SCL线的时钟信号,由IIC接口根据时钟控制寄存器(CCR)控制,控制的参数主要位时钟频率。
-
可选择IIC通讯的“标准/快速”模式,这两个模式分别对应100/400Kbits/s的通讯速率。
-
在快速模式下可选择SCL时钟的占空比,可选T(low)/T(high) = 2或T(low)/T(high)=16/9模式(如下图所示)。
-
CCR寄存器中12位的配置因子CCR,它与IIC外设的输入时钟源共用作用,产生SCL时钟。STM32的IIC外设输入时钟源位PCKL1.
计算时钟频率(CCR的值)
-
标准模式
T high = CCR* Tpckl1
T low= CCR* Tpclk1 -
快速模式中 Tlow/Thigh =2时:
Thigh = CCR* Tpckl1
Tlow = 2* low* Tpckl1 -
快速模式中 Tlow/Thigh =16/9时:
Thigh = 9* CCR* Tpckl1
Tlow = 16* low* Tpckl1
例如(快速模式中 Tlow/Thigh =2时):PCLK1 = 36MHz(AHB1总线的频率 是个二分频),想要配置400Kbits/s 方法:
PCLK时钟周期: TPCLK1 = 1/36 000 000
目标SCL时钟周期: TSCL = 1/400 000
SCL时钟周期内的高电平时间: Thigh = TSCL/3
SCL时钟周期内的低电平时间: Tlow = 2*TSCL/3
计算CCR的值 : CCR = THIGH/TPCLK1 = 30
计算出来的值写入到寄存器即可
3.数据控制逻辑
IIC的SDA信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、PEC寄存器以及SDA数据线。
当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过SDA信号线发送出去(上面讲到的SMBA来控制传输顺序,是从高位开始传的)。
当从外部接收数据的时候,数据移位寄存器把SDA信号线采样到的数据一位一位地存储到”数据寄存器”中。
使用IIC外设通讯时,在通讯的不同阶段它会对”状态寄存器(SR1和SR2)”的不同数据位写入参数,通过读取这些寄存器标志来了解通讯状态。
主发送器
-
控制产生起始信号(S),当发生起始信号后,它产生事件”EV5”(Event5),并会对SR1寄存器的 SB 位置1(如下图所示),表示起始信号已经发生。
-
发生设备地址并等待应答信号,若有从机应答,则产生时间 EV6 及 EV8 ,这时SR1寄存器的ADDR位及TXE位被置1(如下图所示),ADDR位1表示地址已经发送,TEX表示数据寄存器为空。
-
往IIC的数据寄存器DR写入要发送的数据,这时TXE位会被重置为0,表示数据寄存器非空,IIC外设通过SDA信号线一位位把数据发送出去后,又会产生EV8事件,即TXE被置1,重复这个过程,可发送多个字节。
-
发送数据完成后,控制IIC设备产生一个停止信号P,这个时候产生EV2事件,SR1的TEX位及BTF位被置1(如下图所示),表示通讯结束。
STM32的IIC结构体和库函数
STM32的IIC结构体
在固件包i2c.h里面
typedef struct
{
uint32_t I2C_ClockSpeed; //设置SCL时钟频率,此值要低于400 000
uint16_t I2C_Mode; //指定工作模式,可选IIC模式及SMBUS模式
uint16_t I2C_DutyCycle; //时钟占空比,可选low/high = 2:0或16:9
uint16_t I2C_OwnAddress1; //自身的IIC设备地址
uint16_t I2C_Ack; //使能或者关闭响应,一般是使能
uint16_t I2C_AcknowledgedAddress; //指定地址长度,可为7或10
}I2C_InitTypeDef;
-
I2C_ClockSpeed
设置IIC的传输速率,在调用初始化函数时,函数会根据我们输入的数值经过运算后把时钟因子写入到IIC的时钟控制寄存器CCR。而我们写入的这个参数值不得高于400Khz(如下图所示)。
实际上由于CCR寄存器不能写入小数类型的时钟因子,影响到SCL的实际频率可能会低于本成员设置的参数值,这时除了通讯会稍微慢点以外,不会对IIC的标准通讯造成其他影响。
-
I2C_Mode
选择IIC的使用方式,有IIC模式(IIC_Mode_IIC)和SMBus主、从模式(IIC_Mode_SMBusHost、IIC_Mode_SMBusDevice)
IIC不需要在此处区分主从模式,直接设置IIC_Mode_IICj即可 -
I2C_DutyCycle
设置IIC的SCL线时钟的占空比。该配置有两个选择,分别为低电平时间比高电平时间为2:1(IIC_DutyCycle_2)和16:9(IIC_DutyCycle_16_9).
其实这两个模式的比例差别并不大,一般要求都不会如此严格,这里随便选就可以了。
-
I2C_OwnAddress1
配置STM32的IIC设备自己的地址,每个连接到IIC总线上的设备都有一个自己的地址,作为主机也不例外。地址可以设置为7位或10位(受下面IIC_AcknowledgeAddress成员决定),只要该地址是IIC总线上唯一的即可。
STM32的IIC外设可同时使用两个地址(如下图所示),即同时对两个地址作出响应(使用非常的灵活),这个结构体成员IIC_OwnAddress1配置的是默认的,OAR1寄存器存储的地址,若需要设置第二个地址寄存器OAR2,可使用IIC_OwmAddress2Conig函数来配置,OAR2不支持10位地址。
-
I2C_Ack
配置IIC应答是否使能,设置位使能则可以发送响应信号,一般配置位允许应答(IIC_Ack_Enable),这是绝大多数遵循IIC标准的设备的通讯要求,改为禁止应答(IIC_Ack_Disable)往往会导致通讯错误。 -
I2C_AcknowledgedAddress
选择IIC的寻址模式是7位或者是10位地址,这需要根据实际连接到IIC总线上设备的地址进行选择,这个成员的配置也影响到IIC_OwnAddress成员,只有这里设置成10位模式时,IIC_OwnAddress1才支持10位地址
配置完这些结构体成员的值,调用库函数IIC_Init就可以把结构体的配置写入到对应的寄存器中了。
STM32的IIC库函数
固件包.h文件里都给出了,仅列出了部分。
//配置自身设备地址2
void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
//发送设备地址
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
//接收数据
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
//停止接收
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
//IIC外设开始正常工作
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
OLED屏幕介绍
OLED即有机发光管(Organic Light-Emitting Diode,OLED)。OLED显示技术具有自发光、广视角、几乎无穷高的对比度、较低功耗、极高反应速度、可用于绕曲性面板、使用温度范围广、构造及制程简单等有点,被认为是下一代的平面显示屏新兴应用技术。
OLED显示和传统的LCD显示不同,其可以自发光,所以不需要背光灯,这使得OLED显示屏相对于LCD显示屏尺寸更薄,同时显示效果更优。
常用的OLED屏幕有蓝色、黄色、白色等几种。屏的大小为0.96寸,像素点为
128*64,所以我们称为0.96oled屏或者12864屏。
OLED屏幕特点
1.模块尺寸:23.7 *23.8mm
2.电源电压:3.3-5.5V
3.驱动芯片:SSD1306
4.测试平台:提供 k60/k10,9s12XS128,51,stm32,stm8等单片机
OLED屏幕接线说明
OLED屏幕显存
OLED本身是没有显存的,他的显存是依赖SSD1306(驱动芯片)提供的,而SSD1306提供一块显存。
SSD1306显存总共为128*64bit大小,SSD1306将这些显存分成了8页。每页包含了128个字节。
OLED屏幕原理
STM32内部建立一个缓存(共128*8个字节),每次修改的时候,只是修改STM32上的缓存(实际上就是SRAM),修改完后一次性把STM32上的缓存数据写入到OLED的GRAM。
这个方法也有坏处,对于SRAM很小的单片机(51系列)就比较麻烦。
OLED屏幕常用指令
上图第二列:指令的使用
- 指令0X81: 设置对比度。包含两个字节,第一个0X81为命令,随后方法是的一个字节要设置这个对比度,值越大屏幕越亮。
- 指令0XAE/0XAF: 0XAE为关闭显示命令,0XAF为开启显示命令
- 指令0X8D: 包含两个字节,第一个为命令字,第二个为设置值,第二个字节的BIT2表示电荷泵的开关状态,该位为1开启电荷泵,为0则关闭。模块初始化的时候,这个必须要开启,否则看不到屏幕显示。
- 指令0XB0~B7:用于设置页地址(前面讲到了,一共分成了8页),其低三位的值对应GRAM页地址(很好理解,二进制三位可表示0–8)。
- 指令0X00~0X0F:用于设置显示时的起始列地址低四位。
- 指令0X10~0X1F: 用于设置显示时的起始列地址高四位。
OLED屏幕字模软件的使用
OLED打点方式(64*128的点阵)
OLED点阵的点亮方式,举个显示”P”的例子,最左边位最高位P7。
左边的数字在右边点阵中是从下往上写的
-
1.可以看出,要想显示”P”,首先写入0x1f,则显示一个竖杠,之后控制器自动水平移动到下一列。
-
2.再写入0X05,则出现两个小横杆,这个两个横杆就是0X05中0000 0101中两个1所处的位置,写完第二列后,控制器自动跳到第三列.
-
3.再写入0X07,第四列写入0X00后,P就显示出来了。这也说明,即使你只想再一列的最上端显示一个小点,即写入0X01.
-
4.不能一次性控制一个点阵,只能一次性控制八位点阵,即一列点阵。这也决定了字模选择的取模方式为“列行式“。
OLED显示字符串
显示效果:
oled.c
#include "stm32f10x.h"
#include "oled.h"
#include "delay.h"
#include "OLED_Codetab.h"//字库 下面给出了
//OLED存放格式 分成了8页 每页都是8*128(如下所示)
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStructure; //I2C结构体配置 i2c.h里面
GPIO_InitTypeDef GPIO_InitStructure; //GPIO结构体配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //时钟使能 rcc.h里面
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
//PB6——>SCL PB7——>SDA 接线方式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//IIC 选择复用开漏
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//I2C
I2C_DeInit(I2C1);//初始化使用它
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//应答 使能
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//地址选7位
I2C_InitStructure.I2C_ClockSpeed = 400000;//时钟速度400K
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//2:1 16:9都可以
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//I2C模式
I2C_InitStructure.I2C_OwnAddress1 = 0X10;//主机地址 随便写
I2C_Init( I2C1, &I2C_InitStructure);//初始化
I2C_Cmd( I2C1, ENABLE); //使能I2C1
}
//硬件IIC配置
//对照上面的:STM32的IIC特性及架构 3.数据控制逻辑图
void I2C_WriteByte(uint8_t addr , uint8_t data)
{
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //检测I2C总线是否繁忙 等待繁忙完
I2C_GenerateSTART(I2C1, ENABLE); //开启IIC1
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5 主模式 检查是否应答
I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter); //发生器地址(7位) OLED_ADDRESS的值在oled.h中定义了 方向:发送 广播状态(找从机地址吧)
while(!I2C_CheckEvent(I2C1 ,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //EV6
I2C_SendData( I2C1, addr); //发送寄存器地址 上面形参
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8 主模式 每次发送完都要有应答的 需要检测应答
I2C_SendData( I2C1 , data); //发送数据 上面形参
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8 Ö÷ģʽ
I2C_GenerateSTOP(I2C1,ENABLE ); //关闭I2C总线
}
//给OLED
//写命令
void WriteCmd(unsigned char I2C_Cmd)
{
I2C_WriteByte(0X00,I2C_Cmd);//固件库函数 在0X00地址(ROM里)写
}
//写数据
void WriteData(unsigned char I2C_Data)
{
I2C_WriteByte(0X40 , I2C_Data);
}
//OELD屏幕初始化
void OLED_Init(void)
{
//下面 这部分代码是厂家提供的 复制过来
delay_ms(100);
WriteCmd(0xAE); //display off
WriteCmd(0x20); //Set Memory Addressing Mode
WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
WriteCmd(0xc8); //Set COM Output Scan Direction
WriteCmd(0x00); //---set low column address
WriteCmd(0x10); //---set high column address
WriteCmd(0x40); //--set start line address
WriteCmd(0x81); //--set contrast control register
WriteCmd(0xff); //ÁÁ¶Èµ÷½Ú 0x00~0xff
WriteCmd(0xa1); //--set segment re-map 0 to 127
WriteCmd(0xa6); //--set normal display
WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
WriteCmd(0x3F); //
WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
WriteCmd(0xd3); //-set display offset
WriteCmd(0x00); //-not offset
WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
WriteCmd(0xf0); //--set divide ratio
WriteCmd(0xd9); //--set pre-charge period
WriteCmd(0x22); //
WriteCmd(0xda); //--set com pins hardware configuration
WriteCmd(0x12);
WriteCmd(0xdb); //--set vcomh
WriteCmd(0x20); //0x20,0.77xVcc
WriteCmd(0x8d); //--set DC-DC enable
WriteCmd(0x14); //
WriteCmd(0xaf); //--turn on oled panel
}
//设置起点坐标
void OLED_SetPos(unsigned char x, unsigned char y)
{
WriteCmd(0xb0 + y); //这些都是固定的 也是看上面的指令表
WriteCmd((x & 0xf0) >> 4 | 0x10); //取高位
WriteCmd((x & 0x0f ) | 0x01); //取低位
}
//全屏填充 填充黑点 好像
void OLED_Full(unsigned char Full_Data)
{
unsigned char n, m ;//前面讲了 屏幕分成了8页 每个都要处理
for( m = 0 ; m < 8 ; m++)
{
WriteCmd(0xb0 + m);//0xb0 列的起点坐标 上面有
WriteCmd(0x00);
WriteCmd(0x10);
for( n = 0 ; n < 128 ; n++)//128列
{
WriteData(Full_Data);
}
}
}
//清屏函数 让屏幕什么都不显示
void OLED_Clear(void)
{
OLED_Full(0x00);
}
//oled打开 泵
void OLED_Open(void)
{
WriteCmd(0x8D); //设置电荷泵指令(指令表上有)
WriteCmd(0x14); //开启电荷泵
WriteCmd(0xaf); //OLED唤醒 指令大小写都可以 最好和指令表上一致
}
//oled关闭
void OLED_Close(void)
{
WriteCmd(0x8D);
WriteCmd(0x10); //关闭电荷泵
WriteCmd(0xAE); //关闭oled
}
//显示字符串 坐标 要显示的内容 格式有6*8 8*16
void OLED_ShowStr(unsigned char x, unsigned char y , unsigned char ch[] , unsigned TestSize)
{
unsigned char c = 0 , i = 0, j = 0;
switch(TestSize)
{
case 1://6*8
{
while(ch[j] != '\\0')//字符串结束标记
{
c = ch[j] - 32;//大小写的转化
if(x > 126)//X越界了 放到第一个位置
{
x = 0 ;
y ++;
}
OLED_SetPos(x , y);
for( i = 0 ; i< 6 ; i++)
WriteData(F6X8[c][i]);//显示到屏幕上 F6X8在头文件里面
x+= 6;//格式:6*8 跳转到下一个字符(看头文件6个组成一个字符)
j++;
}
}break;
case 2://8*16
{
以上是关于31.硬件 - IIC的主要内容,如果未能解决你的问题,请参考以下文章
STM32使用IIC总线通讯协议在OLED屏幕上显示字符串汉字图像(硬件IIC)