本文使用模拟IIC来驱动 0.91 寸OLED,因为使用模拟IIC在任何平台上都可以快速的驱动屏幕,点亮一个屏幕的只需要 导入3个.c 和对应 .h 文件(共6个文件),需要提供delay 函数 和 翻转IO接口即可点亮屏幕!!十分的方便!!
驱动OLED屏幕本质上其实还是点灯,只不过是整齐排列在基板上的灯!但是我们的MCU不可能提供那么多IO去控制每一颗屏幕上的灯,所以需要有个芯片帮忙,这个屏幕驱动IC会按照代码取控制每一颗LED,显示出代码传输过去的图案信息!
所以驱动代码是发送给屏幕驱动IC的,我们想要显示的字、图案都需要取模软件转化为像素信息,并且按照代码初始化时我们告诉驱动IC的规则(从左到右、从上到小的规则或者其他)发送后,驱动IC就会按照数据,去控制OLED屏幕!!
这是之前测评WB55时驱动的OLED屏幕方法的总结!再次谢谢ST论坛给的开发板!
移植准备
文件介绍
相关文件有以下三个
analog_iic.c analog_iic.h 模拟IIC相关代码
oled.c oled.h OLED初始化接口 和 基本操作函数
gui.c gui.h 画点、画线、显示文字的接口
API准备
1、毫秒级的延时函数,不用太准确差不都即可,我使用的时HAL_Delay接口
2、IO的翻转(拉高或拉低)
移植中&代码简介
main.c
以下初始化屏幕 并 显示时间的代码,如果需要显示时间,只要保留OLED_Init即可,在while填写想要显示数值 和 文字即可(先要显示的文字和数字都要先取模)
time_t now;
struct tm *ts;
static char str_time[80];
uint32_t timestamp=0;
int main(void){
....
MX_GPIO_Init();
....
MX_APPE_Init();
OLED_Init();
now=1688628481;
ts = localtime( &now );
sprintf(str_time,"%04d-%02d-%02d %02d:%02d:%02d",
ts->tm_year+1900,
ts->tm_mon+1,
ts->tm_mday,
ts->tm_hour+8, //时区要加8
ts->tm_min,
ts->tm_sec );
while (1)
{
MX_APPE_Process();
GUI_ShowString(0,0,(u8*)str_time,8,1);
...
}
}
初始化GPIO
void MX_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2|GPIO_PIN_11, GPIO_PIN_SET);
/*Configure GPIO pins : PB2 PB11 */
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
analog_iic.c
由于是屏幕是主控给它发送数据,驱动IC只管接收数据即可,主控不需要去读取数据,所以我们主要关注IIC_Write函数即可。
我们需要留意的有三点
1、IIC_SLAVE_ADDR 从机地址
2、需要确认写命令 和 数据
3、确认模拟IIC的引脚
以上1、2两点可以从规格书中得知。
IIC_SLAVE_ADDR 0x78
写命令需要在发送从机地址后,发送0x00,而数据是0x40。
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();
}
模拟IIC引脚定义
//--------------IIC总线引脚定义-----------------------
#define OLED_SDA GPIO_PIN_2 //OLED屏IIC数据信号
#define OLED_SCL GPIO_PIN_11 //OLED屏IIC时钟信号
//--------------IIC端口操作定义---------------------
#define OLED_SDA_SET() HAL_GPIO_WritePin(GPIOB, OLED_SDA, GPIO_PIN_SET)
#define OLED_SDA_CLR() HAL_GPIO_WritePin(GPIOB, OLED_SDA, GPIO_PIN_RESET)
#define OLED_SCL_SET() HAL_GPIO_WritePin(GPIOB, OLED_SCL, GPIO_PIN_SET)
#define OLED_SCL_CLR() HAL_GPIO_WritePin(GPIOB, OLED_SCL, GPIO_PIN_RESET)
oled.c
其中最重要的代码就是OLED_Init
void OLED_Init( void ){
HAL_Delay( 200 );
/**************初始化SSD1306*****************/
// 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
// OLED_Display_On(); // power on
OLED_Clear( 0 ); //清屏
}
以上发送的初始化参数都是需要屏厂、商家提供的,只是这一款屏幕用的人太多太多了,可以在网上找,如果不对是不能正确初始化屏幕的,后面的显示更不用说了,肯定有问题!
那么如何判断屏幕有没有初始换成功呢?
正确使用IIC发送,正确的初始化参数、并且不发送清屏,OLED屏幕就会这样显示!!
经过以上几步后,只要编译没有报错后,就可以烧录,接线测试了
移植后&实验
如果接线没问题的情况请仔细检查数据是否和填写的代码一致!!
问题
我列一下我在实验时遇到的一个十分难搞的问题
问题:在我将IO配置为 推挽、上拉输出后,我接逻辑分析仪,确认数据全部发送正确,但是接到屏幕后发现数据时错乱的!
解决方法:
将屏幕的SDA SCL都接上10K的上拉,必须确保在连接屏幕后,逻辑分析仪抓获的数据也要和代码里填写的一致!!
相关代码 ↓
研究了一下,不知道怎么上传压缩包附件,发个百度云分享,压缩后14k,限不限速都一样,
链接:https://pan.baidu.com/s/1lSzNwBCNLoV74Y8I0GgoIA?pwd=yxl4 提取码:yxl4
学习一下
有一个长得像回形针的图标就是传附件的哈
学到了
点赞
厉害,使用GUI能这样玩,画点画线
正要用0.91寸的屏,这次省事了
编译应该会报错
在analog_iic.h 找到 IIC_SLAVE_ADDR ,赋值为0x78 即可,如下
define IIC_SLAVE_ADDR 0x78
文件的中文注释使用GB2312编码