历史上的今天

今天是:2024年09月10日(星期二)

正在发生

2018年09月10日 | STM32硬件SPI驱动0.96寸的OLED

发布者:平安心境 来源: 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之低功耗停机配置问题

推荐阅读

等待州长批准的加利福尼亚州参议院法案对最近社交媒体上的言论机器人作出了规管措施:法案规定,为了影响政治投票或获取资金,创建和运营社交媒体“机器人”是非法的,除非明确表示它是机器人。这项名为加利福尼亚SB1001的法案,由州参议员罗伯特·赫兹伯格发起,他是民主党人,但机器人问题不是任何政党所特有的。近期社交网络上的机器人操控选举问题引发...
荣耀Play3已经发布了,作为荣耀业务部副总裁(产品)熊军民也是铆足了干劲宣传该款产品。9月5日,熊军民转发某网友微博时表示:“以前写过4800万像素直出和插值差别的科普,有网友说不同价格产品对比会显得不公平。荣耀Play3以999元“吓人”价格,成为千元内首个使用4800万像素硬件直出的产品。相比一些靠1200万像素插值成4800万的误导宣传,荣耀Play3的4800...
9月9日-11日,2020 CIOE中国光博会在深圳举办,本届展会上,激光雷达芯片和模组厂商洛微科技(LuminWave)展示了国内首款基于硅光OPA的200线纯固态成像级激光雷达(LiDAR)。 据了解,洛微科技早在今年1月的CES展上就推出了世界上尺寸最小的基于自研光芯片技术的MicroLiDAR传感器芯片,主要用于自动驾驶近距补盲和手势识别。此次洛微科技展示的激光雷达原...
今天,中国信通院对外表示,我国首届 6G 研讨会将在9月16在京召开,研讨会共计2天。研讨会将重点分享全球在 6G方面的 进展情况、6G 愿景、潜在关键技术等。本次研讨会由IMT-2030(6G)推进组主办,承办单位为中国信通院、中国通信学会承办,协办单位为推进组成员单位、中国 IDC 圈。探讨的话题涉及十多个重点科研领域,主要包括: 6G 无线融合通...

史海拾趣

问答坊 | AI 解惑

小信号放大时的温漂如何解决?

小信号放大时的温漂如何解决? [6][6][6][6][6][6][6][6][6]…

查看全部问答∨

台电信商盼大陆启动3G 杀手锏为视频业务

      对于台湾三大电信商来说,去年5月启动3G(第三代移动通信技术)后的最大感受是:3G应用是决定市场成败的第一要义。        近日,诺基亚在台湾发起的“3G应用论坛” ...…

查看全部问答∨

有关于运放的知识

本帖最后由 paulhyde 于 2014-9-15 09:28 编辑 一些用过的运放芯片资料和运放使用技巧~~~  …

查看全部问答∨

没有windows系统下怎么开发嵌入式?

各位高人,请问谁知道在纯Linux系统下怎么开发嵌入式,怎么和2440开发板传输数据,有没有比较好的工具呢?我看现在所谓的嵌入式Linux系统都是在windows下装一个Linux的虚拟机,那叫狗屁嵌入式Linux啊,还得在那个垃圾windows下开发,有没有哪位高人 ...…

查看全部问答∨

光电曲线测试仪

初步规划为:       1个SSI 接口挂三个AD芯片;一个I2C 接口挂一个DA;一个串口和网口与PC通信,一个JTAG/SWD 接口和调试指示灯…

查看全部问答∨

acd0809多路输入选择的问题

0809有8路输入,我现在连接了两路(选路地址的B和C位都接地了,因此,A位的0、1,可以直接选择in0和in1,C、B、A相当于000和001),in0和in1;in0没问题,但是in1没反应,请教是怎么回事,谢谢 void adc0809_init(unchar ch)      ...…

查看全部问答∨

VxWork问题求救。

VxWorks在获取路由信息过程中,通过OSPF_Init()从FTP服务器中获取配置信息后,函数运行成功(状态码显示已成功),为什么实际上却没有获得配置信息,是什么引起的?…

查看全部问答∨

UCOSII源码剖析

有做过 UCOSII 源码剖析的吗 有做过 UCGUI  开发的吗…

查看全部问答∨

出手一个ARM11 tiny6410开发板

本帖最后由 ddllxxrr 于 2016-1-7 17:05 编辑 本站强荐:185娱乐┍城.足球┍真_人.彩票齐全┍手机可投┍注任何游戏. 首次开户送10元.首存送58元.信誉绝对保证185.cc …

查看全部问答∨

基于msp430f149的24c02程序

#ifndef __24C02_H__#define __24C02_H__#include \"msp430x14x.h\"#define OP_READ 0xa1        // 器件地址以及读取操作    #define OP_WRITE 0xa0       // ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved