STM32基于IIC通信协议的OLED模块使用(详解) 您所在的位置:网站首页 oled屏幕用什么膜 STM32基于IIC通信协议的OLED模块使用(详解)

STM32基于IIC通信协议的OLED模块使用(详解)

2024-06-12 05:36| 来源: 网络整理| 查看: 265

目录

前言

一、项目内容

实验简介

二、IIC模块

1、IIC协议简介

2、物理层

3、协议层

4、硬件IIC代码配置

5、软件模拟IIC配置

1、起始信号与停止信号

2、从机应答信号

3、数据的有效性

4、数据传输

三、OLED模块

1、软件配置

2、OLED原理

1、OLED初始化函数

2、写入起始坐标

3、清屏函数

4、显示字符串

5、显示文字

6、显示图片(bmp)

4、总结

前言

本篇文章对IIC通信协议的原理做了总结,并在硬件IIC配置和软件模拟IIC上做了代码输出,由此来进行一个OLED屏幕的操作总结。

一、项目内容

本项实验的硬件组成有STM32F103C8T6芯片的开发板、OLED模块(0.96寸4针IIC接口OLED显示屏),时间用系统滴答定时器SysTick,主要模块配置是硬件IIC配置和软件模拟IIC配置。

实验简介

根据IIC通讯原理,来进行数据传输,进行一个OLED屏幕的显示,文字,图像。

二、IIC模块 1、IIC协议简介

IIC通讯协议(Inter---Integrted Circuit)是由Phiips飞利浦公司开发的,由于他引脚少,硬件实现简单,可拓展性强,不需要UASRT,CAN通讯协议的外部收发设备,现在被广泛使用在系统内多个集成电路IC(芯片)间的通讯。

IIC模块接收和发送数据,并将数据从串行转换成并行,或并行转换成串行,可以开启或禁止中 断。同步串行也就是半双工的通讯方式,接口通过数据引脚(SDA)和时钟引脚(SCL)连接到IIC总线。允许连接到标准(高达100kHz)或 快速(高达400kHz)的IIC总线。

接口可以下述4种模式中的一种运行:

1、从发送器模式

2、从接收器模式

3、主发送器模式(本文学习)

4、主接收器模式

该模块默认地工作于从模式。接口在生成起始条件后自动地从从模式切换到主模式;当仲裁丢失或产生停止信号时,则从主模式切换到从模式。允许多主机功能。

2、物理层

 图片来源:零死角玩转 STM32F103—霸道>>>第24章  I2C—读写EEPROM>>>常见的 I2C 通讯系统

它的物理层有如下特点:

1、它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线 中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。

2、 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

3、总线通过上拉电阻接到电源,当IIC设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态,由上拉电阻把总线拉成高电平。 4、多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定哪个设备占用总线。 具有三种传输模式:标准模式传输速率为100kbit/s,快速模式为400kbit/s,高速模式下可达3.4M/s,但目前大多1IC设备尚不支持高速模式。

当然,本次要分两个本分来写,硬件IIC和软件IIC。

硬件IIC:对应芯片上的IIC外设,有相对应的IIC驱动电路,其所使用的IIC脚位也是专用的。速度快并可用于DMA。

软件IIC:一般是用GPIO脚位,用软件控制管脚状态以及模拟IIC通信波形,可以在任何脚位上来模拟。

区别:硬件IIC的效率要远高于软件的,而软件IIC不受引脚限制,接口比较灵活。 软件IIC是通过GPIO,软件模拟寄存器的工作方式,而硬件IIC是直接调用内部寄存器进行配 置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件IIC的端口是固定的,所以会有所区别。  

3、协议层

IIC 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。

图片来源:零死角玩转 STM32F103—霸道>>>第24章  I2C—读写EEPROM>>>图 24-4 I2C 通讯复合格式

 IIC通讯概括

1、其中 S 表示由主机的 I2C 接口产生的传输起始信号(S),这时连接到 I2C 总线上的所有从机都会接收到这个信号。 起始信号产生后,所有从机就开始等待主机紧接下来广播的从机地址信号 (SLAVE_ADDRESS)。

2、在 I2C 总线上,每个设备的地址都是唯一的,当主机广播的地址与某个设备地址相同时,根据 I2C协议,这个从机地址可以是 7 位或 10 位。 在地址位之后,是传输方向的选择位,该位为 0即主机向从机写数据。该位为1时,则相反,即主机由从机读数据。在此传输后选择数据寄存器和命令寄存器两种,传输到对应寄存器表示要传输数据/命令。

3、从机接收到匹配的地址后,主机或从机会返回一个应答(ACK)或非应答(NACK)信号, 只有接收到应答信号后,主机才能继续发送或接收数据。重复这个过程,可以向从机传输N个数据, 这个N没有大小限制

4、主要有以下4个部分,①起始信号与停止信号,②应答信号,③数据的有效性,④数据传输。在后面软件模拟IIC中进行一个详细概括。

4、硬件IIC代码配置

STM32f10x的IIC片上外设专门负责实现IIC通讯协议,它们的IIC 通讯信号引出到不同 GPIO引脚上,使用时必须配置到这些指定的引脚自动根据协议的要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器就能完成数据收发。

 图片来源:STM32F1xx中文参考手册 >>> 8.3.9 I2C1 复用功能重映射>>>表48

为此我们一般用的PB6和PB7的引脚。在此之中需要对GPIO的引脚进行配置和IIC功能进行配置。其中配置的内容在代码中有注释。

#include "stm32f10x.h" #include "oled.h" #include "SysTick.h" #include "codetab.h" void I2C_Configuration(void) { I2C_InitTypeDef I2C_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE ); I2C_DeInit( I2C1); I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能应答位 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//指定地址长度,可为7或者10 I2C_InitStructure.I2C_ClockSpeed = 400000;//时钟速度400kHZ,参数值不高于400KHZ I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//时钟占空比,可选low/high(低电平比高电平)= 2:0或16:9 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//模式 I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机地址,可为7或者10位,但只有IIC1能配置10位的 I2C_Init( I2C1, &I2C_InitStructure); //初始化I2C外设配置 I2C_Cmd(I2C1,ENABLE); //使能I2C外设 //PB6---SCL PB7---SDA GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //高阻态运用开漏 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); }

使用 I2C 外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及 SR2)”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。

 

 图片来源:STM32F1xx中文参考手册>>>24 I2C接口>>>24.3.1 模式选择>>>图245 主发送器传送序列图

 主发送器的流程和事件说明在图中有说明,所以IIC写入字节参数函数需要流程如下,都是在IIC.h文件中查找相应的结构体配置。

//I2C写入字节参数 void I2C_WriteByte(uint8_t addr,uint8_t data) { while ( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY)); //检查I2C总线是否繁忙 I2C_GenerateSTART(I2C1, ENABLE ); //开启I2C1 while ( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查状态EV5,主模式 I2C_Send7bitAddress( I2C1, OLED_ADDRESS , I2C_Direction_Transmitter); //发送器件(OLED)地址 while ( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )); I2C_SendData( I2C1, addr); //发送寄存器地址 while ( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); I2C_SendData( I2C1, data ); //发送数据 while ( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); I2C_GenerateSTOP( I2C1, ENABLE ); //关闭I2C总线 }

5、软件模拟IIC配置

软件IIC是通过GPIO管脚,软件模拟寄存器的工作方式,用软件来控制管脚的状态以及模拟IIC通讯的波形,从而达到一个IIC通讯过程。在下面就详细的来编写IIC软件模拟通讯的4个过程,①起始信号与停止信号②应答信号③数据的有效性④数据传输

其中的定时器是系统滴答定时器SysTick,详细可以看STM32的SysTick系统定时器_努力学习的多云的博客-CSDN博客

1、起始信号与停止信号

起始信号:当SCL为高电平期间,SDA有高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。 停止信号:当SCL为高电平期间,SDA由低到高的跳变;停止信号也是一种高电平跳变时序信号,而不是一个电平信号。 起始信号和停止信号一般由主机产生。

数据和地址按8位/字节进行传输,高位在前。跟在起始条件后的1或2个字节是地址(7位模式为1 个字节,10位模式为2个字节)。地址只在主模式发送。

 图片来源:STM32F1xx中文参考手册>>>24 I2C接口>>>24.3 I2C功能描述>>>24.3.1 模式选择

以下为模拟起始信号和停止信号代码,软件模拟工作波形完成

#include "stm32f10x.h" // Device header #include "oled_soft.h" #include "SysTick.h" #include "codetab.h" static void OLED_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //设置为通用开漏输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOB, &GPIO_InitStructure ); //IIC总线的SCL和SDA空闲状态下两条信号线处于高电平 OLED_SCLK_Set(); //设PB0(SCL)为高电平 OLED_SDAT_Set(); //设PB1(SDA)为高电平 } //模拟IIC的起始信号 static void OLED_IIC_Start(void) { OLED_SCLK_Set(); //时钟总线高电平 OLED_SDAT_Set(); //数据总线高电平 us_delay(1); OLED_SDAT_Clr(); us_delay(1); OLED_SCLK_Clr(); us_delay(1); } //模拟IIC的停止信号 static void OLED_IIC_Stop(void) { OLED_SDAT_Clr(); us_delay(1); OLED_SCLK_Set(); //时钟总线高电平 us_delay(1); OLED_SDAT_Set(); //数据总线高电平 us_delay(1); }

为了更加直观方便的编写,我们可以在.h文件中进行宏定义

#ifndef _OLED_SOFT_H_ #define _OLED_SOFT_H_ #include "stm32f10x.h" #define OLED_SCLK_Set() GPIO_SetBits( GPIOB, GPIO_Pin_0) // PB0(SCL)输出高 #define OLED_SCLK_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_0) // PB0(SCL)输出低 #define OLED_SDAT_Set() GPIO_SetBits( GPIOB, GPIO_Pin_1) // PB1(SDA)输出高 #define OLED_SDAT_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_1) // PB1(SDA)输出低 #define OLED_Read_SDAT() GPIO_ReadInputDataBit( GPIOB, GPIO_Pin_1) //读取PB1(SDA)电平 //应答信号为低电平时,为应答位(ACK) //应答信号为高电平时,为非应答位(NACK) #define IIC_ACK 0 //应答 #define IIC_NACK 1 //不应答 #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 #define SIZE 16 //显示字符大小 #define Max_Column 128 //最大列数 #endif 2、从机应答信号

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位)表示接收器已经成功地接收了该字节:应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 在图中红圈可以看到,SCL为低电平后SDA再升为高电平,再SCL变为高电平,由此我们可以进行一个软件模拟IIC波形。

 代码如下:返回一个应答信号

//模拟IIC读取从机应答信号 static unsigned char IIC_Wait_Ack(void) { unsigned char ack; OLED_SCLK_Clr(); //时钟线置低 us_delay(1); OLED_SDAT_Set(); //数据总线高电平 us_delay(1); OLED_SCLK_Set(); //时钟总线高电平 us_delay(1); if ( OLED_Read_SDAT() ) //读取PB1(SDA)电平 { ack = IIC_NACK; //1,不应答 } else { ack = IIC_ACK; //0,应答 } OLED_SCLK_Clr(); //时钟线置低 us_delay(1); return ack; }

 3、数据的有效性

IIC总线进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。SDA数据线在 SCL的每个时钟周期传输一位数据。

即:数据在SCL的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定。

 

4、数据传输

看3、数据的有效性中,数据位的传输是边沿触发的。在IIC总线上数据传输,传送的每一位数据都有一个时钟脉冲相对应,SCL 为高电平时SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“ 1”,为低电平时表示数据“0”。即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。

传输数据的时候,将SCL置低,然后设置SDA总线对应的引脚电平为高/低,SDA电平确定后再讲SCL置高,将8个位由高到低依次发送出去。

//IIC写入一个字节Byte static void Write_IIC_Byte(unsigned char IIC_Byte) { //高位先行原则 unsigned char i; for (i=0;i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有