IIC驱动屏幕详解
本文使用模拟IIC来驱动 0.91 寸OLED,因为使用模拟IIC在任何平台上都可以快速的驱动屏幕,点亮一个屏幕的只需要 导入3个.c 和对应 .h 文件(共6个文件),需要提供delay 函数 和 翻转IO接口即可点亮屏幕!!十分的方便!!
驱动OLED屏幕本质上其实还是点灯,只不过是整齐排列在基板上的灯!但是我们的MCU不可能提供那么多IO去控制每一颗屏幕上的灯,所以需要有个芯片帮忙,这个屏幕驱动IC会按照代码取控制每一颗LED,显示出代码传输过去的图案信息!
所以驱动代码是发送给屏幕驱动IC的,我们想要显示的字、图案都需要取模软件转化为像素信息,并且按照代码初始化时我们告诉驱动IC的规则(从左到右、从上到小的规则或者其他)发送后,驱动IC就会按照数据,去控制OLED屏幕!!
简介:
此驱动时模拟IIC驱动,只需要延时 和 翻转IO即可,并且只要替换几个API和宏即可完成驱动实现快速的驱动屏幕,这可以作为快速验证硬件+软件的环境,再刷屏内容多且复杂时可以将驱动部分替换为硬件IIC即可。
移植准备
文件介绍
相关文件有以下三个
analog_iic.c analog_iic.h 模拟IIC相关代码
oled.c oled.h OLED初始化接口 和 基本操作函数
gui.c gui.h 画点、画线、显示文字的接口
API准备
1、毫秒级的延时函数,不用太准确差不都即可,我使用的时工程内已有的API Delay_Ms接口。
2、IO的翻转(拉高或拉低)GPIO_WriteBit接口
IIC引脚定义
#define OLED_SDA GPIO_Pin_1
#define OLED_SCL GPIO_Pin_3
#defineOLED_SDA_SET() GPIO_WriteBit(GPIOA, OLED_SDA, 1)
#defineOLED_SDA_CLR() GPIO_WriteBit(GPIOA, OLED_SDA, 0)
#defineOLED_SCL_SET() GPIO_WriteBit(GPIOA, OLED_SCL, 1)
#defineOLED_SCL_CLR() GPIO_WriteBit(GPIOA, OLED_SCL, 0)
初始化IIC引脚
voidiic_io_init(void){
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
analog_iic.c
由于是屏幕是主控给它发送数据,驱动IC只管接收数据即可,主控不需要去读取数据,所以我们主要关注IIC_Write函数即可。
我们需要留意的有三点
1、IIC_SLAVE_ADDR 从机地址
2、需要确认写命令 和 数据
3、确认模拟IIC的引脚
以上1、2两点可以从规格书中得知。
IIC_SLAVE_ADDR 0x78
写命令需要在发送从机地址后,发送0x00,而数据是0x40,所以IIC写命令可以进一步封装为以下代码。
void Write_IIC_Command( u8 IIC_Command ){
IIC_Start();
Write_IIC_Byte( IIC_SLAVE_ADDR ); //Slave address,SA0=0
IIC_Wait_Ack();
Write_IIC_Byte( 0x00 ); //write command
IIC_Wait_Ack();
Write_IIC_Byte( IIC_Command );
IIC_Wait_Ack();
IIC_Stop();
}
void Write_IIC_Data( u8 IIC_Data ){
IIC_Start();
Write_IIC_Byte( IIC_SLAVE_ADDR ); //D/C#=0; R/W#=0
IIC_Wait_Ack();
Write_IIC_Byte( 0x40 ); //write data
IIC_Wait_Ack();
Write_IIC_Byte( IIC_Data );
IIC_Wait_Ack();
IIC_Stop();
}
屏幕初始化
以上发送的初始化参数都是需要屏厂、商家提供的,只是这一款屏幕用的人太多太多了,可以在网上找,如果不对是不能正确初始化屏幕的,后面的显示更不用说了,肯定有问题!
// OLED_Display_Off(); //power off
OLED_WR_Byte( 0xAE, OLED_CMD ); //--display off
OLED_WR_Byte( 0x40, OLED_CMD ); //---set low column address
OLED_WR_Byte( 0xB0, OLED_CMD ); //---set high column address
OLED_WR_Byte( 0xC8, OLED_CMD ); //-not offset
OLED_WR_Byte( 0x81, OLED_CMD ); // contract control
OLED_WR_Byte( 0xFF, OLED_CMD ); //--128
OLED_WR_Byte( 0xA1, OLED_CMD ); //set segment remap
OLED_WR_Byte( 0xA6, OLED_CMD ); //--normal / reverse
OLED_WR_Byte( 0xA8, OLED_CMD ); //--set multiplex ratio(1 to 64)
OLED_WR_Byte( 0x1F, OLED_CMD );
OLED_WR_Byte( 0xD3, OLED_CMD ); //-set display offset
OLED_WR_Byte( 0x00, OLED_CMD );
OLED_WR_Byte( 0xD5, OLED_CMD ); //set osc division
OLED_WR_Byte( 0xF0, OLED_CMD );
OLED_WR_Byte( 0xD9, OLED_CMD ); //Set Pre-Charge Period
OLED_WR_Byte( 0x22, OLED_CMD );
OLED_WR_Byte( 0xDA, OLED_CMD ); //set com pin configuartion
OLED_WR_Byte( 0x02, OLED_CMD );
OLED_WR_Byte( 0xDB, OLED_CMD ); //set Vcomh
OLED_WR_Byte( 0x49, OLED_CMD );
OLED_WR_Byte( 0x8D, OLED_CMD ); //set charge pump enable
OLED_WR_Byte( 0x14, OLED_CMD );
OLED_WR_Byte( 0xAF, OLED_CMD ); //--turn on oled panel
那么如何判断屏幕有没有初始换成功呢?
正确使用IIC发送,正确的初始化参数、并且不发送清屏,OLED屏幕就会这样显示!!
实际代码实验
注意1:
添加文件的方法,不然会编译报错。
注意2
While里不能放显示数据的函数,里面用了Dealy,会导致PD出现不断复位的情况
本文附件为此实验的代码,默认选择PDO报文的第四档,并且显示2023年9月19号 15点30分的实际 和 PDO报文第四档的电压和电流(取决于使用的充电器)。
USBPD_SNK+OLED.zip
(633.14 KB)
|