你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

快速驱动0.91 寸OLED

[复制链接]
dvacos 发布时间:2023-9-1 18:04

本文使用模拟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 ); //清屏
}

以上发送的初始化参数都是需要屏厂、商家提供的,只是这一款屏幕用的人太多太多了,可以在网上找,如果不对是不能正确初始化屏幕的,后面的显示更不用说了,肯定有问题!

那么如何判断屏幕有没有初始换成功呢? 456bf1a6d396191bb218fa736ae1049.jpg 正确使用IIC发送,正确的初始化参数、并且不发送清屏,OLED屏幕就会这样显示!!

经过以上几步后,只要编译没有报错后,就可以烧录,接线测试了

移植后&实验

如果接线没问题的情况请仔细检查数据是否和填写的代码一致!!

问题

我列一下我在实验时遇到的一个十分难搞的问题

问题:在我将IO配置为 推挽、上拉输出后,我接逻辑分析仪,确认数据全部发送正确,但是接到屏幕后发现数据时错乱的!

解决方法: 将屏幕的SDA SCL都接上10K的上拉,必须确保在连接屏幕后,逻辑分析仪抓获的数据也要和代码里填写的一致!!

相关代码 ↓

IIC_Code.zip

1 收藏 评论9 发布时间:2023-9-1 18:04

举报

9个回答
dvacos 回答时间:2023-9-1 18:11:55

研究了一下,不知道怎么上传压缩包附件,发个百度云分享,压缩后14k,限不限速都一样,

链接:https://pan.baidu.com/s/1lSzNwBCNLoV74Y8I0GgoIA?pwd=yxl4 提取码:yxl4

无极考拉 回答时间:2023-9-4 09:00:42

学习一下

STMCU-管管 回答时间:2023-9-5 11:56:07
dvacos 发表于 2023-9-1 18:112 b. j3 q( @- x& l
[md]研究了一下,不知道怎么上传压缩包附件,发个百度云分享,压缩后14k,限不限速都一样,0 ?' O" j- c) I! G& i7 m
; Q1 y: j, K) \$ h3 N
链接:https:/ ...

9 I8 O  \# _/ T有一个长得像回形针的图标就是传附件的哈
$ J) z7 A6 w! h  P6 p, G, a/ E. F1 L
电子烂人 回答时间:2023-9-6 09:24:26

学到了

向明月 回答时间:2023-9-7 14:40:56

点赞

meiyao 回答时间:2023-9-7 21:27:35

厉害,使用GUI能这样玩,画点画线

高迪的教堂 回答时间:2023-9-12 09:45:47
学习一下
onebyte 回答时间:2023-9-15 08:42:36

正要用0.91寸的屏,这次省事了

dvacos 回答时间:2023-9-15 13:00:50

编译应该会报错

在analog_iic.h 找到 IIC_SLAVE_ADDR ,赋值为0x78 即可,如下

define IIC_SLAVE_ADDR 0x78

文件的中文注释使用GB2312编码

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版