STM32F4+0.96OLED+IIC代码讲解

一、 简介:

  • 尺寸:0.96寸
  • 控制芯片:SSD1306
  • 管脚数量:4
  • 引脚间距:2.54mm
  • 分辨率:128*64,可以显示汉字、ASCII、图案,对比度高
  • 可视角度:>160度
  • 无需背光(OLED屏的特点)
  • 供电:3V-5V

二、IIC底层

1.IIC电路连接:
        GND---地
        VCC---3.3V或5V
        SCL---接单片机IO,作为IIC的SCL引脚
        SDA---接单片机IO,作为IIC的SDA引脚

2.将模块连接好后编写(拷贝)IIC底层协议

根据自己定义的SCL和SDA在iic.h中修改宏

/*iic.h*/
#include "main.h"
#include "delay.h"

/*----------------------PIN DEFINE----------------------------*/
#define SCL 	GPIOC     
#define SCL_PIN	GPIO_PIN_0

#define SDA 	GPIOC
#define SDA_PIN	GPIO_PIN_1

#define	SCL_Clock_Enable	__HAL_RCC_GPIOC_CLK_ENABLE
#define	SDA_Clock_Enable	__HAL_RCC_GPIOC_CLK_ENABLE

/*------------------------FUNCTION DEFINE--------------------------*/
#define SCL_W(X)	do{X ? HAL_GPIO_WritePin(SCL,SCL_PIN,GPIO_PIN_SET):\
						HAL_GPIO_WritePin(SCL,SCL_PIN,GPIO_PIN_RESET);}while(0)

#define SDA_W(X)	do{X ? HAL_GPIO_WritePin(SDA,SDA_PIN,GPIO_PIN_SET):\
						HAL_GPIO_WritePin(SDA,SDA_PIN,GPIO_PIN_RESET);}while(0)
#define SDA_R()		HAL_GPIO_ReadPin(SDA,SDA_PIN)
				
#define delay()	delay_us(5)  //延时函数宏替换
#define Device_address 0x78

/*SDA,SCL引脚初始化*/
void IIC_Init(void);
void IIC_Start(void);
void IIC_SendByte(uint8_t byt);
uint8_t IIC_ReadByte(void);
uint8_t IIC_ReadACK(void);
void IIC_SendACK(uint8_t ack);
void IIC_Stop(void);
/*iic.c*/
#include "iic.h"

/*SDA,SCL引脚初始化*/
void IIC_Init(void)
{
	GPIO_InitTypeDef gpio_init = {0};
	SCL_Clock_Enable();
	SDA_Clock_Enable();
	gpio_init.Pin = SCL_PIN;
	gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
	gpio_init.Pull = GPIO_NOPULL;
	gpio_init.Speed = GPIO_SPEED_HIGH;
	HAL_GPIO_Init(SCL,&gpio_init);
	
	gpio_init.Pin = SDA_PIN;
	gpio_init.Pull = GPIO_PULLUP;
	HAL_GPIO_Init(SDA,&gpio_init);
	
	HAL_GPIO_WritePin(SCL,SCL_PIN,GPIO_PIN_SET);
	HAL_GPIO_WritePin(SDA,SDA_PIN,GPIO_PIN_SET);
}
/*配置SDA引脚模式*/
void IIC_SDAMode_Set(uint32_t Mode)
{
	GPIO_InitTypeDef gpio_init = {0};
	gpio_init.Pin = SDA_PIN;
	gpio_init.Mode = Mode;
	if(Mode == GPIO_MODE_INPUT)
		gpio_init.Pull = GPIO_PULLUP;
	else
		gpio_init.Pull = GPIO_NOPULL;
	gpio_init.Speed = GPIO_SPEED_HIGH;
	
	HAL_GPIO_Init(SDA,&gpio_init);
	
}

void IIC_Start(void)
{
	IIC_SDAMode_Set(GPIO_MODE_OUTPUT_PP);
	SDA_W(1);
	SCL_W(1);
	delay();
	
	SDA_W(0);
	delay();
	SCL_W(0);	//将时钟线拉低,告诉挂载在总线的其他设备总线在忙
	delay();
}

void IIC_SendByte(uint8_t byt)
{
	IIC_SDAMode_Set(GPIO_MODE_OUTPUT_PP);
	SCL_W(0);
	int i;
	for(i = 7;i >= 0;i--)
	{
		if(byt & (1<<i))
			SDA_W(1);
		else
			SDA_W(0);
		delay();
		SCL_W(1);
		delay();
		SCL_W(0);
		delay();
	}
}
uint8_t IIC_ReadByte(void)
{
	int i;
	uint8_t byte = 0;
	IIC_SDAMode_Set(GPIO_MODE_INPUT);
	for(i = 0;i < 8;i++)
	{
		SCL_W(1);
		delay();
		if(SDA_R())
			byte |= 1<<(7-i);
		delay();
		SCL_W(0);
		delay();
	}
	return byte;
}

uint8_t IIC_ReadACK(void)
{
	uint8_t ack = 0;
	IIC_SDAMode_Set(GPIO_MODE_INPUT);
	SCL_W(1);
	delay();
	ack = SDA_R();
	SCL_W(0);	
	return ack;
}

void IIC_SendACK(uint8_t ack)
{
	IIC_SDAMode_Set(GPIO_MODE_OUTPUT_PP);
	SCL_W(0);
	SDA_W(ack);
	delay();
	SCL_W(1);
	delay();
	SCL_W(0);
}

void IIC_Stop(void)
{
	IIC_SDAMode_Set(GPIO_MODE_OUTPUT_PP);
	SDA_W(0);
	delay();
	SCL_W(1);
	delay();
	SDA_W(1);
	
}

 三、SSD1306芯片

1.简介

SSD1306是一款带控制器的用于OLED点阵图形显示系统的单片CMOS OLED/PLED驱动器。它由128个SEG(列输出)和64个COM(行输出)组成。该芯片专为共阴极OLED面板设计。
  SSD1306内置对比度控制器、显示RAM(GDDRAM)和振荡器,以此减少了外部元件的数量和功耗。该芯片有256级亮度控制。数据或命令由通用微控制器通过硬件选择的6800/8000系通用并行接口、I2C接口或串行外围接口发送。该芯片适用于许多小型便携式应用,如手机副显示屏、MP3播放器和计算器等。

2.了解SSD1306基本指令指令(具体参考文档)

 四、0.96OLED代码

1、编写向OLED发送数据和发送命令函数

        #define OLED_ADDRESS 0X78   //器件地址
        #define OLED_CMD     0X00        //命令地址
        #define OLED_DAT     0X40        //数据地址


/*向OLED发送写指令命令*/
void OLED_Write_Cmd(uint8_t cmd)
{
	IIC_Start();
	IIC_SendByte(OLED_ADDRESS);
	IIC_ReadACK();
	IIC_SendByte(OLED_CMD);
	IIC_ReadACK();
	IIC_SendByte(cmd);
	IIC_ReadACK();
	IIC_Stop();
}
/*向OLED发送写数据命令*/
void OLED_Write_DAT(uint8_t dat)
{
	IIC_Start();
	IIC_SendByte(OLED_ADDRESS);
	IIC_ReadACK();
	IIC_SendByte(OLED_DAT);
	IIC_ReadACK();
	IIC_SendByte(dat);
	IIC_ReadACK();
	IIC_Stop();
}

2.首先初始化OLED

/*初始化设置*/
void OLED_Init(void)
{
	delay_ms(200);
	
	OLED_Write_Cmd(0XA8);  //设置分辨率
	OLED_Write_Cmd(0X3F);  //0X3F: 128 * 64  0X1F: 128 * 32 
	
	OLED_Write_Cmd(0XAE); //关闭显示
	
	OLED_Write_Cmd(0XD3); //设置偏移
	OLED_Write_Cmd(0X00);
	
	OLED_Write_Cmd(0X40); //设置显示开始
	
	OLED_Write_Cmd(0XA1); // 设置段重映射
	
	OLED_Write_Cmd(0Xc8); //设置扫描方向 左->右
	
	OLED_Write_Cmd(0XDA); //设置“COM引脚硬件配置
	OLED_Write_Cmd(0X12); //128*64   0X02:128*32
	
	OLED_Write_Cmd(0X81); //设置对比度
	OLED_Write_Cmd(0XFF);
	
	OLED_Write_Cmd(0XD9); //设置预充电时间
	OLED_Write_Cmd(0XF1);
	
	OLED_Write_Cmd(0XDB); //设置取消选择级别
	OLED_Write_Cmd(0X20);
	
	OLED_Write_Cmd(0XA4); //设置整个打开
	
	OLED_Write_Cmd(0XA6); //设置反转和正常显示
	
	OLED_Write_Cmd(0X8D); //电泵设置
	OLED_Write_Cmd(0X14); //开启电荷泵
	
	OLED_Write_Cmd(0XAF); //打开显示
	
	OLED_Clear();
}

3.编写显示字符函数

/*向OLED中写入的字的起始位置
  x:显示的横坐标(页)
  y:显示字符的纵坐标(列)
*/
void OLED_SetPos(uint8_t x,uint8_t y)
{
	OLED_Write_Cmd(0xb0+y);           //写入页地址
	OLED_Write_Cmd(0x10+(x>>4&0x0f)); //写入列地址高位
	OLED_Write_Cmd((x & 0x0f)|0x01);  //写入列地址低位
	
}

/*写入16*16字符或者汉字
  x:显示的横坐标(页)
  y:显示字符的纵坐标(列)
  ch:取模后的汉字和字符数组
  n:  显示ch数组中的第几个字符(从0开始)
*/
void OLED_Show_char(uint8_t x,uint8_t y,uint8_t *ch,uint8_t n)
{
	uint8_t num;
	uint16_t address = n*32;   //定位字符的首地址在数组的位置
	OLED_SetPos(x,y);		   //发送要写入的页地址和列地址起始位置 8行为一页,
	for(num = 0; num < 16; num++) //写第一页
	{
		OLED_Write_DAT(ch[address++]); //向OLED发送数据
	}
	OLED_SetPos(x,y+1);          //页地址+1
	for(num = 0; num < 16; num++)//写第二页
	{
		OLED_Write_DAT(ch[address++]);
	}
}
/*写入8*8字符或者汉字
  x:显示的横坐标(页)
  y:显示字符的纵坐标(列)
  ch:取模后的汉字和字符数组
  n:  显示ch数组中的第几个字符(从0开始)
*/
void OLED_Show_char8x8(uint8_t x,uint8_t y,uint8_t *ch,uint8_t n)
{
	uint8_t num;
	uint16_t address = n*8;
	OLED_SetPos(x,y);
	for(num = 0; num < 8; num++)
	{
		OLED_Write_DAT(ch[address++]);
	}
	
}
/*
	显示图片128*64
	bmp:保存图片的模
*/
void OLED_Show_Bmp(uint8_t *bmp)
{
	uint16_t address = 0;
	for(uint8_t i = 0; i < 8;i++)
	{
		OLED_SetPos(0,i);
		for(uint8_t j = 0; j < 128;j++)
			OLED_Write_DAT(bmp[address++]);
	}
}

4.其他函数

/*清除屏幕内容*/
void OLED_Clear(void)
{
	uint8_t i,n;
	for(i = 0;i < 8;i++) //128 * 64  一个单元16*8 一行8个字,循环清空8行
	{
		OLED_Write_Cmd(0xb0|i);  //配置0~7页的那一页
		OLED_Write_Cmd(0x00); 	 //设置操作的低位(列)
		OLED_Write_Cmd(0x10);    //设置操作的高位(列)
		for(n = 0;n < 128;n++)
		OLED_Write_DAT(0x00); //0xff:白屏,0x00:黑屏
	}
}
/*oled开启显示*/
void OLED_Display_ON(void)
{
	OLED_Write_Cmd(0X8D); //开启电荷泵
	OLED_Write_Cmd(0x14);
	
	OLED_Write_Cmd(0XAF); //打开显示
}
/*oled关闭显示*/
void OLED_Display_OFF(void)
{
	OLED_Write_Cmd(0X8D); //开启电荷泵
	OLED_Write_Cmd(0x14);
	
	OLED_Write_Cmd(0XAE); //关闭显示
}

oled.h

#ifndef _OLED_H_
#define _OLED_H_

#include "main.h"
#include "iic.h"

#define OLED_ADDRESS 0X78
#define OLED_CMD	 0X00
#define OLED_DAT	 0X40

void OLED_Init(void);
void OLED_Display_OFF(void);
void OLED_Display_ON(void);
void OLED_Clear(void);
void OLED_Show_Char(uint8_t x,uint8_t y,uint8_t g,uint8_t k,uint8_t *dat);
void OLED_Show_char(uint8_t x,uint8_t y,uint8_t *ch,uint8_t n);
void OLED_Show_Num(uint8_t x,uint8_t y,uint8_t num);
void OLED_Show_char8x8(uint8_t x,uint8_t y,uint8_t *ch,uint8_t n);
void OLED_Show_Bmp(uint8_t *bmp);
#endif

五、字符取模

oled

六、图片取模

OLED_图片_BMP格式_再取模图片

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
引用\[1\]中提到了驱动里面SPI通信采用电平模拟方式,这样写驱动移植起来比较方便,但是速率、可靠性稍差一点。而引用\[2\]中提到了OLED驱动方式有8080、6800、3线/4线SPI以及IIC,本次实验使用的是IIC通信协议。所以,对于stm32f103和0.96oled的连接,可以选择使用IIC通信协议进行驱动。在移植时,需要将官方GUI下的画点API函数和读点API函数用自己写的驱动函数进行填充,以实现在0.96寸OLED单色屏上画点。移植的难度相对较低,但如果需要进行刷屏、画多边形等操作,可能需要进行优化以提高速率。移植可以在keil5环境下进行,不需要系统的环境移植。最终的显示效果受限于屏幕的尺寸和颜色能力。 #### 引用[.reference_title] - *1* *3* [基于STM32F103移植STemWin5.32到0.96寸OLED](https://blog.csdn.net/z961968549/article/details/105243723)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [基于STM32F103 0.96寸OLED液晶屏驱动(iic通讯)](https://blog.csdn.net/weixin_45419341/article/details/114191044)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值