IIC与四针0.96寸OLED自我总结(STM32F103)

我回来啦!

呃,已经很久没有更新博客了,因为都在自己吃独食(bushi)。即使太懒了,学了快一年了算是入了门吧,最近有好几个人问我“东墙东墙,这屏幕又好看又精巧要怎么用呢?”于是我想要不就写一篇自己对IIC和OLED的认识来给大伙整一篇博客吧!

单片机搭载外设

不要拘于买来的开发板上所带的一些东西比如数码管啊这些,因为以后你要接触更多不一样的器件!所以你应该要学会怎么去使用外设,也就是说你要知道怎么去操纵这个外设的寄存器地址之类的!这是必经之路!

  1. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  2. 全新的 KaTeX数学公式 语法;
  3. 增加了支持甘特图的mermaid语法1 功能;
  4. 增加了 多屏幕编辑 Markdown文章功能;
  5. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  6. 增加了 检查列表 功能。

IIC协议

要按官方话说那就有点乏了,我想这么说不太合适就是复制粘贴呗,那我就按自己的理解来说。(如果要具体可以自行搜索)
把IIC通讯系统看成是“父”,那么连接于它之下的多个IIC通讯设备我称为“子”。而一个父可以有很多很多的子,但子只有一个父。而收发数据呢就像是父子之间互相给钱,两只手串行数据线(SDA)给数据也就是钱,而串行时钟线(SCL)是告诉对方同步收发也就是告诉对方自己什么时间合适拿钱。而每个子呢又有不同的住处(也就是他们的地址),父就要根据不同的门牌号来知道是哪个子。
IIC协议有起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。

读写过程

在这里插入图片描述
在这里插入图片描述
解释下上图的含义:
划线的格子:主机传给从机数据
白格子:从机把数据传给主机
S:传输开始信号(Start!就是主机告诉那些从机们:我要开始传消息啦!)
SLAVE_ADDRESS: 从机地址(主机告诉大家要和谁讲话,所以点名哪个的地址)
R/W- :传输方向选择位,1 为读,0 为写(就是主机要和你讲话还是听你讲话)
A/A- :应答 (ACK) 或非应答 (NACK) 信号(主机听到没有你说的话)
P :停止传输信号(差不多得了😅)

根据字面意思不难理解各个的含义,其实就是人与人说话聊天一样。

通讯时的时序图

通过对SDA与SCL电平高低切换的操作,来实现数据的传输
在这里插入图片描述
当 SCL 线是高电平时,SDA线从高电平向低电平切换,此时就是起始信号。当 SCL 是高电平时 SDA 线由低电平向高电平切换,表示停止信号。
(注:起始和停止信号一般由主机产生。)
代码上就是拉高拉低(给1或者0)

在这里插入图片描述
大家请看,这幅图上当SCL是高电平的时候,SDA所传的数据是有效的是听得见的,当 SCL 为低电平时,SDA 的数据无效,就是听不见!

应答环节!

Acknowledge!就是应答,大家高中学生物的时候是不是也学过(免疫应答之类的)其实都是差不多意思。若想对方继续发数据,需要向对方发送“应答 (ACK)”信号,发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答 (NACK)”信号,发送方接收到该信号后会产生一个停止信号,结束信号传输。在这里插入图片描述

上代码喽

这里就和大家说一下库函数版本吧(但是个人认为大势所趋其实是Hal库)

//起始信号
void I2C_Start(void)
{
	OLED_SDIN_Set();
	OLED_SCLK_Set();
	OLED_SDIN_Clr();
	OLED_SCLK_Clr();
}

//结束信号
void I2C_Stop(void)
{
	OLED_SCLK_Set();
	OLED_SDIN_Clr();
	OLED_SDIN_Set();
}
//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
	OLED_SCLK_Set();
	OLED_SCLK_Clr();
}

//写入一个字节
void Send_Byte(u8 dat)
{
	u8 i;
	for(i=0;i<8;i++)
	{
		OLED_SCLK_Clr();//将时钟信号设置为低电平
		if(dat&0x80)//将dat的8位从最高位依次写入
		{
			OLED_SDIN_Set();
    }
		else
		{
			OLED_SDIN_Clr();
    }
		OLED_SCLK_Set();//将时钟信号设置为高电平
		OLED_SCLK_Clr();//将时钟信号设置为低电平
		dat<<=1;
  }
}

此处的这几个函数
OLED_SDIN_Set();
OLED_SCLK_Set();
OLED_SDIN_Clr();
OLED_SCLK_Clr();
都是在自己做的头文件里定义的,就是配置引脚拉高拉低换成这样更方便程序可读。上面可以和发的时序图一一对应。

操作OLED

根据上面的代码就可以向OLED发送一个字节

//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
	I2C_Start();
	Send_Byte(0x78);
	I2C_WaitAck();
	if(mode){Send_Byte(0x40);}
    else{Send_Byte(0x00);}
	I2C_WaitAck();
	Send_Byte(dat);
	I2C_WaitAck();
	I2C_Stop();
}

与上面的读写过程的图一一对应这样就做到了操作寄存地址并让他做出自己想要的指令。
接下来就调用这个函数就能不断引申下面的各个功能,大家读一下这个 程序就能发现就是一个套一个
比如初始化OLED

//OLED的初始化
void OLED_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE, ENABLE);	 //使能A端口时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;	 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
 	GPIO_Init(GPIOG, &GPIO_InitStructure);	  //初始化GPIOG12
 	GPIO_SetBits(GPIOG,GPIO_Pin_12);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_5|GPIO_Pin_15;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
 	GPIO_Init(GPIOD, &GPIO_InitStructure);	  //初始化GPIOD1,5,15
 	GPIO_SetBits(GPIOD,GPIO_Pin_1|GPIO_Pin_5|GPIO_Pin_15);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_10;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
 	GPIO_Init(GPIOE, &GPIO_InitStructure);	  //初始化GPIOE8,10
 	GPIO_SetBits(GPIOE,GPIO_Pin_8|GPIO_Pin_10);

//	OLED_RST_Clr();//复位
//	delay_ms(200);
//	OLED_RST_Set();
	
	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
	OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WR_Byte(0x12,OLED_CMD);
	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WR_Byte(0x02,OLED_CMD);//
	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
	OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
	OLED_WR_Byte(0xAF,OLED_CMD);
	OLED_Clear();
}

这里的什么0x**可以看作是对这个OLED的命令集,就是让他做出什么动作

//开启OLED显示 
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(0xAF,OLED_CMD);//关闭屏幕
}

//更新显存到OLED	
void OLED_Refresh(void)
{
	u8 i,n;
	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(OLED_GRAM[n][i],OLED_DATA);
  }
}
//清屏函数
void OLED_Clear(void)
{
	u8 i,n;
	for(i=0;i<8;i++)
	{
	   for(n=0;n<128;n++)
			{
			 OLED_GRAM[n][i]=0;//清除所有数据
			}
  }
	OLED_Refresh();//更新显示
}

代码太多不太好全部展示有点是在挤牙膏的嫌疑所以这里放一份OLED的资料和例程大家可以自行参考,但各位想要提升一定要好好看程序不要就是抄,这样才能触类旁通

链接:https://pan.baidu.com/s/1NcO6SgfZ-m4-Mj0xXhBqfw 
提取码:5216 

而且OLED的说明书里有很多有意思的指令,比如让显示滚动啊之类的,这里提一下代码

	WriteCmd(0x2E);         //关闭滚动
    WriteCmd(0x27 );        //水平向左或者右滚动 26/27
    WriteCmd(0x00 );        //虚拟字节
	WriteCmd(0x00 );        //起始页 0
	WriteCmd(0x07 );        //滚动时间间隔
	WriteCmd(0x07 );        //终止页 7
	WriteCmd(0x00 );        //虚拟字节
	WriteCmd(0xFF );        //虚拟字节
	OLED_ShowStr(0, 0, (unsigned char*) "TheBestOne", 2);
	Delay_ms(5);
	WriteCmd(0x2F ); 

看了这么多,我想大家应该也有了解了,就是发送OLED手册上的各个指令来实现不一样的功能,配置不同的模式。

结尾

希望以后能坚持下去写博客,大家也能坚持学习下去
本篇文章肯定有不少疏漏之处,欢迎观者斧正!
在这里插入图片描述


  1. mermaid语法说明 ↩︎

  • 24
    点赞
  • 166
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: 在使用STM32F103C8T6硬件IIC控制4针0.96OLED显示屏时,我们需要了解IIC总线的基本原理和OLED显示屏的接口及控制方式。 IIC总线是一种串行通信协议,它由两根信号线组成,分别是时钟线(SCL)和数据线(SDA)。IIC通信中,数据从一个设备流向另一个设备,通过设备地址进行寻址和选择。而OLED显示屏则是一种可以直接输出图像的静电显示器件,需要通过IIC总线进行控制。 通常,我们会使用STM32F103C8T6的GPIO引脚连接OLED显示屏的时钟线和数据线。在程序中,我们需要设置STM32F103C8T6的GPIO引脚为IIC模式,并且按照IIC协议的流程来进行数据的发送和接收。对于不同的OLED显示屏,其IIC地址可能不一样,我们需要在程序中进行指定。 在显示实际内容时,我们可以通过对OLED显示屏内部的寄存器进行设置来显示所需的图像和文字。需要注意的是,OLED显示屏的控制方式和寄存器的设置可能与其他显示屏不同,我们需要查阅相关的资料才能正确地进行设置。 通过STM32F103C8T6硬件IIC控制4针0.96OLED显示屏,我们可以实现对各种图像和文字内容的显示,是嵌入式开发中常用的一种显示方式。 ### 回答2: 首先,stm32f103c8t6是一款运行速度快、性能稳定的工业级微控制器。该微控制器内置硬件IIC接口,可直接用于控制OLED显示屏。 0.96OLED显示屏通常具有128x64的分辨率,并且有四个引脚:电源、地、SCL和SDA。连接硬件IIC接口和OLED显示屏的时候,需要将SCL引脚连接到stm32f103c8t6的PB6引脚,将SDA引脚连接到stm32f103c8t6的PB7引脚。 对于代码编写,我们可以使用STM32CubeMX和Keil uVision等工具来生成初始化代码,具体步骤如下: 1. 在STM32CubeMX中选择对应的微控制器型号和工程,然后进入"Pinout & Configuration"页面,找到PB6和PB7引脚,将其配置为I2C1_SCL和I2C1_SDA。 2. 进入"Project Manager"页面,在Code Generator一栏中选择"Generate peripheral initialization as a pair of '.c/.h' files per peripheral",然后点击"Generate Code"按钮。 3. 在Keil uVision中创建一个新工程,将CubeMX生成的.c和.h文件添加到工程中。然后在main函数中调用HAL_I2C_Init函数初始化IIC接口,并使用oled_init函数初始化OLED屏。 4. 编写显示函数,例如oled_show_char等,通过IIC接口向OLED屏发送显示数据即可。 需要注意的是,OLED屏显存为8页,每页包含8个字节,因此需要在显示函数中进行相应的位移计算,以保证数据正确展示在OLED屏上。 综上所述,stm32f103c8t6硬件IIC控制0.96OLED显示屏的方式比较简单,只需以下几个步骤:连接SCL和SDA引脚、生成初始化代码、初始化IIC接口和OLED屏、编写显示函数,并处理相关的位移计算。 ### 回答3: STM32F103C8T6是一种强大的微控制器,也是目前广泛应用于嵌入式系统中的芯片之一。它拥有强大的处理器能力和大量的电子模块,并且可以方便地进行编程,具有广泛的应用领域。而硬件IIC控制的4针0.96OLED显示屏则是智能硬件设备中非常重要的一部分,可以用于显示各种数据、文本和图形等。 在将STM32F103C8T6微控制器连接到4针0.96OLED显示屏之前,我们需要了解一些基本知识。其中,硬件IIC (Inter-Integrated Circuit)是一种用于实现芯片之间通信的协议,它可以实现高速和双向传输。硬件IIC总线有两个线路:SDA和SCL,其中SDA是数据线,而SCL是时钟线。因此,在使用IIC控制4针0.96OLED显示屏时,需要将SDA和SCL引脚连接到相应的STM32F103C8T6引脚上。 为了开始使用硬件IIC控制4针0.96OLED显示屏,我们需要在STM32F103C8T6上初始化IIC控制器并打开IIC通讯。在初步准备工作完成后,我们可以开始使用C语言程序将相应的数据传输到OLED显示屏上,以便实现图形和文本输出等功能。OLED显示屏有两种驱动方式:点阵和字符。每种驱动方式都有其自己的优势和劣势。 点阵驱动方式发送的数据可能更加精细和清晰,而字符驱动方式可以输出文本等更具分析性的数据。因此,在使用硬件IIC控制4针0.96OLED显示屏时,需要选择适当的驱动方式来实现所需的功能。 除此之外,硬件IIC控制4针0.96OLED显示屏还涉及到电源管理、数据缓存和错误检测等方面的操作,需要进行适当的设置和调整。只有在正确的设置和调整下才能实现良好的显示效果。 总而言之,硬件IIC控制4针0.96OLED显示屏在STM32F103C8T6上的应用是非常重要的,需要熟悉IIC协议、OLED显示屏驱动和字符集库等相关技术知识,并进行适当的调整和设置才能实现理想的显示效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值