STM32硬件SPI驱动0.96寸的OLED

发布者:平安心境最新更新时间:2018-09-10 来源: eefocus关键字:STM32  硬件SPI  OLED 手机看文章 扫描二维码
随时随地手机看文章

1.OLED相关


参见—->51 软件模拟SPI驱动OLED


2.硬件SPI


参见—->SPI专题(二)——STM32驱动FLASH(W25Q64)


3.驱动程序


驱动程序参照51单片机进行移植,只不过模拟的SPI换成STM32硬件SPI,不用再写时序部分的代码。对于STM32的硬件SPI,我们在驱动FLASH中已有介绍,这里就不再做介绍。


OLED引脚部分定义:


#ifndef __OLED_H

#define __OLED_H


#include "spi.h"

#include "stm32f10x.h"

#include "stm32f10x_conf.h"


#define Max_Column  128

#define Max_Row     64

#define SIZE 16 //显示字体选择



#define RCC_APB2Periph_OLED_PORT    RCC_APB2Periph_GPIOA

#define OLED_PORT                   GPIOA


#define OLED_CS_PIN     GPIO_Pin_2

#define OLED_CS_LOW     GPIO_ResetBits(GPIOA,GPIO_Pin_2)                        

#define OLED_CS_HIGH    GPIO_SetBits(GPIOA,GPIO_Pin_2)


#define OLED_DC_PIN     GPIO_Pin_3

#define OLED_DC_LOW     GPIO_ResetBits(GPIOA,GPIO_Pin_3)

#define OLED_DC_HIGH    GPIO_SetBits(GPIOA,GPIO_Pin_3)


#define OLED_RST_PIN    GPIO_Pin_4

#define OLED_RST_LOW    GPIO_ResetBits(GPIOA,GPIO_Pin_4)

#define OLED_RST_HIGH   GPIO_SetBits(GPIOA,GPIO_Pin_4)


#define OLED_CLK_PIN    GPIO_Pin_5

#define OLED_DATA_PIN   GPIO_Pin_7


void SPI_OLED_Init(void);

void OLED_Write_Byte(uint8_t dat);

void OLED_Write_Data(uint8_t dat);

void OLED_Write_Cmd(uint8_t cmd);



void OLED_Set_Pos(u8 x,u8 y);

void OLED_Display_On(void);

void OLED_Display_Off(void);

void OLED_Display_Clear(void);

void OLED_Display_Onechar(u8 x,u8 y,u8 str);

void OLED_Display_String(u8 x,u8 y,u8 *str);

void OLED_Display_Chinese(u8 x,u8 y,u8 no);

void OLED_Display_Picture(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]);

u32 OLED_Pow(u8 m,u8 n);

void OLED_Display_Num(u8 x,u8 y,u32 num,u8 len,u8 size_num);

void OLED_Init(void);


#endif


连接的时候需要看清楚,一开始我就不小心把SPI的CLK与DO接反了,半天找不到原因,这种问题就太低级了,一定得多细心。


OLED初始化:


void SPI_OLED_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_OLED_PORT, ENABLE );


    //片选信号初始化

    GPIO_InitStructure.GPIO_Pin = OLED_CS_PIN|OLED_DC_PIN|OLED_RST_PIN;  

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //复用推挽输出

    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

    GPIO_Init(OLED_PORT, &GPIO_InitStructure);

    GPIO_SetBits(OLED_PORT,OLED_CS_PIN|OLED_DC_PIN|OLED_RST_PIN);


    SPI1_Init();           //初始化SPI

    SPI1_SetSpeed(SPI_BaudRatePrescaler_16);    //设置为18M时钟,高速模式

}  


OLED写数据实现:


//硬件SPI发送数据

void OLED_Write_Byte(uint8_t dat)

{

    SPI1_ReadWriteByte(dat);

}


//写入数据

void OLED_Write_Data(uint8_t dat)

{

    OLED_CS_LOW;

    OLED_DC_HIGH;

    OLED_Write_Byte(dat);

}


//写入命令

void OLED_Write_Cmd(uint8_t cmd)

{

    OLED_CS_LOW;

    OLED_DC_LOW;

    OLED_Write_Byte(cmd);

}


下面就是OLED的具体实现,开启,初始化,写一个字节,写字符串等,也是在51MCU的基础上修改而成。


//Function:设置显示坐标

//Input:x:横坐标;y:纵坐标

//Output:无

//Return:无

//Others:无

void OLED_Set_Pos(uint8_t x,uint8_t y)

{

    OLED_Write_Cmd(0xb0+y);//列偏移

    OLED_Write_Cmd(((x&0xf0)>>4)|0x10);//行高四位地址

    OLED_Write_Cmd((x&0x0f)|0X01);//行低四位地址

}


//Function:开启OLED显示

//Input:无

//Output:无

//Return:无

//Others:无

void OLED_Display_On(void)

{

    OLED_Write_Cmd(0X8D);//设置DCDC

    OLED_Write_Cmd(0X14);//打开DCDC

    OLED_Write_Cmd(0XAF);//打开OLED

}


//Function:关闭OLED显示

//Input:无

//Output:无

//Return:无

//Others:无

void OLED_Display_Off(void)

{

    OLED_Write_Cmd(0X8D);//设置DCDC

    OLED_Write_Cmd(0X10);//关闭DCDC

    OLED_Write_Cmd(0XAE);//关闭OLED

}


//Function:清屏

//Input:无

//Output:无

//Return:无

//Others:无

void OLED_Display_Clear(void)

{

    u8 page,len;


    for(page=0;page<8;page++)

    {

        OLED_Write_Cmd(0xB0+page);//设置页地址(0--7)

        OLED_Write_Cmd(0X00);//设置显示位置—列低地址

        OLED_Write_Cmd(0X10); //设置显示位置—列高地址


        for(len=0;len<128;len++)

            OLED_Write_Data(0);//写入0;屏熄灭

    }

}

//Function:在指定位置显示一个字符,包括部分字符

    //x:0~127;y:0~63;size:选择字体 16/12 

//Input:x:横坐标;y:纵坐标;str:显示的字符

//Output:无

//Return:无

//Others:无               

void OLED_Display_Onechar(u8 x,u8 y,u8 str)

{

    u8 i=0,ret=0;

    //ret = str -32;

    ret = str - ' ';//得到偏移后的值,对ASCLL码进行一个减法.即在二维数组里找它的位置  

    if(x>Max_Column-1)

    {

        x = 0;

        y = y + 2;//针对16号的字符

    }

    if(SIZE == 16 )

    {

        OLED_Set_Pos(x,y);

        //16的字体分成两部分写入

        for(i=0;i<8;i++)

        OLED_Write_Data(F8X16[ret*16+i]);

        OLED_Set_Pos(x,y+1);

        for(i=0;i<8;i++)

            OLED_Write_Data(F8X16[ret*16+i+8]);

    }

    else{

        OLED_Set_Pos(x,y+1);

        for(i=0;i<6;i++)

            OLED_Write_Data(F6x8[ret][i]);

    }

}


//Function:显示字符串

//Input:x:横坐标;y:纵坐标;str:显示的字符串

//Output:无

//Return:无

//Others:无

void OLED_Display_String(u8 x,u8 y,u8 *str)

{

    u8 i=0;


    while(str[i]!='\0')

    {

        OLED_Display_Onechar(x,y,str[i]);

        x += 8;

        if(x>120)

        {

            x = 0;

            y += 2;

        }

        i++;

    }

}


//Function:显示中文

//Input:x:横坐标;y:纵坐标;no:显示的字的序号

//Output:无

//Return:无

//Others:无

void OLED_Display_Chinese(u8 x,u8 y,u8 no)

{

    u8 ch,addr=0;


    OLED_Set_Pos(x,y);

    for(ch=0;ch<16;ch++)//数组行列寻址

    {

        OLED_Write_Data(TEST[2*no][ch]);//汉字是2个字节

        addr += 1;

    }

    OLED_Set_Pos(x,y+1);

    for(ch=0;ch<16;ch++)

    {

        OLED_Write_Data(TEST[2*no+1][ch]);

        addr += 1;

    }


}


//Function:显示图片

//Input:x0,x1:横坐标;y0,y1:纵坐标;BMP:显示的图片

//注意:y1<8,页寻址模式

//Output:无

//Return:无

//Others:无

void OLED_Display_Picture(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[])

{

    u8 x,y;

    u32 i=0;


    if(y1%8==0)

        y = y1 / 8;

    else

        y = y1 /8 + 1;

    for(y=y0;y

    {

        OLED_Set_Pos(x0,y);

        for(x=x0;x

        {

            OLED_Write_Data(BMP[i++]);

        }

    }

}


//计算m的n次方

u32 OLED_Pow(u8 m,u8 n)

{

    u32 ret = 1;

    while(n--)

        ret *= m;

    return ret;

}


//Function:显示数字

//Input:x:横坐标;1:纵坐标;num:显示的数字:len:数字长度;size_num:数字字体

//Output:无

//Return:无

//Others:无

void OLED_Display_Num(u8 x,u8 y,u32 num,u8 len,u8 size_num)

{

    u8 t,temp;

    u8 enshow = 0;


    for(t=0;t

    {

        temp = (num/OLED_Pow(10,len-t-1))%10;//把显示的数字一位一位取出来

        if(enshow==0&&t<(len-1))

        {

            if(temp==0)

            {

                OLED_Display_Onechar(x+(size_num/2)*t,y,' ');

                continue;

            }

            else

                enshow = 1;

        }

        OLED_Display_Onechar(x+(size_num/2)*t,y,temp+'0');

    }

}


//初始化SSD1306

//命令设置与开启函数作用重叠......

void OLED_Init(void)

{

    SPI_OLED_Init();


    OLED_RST_HIGH;

    delay_ms(200);

    OLED_RST_LOW;

    delay_ms(200);

    OLED_RST_HIGH; 


    OLED_Write_Cmd(0xAE);//关闭OLED

    OLED_Write_Cmd(0x00);//设置列低位地址

    OLED_Write_Cmd(0x10);//设置列高位地址

    OLED_Write_Cmd(0x40);//设置起始行地址及映射RAM显示起始行 (0x00~0x3F)

    OLED_Write_Cmd(0x81);//对比度设置

    OLED_Write_Cmd(0xCF); // Set SEG Output Current Brightness

    OLED_Write_Cmd(0xA1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常

    OLED_Write_Cmd(0xC8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常

    OLED_Write_Cmd(0xA6);//设置显示方式;bit0:1,反相显示;0,正常显示

    OLED_Write_Cmd(0xA8);//设置驱动路数(1 to 64)

    OLED_Write_Cmd(0x3f);//--1/64 duty

    OLED_Write_Cmd(0xD3);//-设置显示偏移(0x00~0x3F)

    OLED_Write_Cmd(0x00);//-not offset

    OLED_Write_Cmd(0xd5);//--set display clock divide ratio/oscillator frequency

    OLED_Write_Cmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec

    OLED_Write_Cmd(0xD9);//--set pre-charge period

    OLED_Write_Cmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock

    OLED_Write_Cmd(0xDA);//--set com pins hardware configuration

    OLED_Write_Cmd(0x12);

    OLED_Write_Cmd(0xDB);//--set vcomh

    OLED_Write_Cmd(0x40);//Set VCOM Deselect Level

    OLED_Write_Cmd(0x20);//设置页地址模式(0x00/0x01/0x02)

    OLED_Write_Cmd(0x02);//

    OLED_Write_Cmd(0x8D);//--set Charge Pump enable/disable

    OLED_Write_Cmd(0x14);//--set(0x10) disable

    OLED_Write_Cmd(0xA4);//禁用显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)(0xa4/0xa5)

    OLED_Write_Cmd(0xA6);// 不使用反向显示 (0xa6/a7) 

    OLED_Write_Cmd(0xAF);//打开显示


    OLED_Write_Cmd(0xAF); /*display ON*/

    OLED_Display_Clear();

    OLED_Set_Pos(0,0);  

}  


实现效果:

这里写图片描述

关键字:STM32  硬件SPI  OLED 引用地址:STM32硬件SPI驱动0.96寸的OLED

上一篇:STM32F4使用硬件SPI驱动ADS8322
下一篇:STM8L051之低功耗停机配置问题

推荐阅读最新更新时间:2024-03-16 16:13

STM32+Keil 如何使用printf函数?
Keil不支持Host-semi机制,即不支持直接在IDE打印字符串。 那么只能通过程序向硬件串口发数据了,这样调用的时候用自定义的函数即可,也很方便,例如: void send_char_to_usart(unsigned char c){} 但是可否直接使用printf函数呢?毕竟人家都做好了,我们给他定一个打印输出的接口就可以了,答案是肯定的,看ST的官方源码: /** ****************************************************************************** * @file Lib_DEBUG/Lib_DEBUG_Example/m
[单片机]
错估 OLED 普及时间,传JDI撤重建计划、找外部企业资本合作
eeworld网消息,据日经新闻报导,因对于OLED 面板普及时间的错判,LG Display(LGD)分食苹果订单的现状,全球中小尺寸面板厂商Japan Display Inc(以下简称JDI)将撤回2016年年末发表的中期营运计划,之后将在今年8月发表由预计于6月21日举行的定期股东会后上路的新经营团队所研拟的“新中期营运计划”,该新重建计划内容将包含整编日本国内据点、人员重新配置等能让JDI摆脱亏损体质的对策。 据JDI 5月10日公布的财报资料显示,上年度(2016年4月-2017年3月)JDI合并净损额为316.64亿日圆(前一个年度为净损318.4亿日圆)、已连续第3年陷入亏损。为了筹措结构改革费用,JDI将活用外
[手机便携]
STM32程序软件复位
在需要软件复位的地方添加如下两句代码: __set_FAULTMASK(1); //STM32程序软件复位 NVIC_SystemReset();
[单片机]
STM32模拟IIC读写24CXX
文件(iic.h): #define SDA_IN() {GPIOB- CRL&=0X0FFFFFFF;GPIOB- CRL|=0X80000000;} #define SDA_OUT() {GPIOB- CRL&=0X0FFFFFFF;GPIOB- CRL|=0X30000000;} #define IIC_SCL PBout(6) #define IIC_SDA PBout(7) #define READ_SDA PBin(7) void bsp_iic_init(void); void bsp_iic_start(void); void bsp_iic_st
[单片机]
STM32 PWM输入捕获
STM32定时器具有PWM的输入捕获模式。PWM输入捕获是定时器输入捕获的一个特例,它专门用于测量PWM波的频率与占空比(芯片设计得还真人性化)。在上一篇博文中,我用输入捕获实现了输入PWM波的频率测量,而这一次,我用定时器的PWM输入捕获来测量PWM波的频率与占空比。他们的基本思路差不多,唯一区别的地方就是前者采用软件实现计数值的记录,而后者硬件直接记录计数值。如下图所示PWM输入捕获的时序: 上面说过PWM的输入捕获是硬件自动记录计数值,从上图就可知道:当检测到上升沿信号,硬件会自动清除计数值,然后当检测到下降沿时,就将当前定时器的计数值保存在IC2捕获寄存器中,当再次检测到一个上升沿信号时,则保存当前的计数值到IC1捕
[单片机]
<font color='red'>STM32</font> PWM输入捕获
STM32 Flash详解
本文将根据ST官方Flashprogramming manual,文档编号:PM0059,讲解STM32F207内部Flash编程。 01、概述 这里的flash是指STM32F207内部集成的Flash Flash存储器有以下特点 最大1M字节的能力 128位,也就是16字节宽度的数据读取 字节,半字,字和双字写入 扇区擦除和批量擦除 存储器的构成 主要存储区块包含4个16K字节扇区,1个64K字节扇区和7个128K字节扇区。 系统存储器是用于在系统boot模式启动设备的。这一块是预留给ST的。包括bootloader程序,boot程序用于通过以下接口对Flash进行编程。USART1、USART3、CAN2、
[单片机]
<font color='red'>STM32</font> Flash详解
韩媒:苹果明年 iPhone或全面采用触控一体OLED 屏,或引领市
据韩媒etnews报道,业内人士透露,苹果为其2021年新款iPhone订购了一批触摸一体OLED屏。另外,苹果要求明年在新iPhone中使用的所有面板都必须具有触摸集成功能。 据悉,现有的触摸输入是通过将触摸传感器薄膜粘贴到屏幕上来实现的,而触摸一体是指具有内置触摸功能的OLED屏。在OLED屏的薄膜封装上实现触摸功能可使屏幕变薄的同时降低成本。 该报道称,苹果从2007年第一部iPhone发行之日起便一直采用以往的“触摸传感器薄膜”方案,但目前看来这一策略似乎正在改变。苹果或将在今年发布的6.1英寸的iPhone12上采用触摸一体OLED屏,且该屏幕由三星显示器(Samsung Display)和LG显示器(LG Disp
[手机便携]
OLED驱动电源解决方案
功能先进的显示器渐成为现今消费电子产品的重要特色,这些新型显示器所发挥的作用,通常会强化使用者对于整体产品的印象,而这样的印象最终会决定该产品在市场上会多成功。使用者在面对行动电话和口袋型计算机时,对新型显示器的印象尤为重要,因为高分辨率彩色屏幕已成为这些产品的必备功能。   多种新型显示技术正扩大其市场占有率,包括新出现的OLED显示器在内,它们拥有超高的对比值、快速的响应时间和宽广的视角。就像其它新技术一样,厂商正利用不同的 LED 材料(聚合物或小分子)、主动或被动矩阵控制、电流和电压 驱动 技术,以及不同的偏压供应电路来评估和制造不同的解决方案。   本文将讨论各种OLED技术和适当的偏压 电源 供应电路,
[电源管理]
<font color='red'>OLED</font>驱动电源解决方案
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved