机智云STM32平台移植oled显示屏

机智云gokitSTM32平台移植oled显示屏

首先非常感谢机智云官方提供的免费开发板,需要的同学可以上机智云的官方网站申请。


oled简介

OLED,即有机发光二极管( Organic Light Emitting Diode)。 OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。LCD 都需要背光,而 OLED 不需要,因为它是自发光的。这样同样的显示 OLED 效果要来得好一些。以目前的技术,OLED 的尺寸还难以大型化,但是分辨率确可以做到很高。在此我们使用的是的 0.96 寸 OLED 显示屏,该屏有以下特点:
1)0.96 寸 OLED 有黄蓝,白,蓝三种颜色可选;其中黄蓝是屏上 1/4 部分为黄光,下 3/4 为蓝;而且是固定区域显示固定颜色,颜色和显示区域均不能修改;白光则为纯白,也就是黑底白字;蓝色则为纯蓝,也就是黑底蓝字。
2)分辨率为 128*64
3)多种接口方式;OLED 裸屏总共接口包括:6800、8080 两种并行接口方式、3 线或 4 线的串行 SPI 接口方式、 IIC 接口方式(只需要 2 根线就可以控制 OLED 了!),这五种接口是通过屏上的 BS0~BS2 来配置的。
本次试验中我们使用模拟SPI的方式来驱动。

硬件确认

硬件规格:gokit STM32底板 版本号:V2.3;WiFi扩展板版本号:V2.3

扩展板的oled接口如下:
这里写图片描述

STM32对应的底板接口如下:
这里写图片描述

查看硬件后发现R8、R9、R11、R13的0R电阻是焊接的,所以得到屏体的对应关系如下:
1. Din<–>D11<–>PA7
2. CLK<–>D13<–>PA5
3. CS<–>D10<–>PA15
4. D/C<–>D9<–>PB11
5. RES<–>D8<–>PB6

大多数SPI接口的屏模块接口定义如下:
1. GND 电源地
2. VCC 电源正(3~5.5V)
3. D0 OLED 的 D0 脚,在 SPI 和 IIC 通信中为时钟管脚
4. D1 OLED 的 D1 脚,在 SPI 和 IIC 通信中为数据管脚
5. RES OLED 的 RES#脚,用来复位(低电平复位)
6. DC OLED 的 D/C#E 脚,数据和命令控制管脚
7. CS OLED 的 CS#脚,也就是片选管脚 当只使用一个屏的时候,我们可以直接将CS引脚接低电平,让其一直保持选中状态。

确认了硬件连接后,我们就可以移植代码了。

代码移植

基于STM32的0.96吋oled屏的代码网上一搜一大堆,随便撸过来一个就着手开始移植。
其实移植的过程很简单,就是将对应的接口配置好就OK啦。
我的移植思路是先将单独的oled显示屏的代码跑起来,如果显示正常,则证明以下两点:a)硬件连接没有问题;b).oled屏驱动没有问题。确认好这两点后,再将此代码整合到gokkit提供的代码中,实现自己想要的功能,那就大工搞成了。
移植过程如下:
本次使用的是软件模拟SPI来驱动oled屏,所以GPIO没有要求,随便哪个都可以,但是要配置为推完输出,按照硬件连接,接口定义如下:

//-----------------OLED端口定义----------------                        

#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)//CLK
#define OLED_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)

#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//DIN
#define OLED_SDIN_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)

#define OLED_RST_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)//RES
#define OLED_RST_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6)

#define OLED_DC_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_11)//DC
#define OLED_DC_Set() GPIO_SetBits(GPIOB,GPIO_Pin_11)

#define OLED_CS_Clr()  GPIO_ResetBits(GPIOA,GPIO_Pin_15)//CS
#define OLED_CS_Set()  GPIO_SetBits(GPIOA,GPIO_Pin_15)

说到这里,再补充一句,其实本代码移植到51、MSP430单片机上的道理都是一样的,我们的思想就是:OLED_SCLK_Clr() 这个函数的功能就是将CLK引脚置为低电平0;OLED_SDIN_Set()这个函数的功能就是将CLk引脚置为高电平1;那么在51单片机中我们可以定义如下:

sbit OLED_CLK   =   P1^3;
#define OLED_SCLK_Clr() OLED_CLK = 0 //CLK 注意:不需要";"
#define OLED_SCLK_Set() OLED_CLK = 1 

在MSP430单片机中可以定义如下:

P1DIR |= BIT3;   //将P1.3设置为输出
#define OLED_SCLK_Clr() P1OUT &= ~(BIT3)//CLK
#define OLED_SCLK_Set() P1OUT |= BIT3

其他单片机的移植也大同小异,注意一点的是。在初始化代码中一定要加入IO口的初始化,STM32的IO初始化函数代码如下:

void OLED_Init(void)
{       
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //使能A端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 |GPIO_Pin_15  ; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);    //初始化GPIOD3,6
    GPIO_SetBits(GPIOA,GPIO_Pin_5 | GPIO_Pin_7 |GPIO_Pin_15);   

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    //使能A端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_6|GPIO_Pin_1;     
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure);    //初始化GPIOD3,6
    GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_6|GPIO_Pin_1);  
}

好的,其他地方基本上就不需要动了,直接在main函数中做相应的初始化后打印一串字符串看看。

 int main(void)
 {  
      u8 t;
        delay_init();            //延时函数初始化    
        NVIC_Configuration();    //设置NVIC中断分组2:2位抢占优先级,2位响应优先级  LED_Init();              //LED端口初始化
        OLED_Init();            //初始化OLED  
        OLED_Clear()    ; 
        LED_OFF;
        delay_ms(1000);

        OLED_ShowString(30,0,"OLED TEST");
        OLED_ShowString(8,2,"ZHONGJINGYUAN");  
        OLED_ShowString(20,4,"2017/06/15");  
        OLED_ShowString(0,6,"ASCII:");  
        OLED_ShowString(63,6,"CODE:"); 
        while(1);  //让程序停在这里
} 

将代码下载进去后,上电。见证奇迹的时候到了,卧槽!屏幕一片黑暗,怎么回事?不知道啊,硬着头皮将硬件电路检查了一遍,看看接线有没有错,检查了两遍没问题啊,是不是杜邦线有接触不良的?于是我又找了一块STM32的开发板,试试能不能用,线接好后将代码下载进去,还是不能用。我就开始怀疑是不是买了一块坏的屏,不应该啊。是不是时序太快了屏反应不过来?于是乎我在写数据和命令的函数中增加了一个延时函数,代码如下:

//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{   
    u8 i;             
    if(cmd)
      OLED_DC_Set();
    else 
      OLED_DC_Clr();          
    OLED_CS_Clr();
    for(i=0;i<8;i++)
    {             
        OLED_SCLK_Clr();
        if(dat&0x80)
           OLED_SDIN_Set();
        else 
           OLED_SDIN_Clr();
        delay_us(100); //稍作延时
        OLED_SCLK_Set();
        dat<<=1;   
    }                         
    OLED_CS_Set();
    OLED_DC_Set();        
} 

重新下载,屏还是黑的,没有任何反应,重新调整延时时间,没有任何作用,看来应该不是时序的问题。是不是他的代码有问题,导致我移植出了问题,毕竟现在网上的资源太杂太乱,于是乎我就在网上又找了一个oled屏的代码,重新配置了GPIO后下载验证,还是一样,屏无任何反应,不应该啊,怎么回事?正确的解决方法是挂示波器看各个IO口的波形,是不是IO输出有问题,可是我没有示波器啊。折腾了好久突然灵光乍现,是不是我的SPI的CS没有拉低啊,数据根本就没有写入oled,于是乎我将CS管脚接GND,复位一下,果然屏上出字了。高兴之余,我将之前的代码在gokit的硬件上重新验证了一遍,果然都没问题,就是CS没有置低的原因。检查代码后才发现,他只是定义了CS,根本就没在代码中体现啊,坑。
能出字后说明软硬件都没有问题了,将相关的oled.c和oled.h文件放在gokit的HAL文件夹中,当然还有相关字库头文件。
这里写图片描述

在main.c中相关函数中初始化后就可以正常显示了。

顺便说一下,gokit的代码写的是非常好,非常规范。后续有时间认真研究一下。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值