1276|6

270

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【ST NUCLEO-U5A5ZJ-Q开发板测评】03 SPI 驱动OLED [复制链接]

本篇使用SPI驱动0.96寸OLED显示屏

一、硬件

屏幕:中景园的0.96寸黄蓝OLED显示屏,驱动芯片是SSD1306。

OLED介绍

OLED引脚,是7针SPI模式。

  • GND 电源地VCC 电源正(3~5.5V)
  • D0 OLED 的 D0 脚,在 SPI 和 IIC 通信中为时钟管脚
  • D1 OLED 的 D1 脚,在 SPI 和 IIC 通信中为数据管脚
  • RES OLED 的 RES#脚,用来复位(低电平复位)
  • DC OLED 的 D/C#E 脚,数据和命令控制管脚

OLED与SPI引脚连接顺序为:

D0---PA5

D1---PA7

RES-PD14

DC---PD15

CS---PF12

 

二、软件设计

1、配置相关引脚

使能SPI1和配置相关参数

 

配置OLED DC/RST/CS引脚

2、编写OLED驱动函数

OLED.c

#include "OLED.h"
#include "oledfont.h"
#include "spi.h"

/*OLED段码分布
正常
(page0)      SEG0-SEG128
                    COM0
                     |
                    COM7

反置
(page0)       SEG128-SEG0
                    COM63
                     |
                    COM56
                    
写命令,其实是写寄存器
*/

/****************************************************************************
* 名    称:void OLED_Init(void)
* 功    能:OLED初始化
* 入口参数:无
* 出口参数:无
* 说    明:参照上电序列初始化(24/40)
****************************************************************************/
void OLED_Init(void)
{
    
    OLED_CS_High;
    //复位OLED
    OLED_RST_High;  
    HAL_Delay(200);
    OLED_RST_Low;
    HAL_Delay(200);
    OLED_RST_High;
    
    OLED_Write_Operate(OLED_Mode_Cmd,0xAE); //关闭OLED
    OLED_Write_Operate(OLED_Mode_Cmd,0x00); //设置列低位地址
    OLED_Write_Operate(OLED_Mode_Cmd,0x10); //设置列高位地址
  OLED_Write_Operate(OLED_Mode_Cmd,0x40); //设置起始行地址及映射RAM显示起始行 (0x00~0x3F)
    OLED_Write_Operate(OLED_Mode_Cmd,0xB0); //设置页地址
    OLED_Write_Operate(OLED_Mode_Cmd,0x81); //对比度设置
    OLED_Write_Operate(OLED_Mode_Cmd,0xCF); //Set SEG Output Current Brightness
    
    OLED_Write_Operate(OLED_Mode_Cmd,0xA1); //Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_Write_Operate(OLED_Mode_Cmd,0xA6); //
    OLED_Write_Operate(OLED_Mode_Cmd,0xA8); //设置驱动路数(1 to 64)
    OLED_Write_Operate(OLED_Mode_Cmd,0x3F); //*duty = 1/64*/ 
    OLED_Write_Operate(OLED_Mode_Cmd,0xC8); //0xc0上下反置 0xc8正常
    OLED_Write_Operate(OLED_Mode_Cmd,0xD3); //设置显示偏移(0x00~0x3F)
    OLED_Write_Operate(OLED_Mode_Cmd,0x00); //not offset
    OLED_Write_Operate(OLED_Mode_Cmd,0xD5); //--set Display clock divide ratio/oscillator frequency
    OLED_Write_Operate(OLED_Mode_Cmd,0x80); //--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_Write_Operate(OLED_Mode_Cmd,0xD9); //*set pre-charge period*/ 
    OLED_Write_Operate(OLED_Mode_Cmd,0Xf1); //Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_Write_Operate(OLED_Mode_Cmd,0xDA); //*set COM pins*/ 
    OLED_Write_Operate(OLED_Mode_Cmd,0x12); //
    OLED_Write_Operate(OLED_Mode_Cmd,0xdb); //*set vcomh*/ 
    OLED_Write_Operate(OLED_Mode_Cmd,0x40); //Set VCOM Deselect Level
    /**/
    OLED_Write_Operate(OLED_Mode_Cmd,0x20);    //设置存储模式(0x00,0x02,0x01)
    OLED_Write_Operate(OLED_Mode_Cmd,0x02); //页地址模式
    
    OLED_Write_Operate(OLED_Mode_Cmd,0x8d); //*set charge pump disable*/ 
    OLED_Write_Operate(OLED_Mode_Cmd,0x14); //--set(0x10) disable
    /**/
    OLED_Write_Operate(OLED_Mode_Cmd,0xA4); //显示开启(A4,显示,A5无显示)
    OLED_Write_Operate(OLED_Mode_Cmd,0xA6); //背景正反向显示(0xa6,正显,0xa7,反显)
    
    
    OLED_Display_Clear();                                        //清屏
    OLED_Write_Operate(OLED_Mode_Cmd,0xAF); //打开显示
    
}

/****************************************************************************
* 名    称:uint8_t OLED_Write_Byte(uint8_t data)
* 功    能:OLED写一个字节
* 入口参数:无
* 出口参数:接收的数据
* 返回值  :0失败,1成功
* 说    明:无
****************************************************************************/
uint8_t OLED_Write_Byte(uint8_t data)
{
    if(!HAL_SPI_Transmit(&hspi1, &data, 1, 10))
        return 0;
    else 
        return 1;
}


/****************************************************************************
* 名    称:void OLED_Write_Operate(uint8_t mode,uint8_t data)
* 功    能:OLED写操作
* 入口参数:模式,数据
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Write_Operate(uint8_t mode,uint8_t data)
{
    OLED_CS_Low;
    
    if(mode)
    {
        OLED_Write_Data;
    }
    else
    {
        OLED_Write_Cmd;
    }
    
    OLED_Write_Byte(data);
    
    OLED_CS_High;
}


/****************************************************************************
* 名    称:void OLED_Display_Clear(void)
* 功    能:OLED清屏
* 入口参数:无
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_Clear(void)
{
    uint8_t page = 0;
    uint8_t i=0;
    OLED_CS_Low;
    
    for(page=0;page < 8; page++)
    {
        OLED_Write_Operate(OLED_Mode_Cmd,0xB0+page);//设置页地址
        OLED_Write_Operate(OLED_Mode_Cmd,0x00);     //设置显示位置-列低地址
      OLED_Write_Operate(OLED_Mode_Cmd,0x10);     //设置显示位置-列高地址
        
        for(i = 0;i< 128; i++)
        {
            OLED_Write_Operate(OLED_Mode_Data,0x00);  //清屏
        }
    }
}



/****************************************************************************
* 名    称:void OLED_Set_Positon(void)
* 功    能:设置显示坐标
* 入口参数:x,y
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Set_Positon(uint8_t x,uint8_t y)
{
    
    OLED_Write_Operate(OLED_Mode_Cmd,0xB0 + y);                               //设置页地址
    OLED_Write_Operate(OLED_Mode_Cmd,((x & 0xf0) >>4 ) | 0x10); //设置列高四位地址
    OLED_Write_Operate(OLED_Mode_Cmd,(x & 0x0f) | 0x01);          //设置列低四位地址

}


/****************************************************************************
* 名    称:void OLED_Display_on(void)
* 功    能:显示打开
* 入口参数:无
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_on(void)
{
    
    OLED_Write_Operate(OLED_Mode_Cmd,0x8d); //写充电泵寄存器
    OLED_Write_Operate(OLED_Mode_Cmd,0x14); //打开充电泵
    OLED_Write_Operate(OLED_Mode_Cmd,0xAF);    //打开OLED显示

}


/****************************************************************************
* 名    称:void OLED_Display_offvoid)
* 功    能:显示关闭
* 入口参数:无
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_off(void)
{
    
    OLED_Write_Operate(OLED_Mode_Cmd,0x8d); //写充电泵寄存器
    OLED_Write_Operate(OLED_Mode_Cmd,0x10); //关闭充电泵
    OLED_Write_Operate(OLED_Mode_Cmd,0xAE);    //关闭OLED显示

}


/****************************************************************************
* 名    称:void OLED_Display_onechar(uint8_t x,uint8_t y,uint8_t character,uint8_t size)
* 功    能:显示单个字符
* 入口参数:
x ,y坐标位置
character 字符
size 字号大小
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_onechar(uint8_t x,uint8_t y,uint8_t character,uint8_t size)
{
    uint8_t c=0,i=0;
    c = character-' ';
    if(x > MAX_COLUMN - 1)
    {
        x= 0;
        if(size == SIZE8)
        {
            y = y+1;
        }
        if(size == SIZE16)
        {
            y = y+2;
        }
    }
    if(size == SIZE16)
    {
        OLED_Set_Positon(x,y);
        for( i =0;i< 8; i++)
        {
            OLED_Write_Operate(OLED_Mode_Data,F8X16[c*16 + i]);
        }
        OLED_Set_Positon(x,y+1);
        for( i =0;i< 8; i++)
        {
            OLED_Write_Operate(OLED_Mode_Data,F8X16[c*16 + i+8]);
        }
    }
    else
    {
        OLED_Set_Positon(x,y+1);
        for( i =0;i< 6; i++)
        {
            OLED_Write_Operate(OLED_Mode_Data,F6x8[c][i]);
        }
    }
}


/****************************************************************************
* 名    称:void OLED_Display_string(uint8_t x,uint8_t y,uint8_t *str,uint8_t size)
* 功    能:显示字符串
* 入口参数:
x ,y坐标位置
str 字符串
size 字号大小
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_string(uint8_t x,uint8_t y,uint8_t *str,uint8_t size)
{
    uint8_t i=0;
    while(str[i]!='\0')
    {
        OLED_Display_onechar(x,y,str[i],size);
        x += 8;
        if(x > 120)
        {
            x = 0;
            y += 2;
        }
        i++;
    }
}


/****************************************************************************
* 名    称:void OLED_Display_Chinese(uint8_t x,uint8_t y,uint8_t Sno)
* 功    能:显示单个字符
* 入口参数:
x ,y坐标位置
Sno 表示汉字数组中一个字的码所占的序号
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_Chinese(uint8_t x,uint8_t y,uint8_t Sno)
{
    uint8_t adder=0,i=0;
    OLED_Set_Positon(x,y);
    for(i = 0;i< 16;i++)
    {
        OLED_Write_Operate(OLED_Mode_Data,Hzk[2*Sno][i]);
        adder += 1;
    }
  OLED_Set_Positon(x,y+1);
    for(i = 0;i< 16;i++)
    {
        OLED_Write_Operate(OLED_Mode_Data,Hzk[2*Sno+1][i]);
        adder += 1;
    }    
}



/****************************************************************************
* 名    称:uint32_t OLED_POW(uint8_t m, uint8_t n)
* 功    能:m的n次方
* 入口参数:
m为底数,n为指数
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
uint32_t OLED_POW(uint8_t m, uint8_t n)
{
    uint32_t result=1;
    while(n--)
    {
        result *= m;
    }
    return result;
}


/****************************************************************************
* 名    称:void OLED_Display_Num(uint8_t x,uint8_t y,uint32_t num, uint8_t Len,uint8_t size)
* 功    能:显示单个字符
* 入口参数:
x ,y坐标位置
Sno 表示汉字数组中一个字的码所占的序号
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_Num(uint8_t x,uint8_t y,uint32_t num, uint8_t len,uint8_t size)
{
    uint8_t i=0;
    uint8_t endisplay=0;
    uint8_t temp=0;
    for(i = 0;i < len;i++)
    {
        temp = (num / (OLED_POW(10,len-i-1)))%10;
        if(endisplay == 0 && i < len-1)
        {
            if(temp == 0)
            {
                OLED_Display_onechar(x + (size / 2) * i,y,' ',size);
                continue;
            }
            else
            {
                endisplay = 1;
            }
        }
        OLED_Display_onechar(x + (size / 2) * i,y,temp + '0',size);
    }
}


/****************************************************************************
* 名    称:void OLED_Display_Picture(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t BMP[])
* 功    能:显示一张图片
* 入口参数:
x0 ,y0,x1,y1图片的大小
BMP[] 图片的码
* 出口参数:无
* 返回值  :无
* 说    明:无
****************************************************************************/
void OLED_Display_Picture(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t BMP[])
{
    uint8_t i=0;
    uint8_t x,y;
  if(y1 == 8)
  {
   y= y1/ 8;
    }        
    else
    {
        y = y1/ 8 + 1;
    }
    for(y = y0;y < y1;y++)
    {
        OLED_Set_Positon(x0,y);
        for(x = x0;x< x1; x++)
        {
            OLED_Write_Operate(OLED_Mode_Data,BMP[i++]);
        }    
    }
}

OLED.h

#ifndef _OLED_H
#define _OLED_H

#include "main.h"


/*引脚连接
PA4  CS  低电平有效
PA5  SCLK(SPI1)
PA6  RES/MISO  低电平有效
PA7  MOSI
PB0  DC 
Page0-7地址为B0-B7
*/

#define MAX_COLUMN 128
#define MAX_ROW    64

#define SIZE16       16
#define SIZE8        8

#define OLED_Mode_Data  1  //数据模式
#define OLED_Mode_Cmd   0  //命令模式

#define W25QXX_CS_L()
#define W25QXX_CS_H()

#define OLED_Write_Data HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET)   //写数据
#define OLED_Write_Cmd  HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET) //写命令

#define OLED_CS_High  HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_SET)     //片选无效
#define OLED_CS_Low   HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_RESET)   //片选有效

#define OLED_RST_High  HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET)
#define OLED_RST_Low   HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_RESET)

void OLED_Config(void);
void OLED_GPIO_Init(void);
void OLED_SPI_Init(void);
void OLED_Init(void);
uint8_t SPI1_WriteReadByte(uint8_t Data);
uint8_t OLED_Write_Byte(uint8_t data);
void OLED_Write_Operate(uint8_t mode,uint8_t data);
void OLED_Display_Clear(void);
void OLED_Set_Positon(uint8_t x,uint8_t y);
void OLED_Display_on(void);
void OLED_Display_off(void);

void OLED_Display_onechar(uint8_t x,uint8_t y,uint8_t character,uint8_t size);
void OLED_Display_string(uint8_t x,uint8_t y,uint8_t *str,uint8_t size);
uint32_t OLED_POW(uint8_t m, uint8_t n);
void OLED_Display_Num(uint8_t x,uint8_t y,uint32_t num, uint8_t len,uint8_t size);
void OLED_Display_Chinese(uint8_t x,uint8_t y,uint8_t Sno);
void OLED_Display_Picture(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t BMP[]);
#endif

三、下载验证

1、显示文字和图片

2、工程

oled-U5A5.zip (17.7 MB, 下载次数: 3)
此帖出自stm32/stm8论坛

最新回复

32和linux都玩的这么6,测评细致周密!学到了学到了   详情 回复 发表于 2024-2-2 13:42
点赞 关注
 

回复
举报

6587

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

可以作为SPI驱动0.96寸OLED显示屏的教程贴啦

此帖出自stm32/stm8论坛

点评

多谢大佬肯定  详情 回复 发表于 2024-2-1 08:59
 
 

回复

270

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
Jacktang 发表于 2024-2-1 07:44 可以作为SPI驱动0.96寸OLED显示屏的教程贴啦

多谢大佬肯定

此帖出自stm32/stm8论坛
 
 

回复

6841

帖子

11

TA的资源

版主

4
 

I2C经典教程,感谢精彩的分享!

此帖出自stm32/stm8论坛

点评

多谢  详情 回复 发表于 2024-2-1 10:13
 
 
 

回复

270

帖子

0

TA的资源

一粒金砂(高级)

5
 
lugl4313820 发表于 2024-2-1 09:48 I2C经典教程,感谢精彩的分享!

多谢

此帖出自stm32/stm8论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(中级)

6
 

32和linux都玩的这么6,测评细致周密!学到了学到了

此帖出自stm32/stm8论坛

点评

站在大佬的肩膀上,哈哈  详情 回复 发表于 2024-2-2 13:43
 
 
 

回复

270

帖子

0

TA的资源

一粒金砂(高级)

7
 
2609 发表于 2024-2-2 13:42 32和linux都玩的这么6,测评细致周密!学到了学到了

站在大佬的肩膀上,哈哈

此帖出自stm32/stm8论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表