SPI驱动0.96/1.3寸 OLED屏幕,易修改为DMA控制

发布者:science56最新更新时间:2022-07-14 来源: csdn关键字:SPI驱动  OLED屏幕  DMA控制 手机看文章 扫描二维码
随时随地手机看文章

STC实验箱4

IAP15W4K58S4

Keil uVision V5.29.0.0

PK51 Prof.Developers Kit Version:9.60.0.0


DMA控制见【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结


OLED SPI 端口定义

本节引自STM32驱动0.96寸OLED液晶屏(12864液晶屏) —— 小牧同学

在这里插入图片描述

两种屏幕的引脚数不一样,左边的有7个引脚,而右边的只有6个。其次,端口的标号也不完全一样,第一个分别标为GND,VCC,D0,D1,RES,DC和CS第二个分别标为GND,VCC,SCL,SDA,RST,D/C。


七针OLED引脚定义

GND — 接地端口

VCC — 接3.3V电源端口

D0 — CLK时钟信号(等同于上面的SCL)

D1 — 数据端口(等同于上面的SDA)

RES — 复位端口(等同于上面的RST)

DC — 数据/命令选择引脚(等同于上面的D/C)

CS — 片选引脚(低电平有效,也就是所需要接低电平,我实际试验过不接该引脚也是可以正常使用的)


六针OLED引脚定义

GND — 接地端口

VCC — 接3.3V电源端口

SCL — CLK时钟信号端口

SDA — MOSI数据端口

RST — 复位端口

D/C — 数据/命令选择引脚


在这里插入图片描述

驱动程序

       指令解读见【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解

       软件SPI程序见【51单片机快速入门指南】5:软件SPI

       SPI选择模式1或2均可,实测模式0也行。

       51内核单片机所用的stdint.h见【51单片机快速入门指南】1:基础知识和工程创建


oled.c

#include "./SPI_OLED/oled.h"

#include "./SPI_OLED/oledfont.h"

#include "./Soft_SPI/Soft_SPI.h"

#include "./Drivers/delay.h"


sbit OLED_RES = P2 ^ 6;

sbit OLED_DC = P2 ^ 7;

sbit OLED_CS = P2 ^ 4;


//OLED_RST拉高 移植时需修改

void OLED_RST_H()

{

    OLED_RES = 1;

}


//OLED_RST拉低 移植时需修改

void OLED_RST_L()

{

    OLED_RES = 0;

}


//OLED_DC拉高 移植时需修改

void OLED_DC_H()

{

    OLED_DC = 1;

}


//OLED_DC拉低 移植时需修改

void OLED_DC_L()

{

    OLED_DC = 0;

}


//OLED_CS拉高 移植时需修改

void OLED_CS_H()

{

    OLED_CS = 1;

}


//OLED_CS拉低 移植时需修改

void OLED_CS_L()

{

    OLED_CS = 0;

}


//OLED的显存

//存放格式如下.

//[0]0 1 2 3 ... 127

//[1]0 1 2 3 ... 127

//[2]0 1 2 3 ... 127

//[3]0 1 2 3 ... 127

//[4]0 1 2 3 ... 127

//[5]0 1 2 3 ... 127

//[6]0 1 2 3 ... 127

//[7]0 1 2 3 ... 127


#if OLED_BUFFER_MODE


uint8_t OLED_GRAM[Max_Row / 8][Max_Column] = {0};


#endif


/**************************************************************************

 Function: Refresh the OLED screen

 Input   : none

 Output  : none

 函数功能:刷新OLED屏幕

 入口参数:无

 返回  值:无

 **************************************************************************/

void OLED_Refresh_Gram(void)

{

#if OLED_BUFFER_MODE

    uint16_t i;

    OLED_Set_Pos(0, 128);

    for (i = 0; i < Max_Row / 8 * Max_Column; i++)

    {

        OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA);

    }

#endif

}


/**

* @brief 向SSD1306写入一个字节

* @param dat:要写入的数据/命令 cmd:数据/命令标志 0,表示命令;1,表示数据;

* @retval None

*/

void OLED_WR_Byte(uint8_t dat, uint8_t cmd)

{

    OLED_CS_L();

    if (cmd)

        OLED_DC_H();

    else

        OLED_DC_L();

    SOFT_SPI_RW_MODE2(dat);

    OLED_DC_H();

    OLED_CS_H();

}


/**************************************************************************

 Function: Set the coordinates (position) displayed on the screen.

 Input   : x, y: starting point coordinates

 Output  : none

 函数功能:设置汉字在屏幕上显示的坐标(位置)

 入口参数: x,y :起点坐标

 返回  值:无

 **************************************************************************/

void OLED_Set_Pos(uint8_t x, uint8_t y)

{

    OLED_WR_Byte(0xb0 + y, OLED_CMD);

    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);

    OLED_WR_Byte((x & 0x0f), OLED_CMD);

}


/**

* @brief 开启OLED显示

* @param None

* @retval None

*/

void OLED_Display_On(void)

{

    OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令

    OLED_WR_Byte(0X14, OLED_CMD);  //DCDC ON

    OLED_WR_Byte(0XAF, OLED_CMD);  //DISPLAY ON

}


/**

* @brief 关闭OLED显示

* @param None

* @retval None

*/

void OLED_Display_Off(void)

{

    OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令

    OLED_WR_Byte(0X10, OLED_CMD);  //DCDC OFF

    OLED_WR_Byte(0XAE, OLED_CMD);  //DISPLAY OFF

}


/**

* @brief 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样

* @param None

* @retval None

*/

void OLED_Clear(void)

{

#if OLED_BUFFER_MODE

    uint16_t i;

    for (i = 0; i < Max_Row / 8 * Max_Column; i++)

    {

        OLED_GRAM[0][i] = 0;

    }

    OLED_Refresh_Gram(); //Update the display //更新显示

#else

    uint8_t i, n;

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

    {

        OLED_WR_Byte(0xb0 + i, OLED_CMD);    //设置页地址(0~7)

        OLED_WR_Byte(0x00, OLED_CMD);      //设置显示位置—列低地址

        OLED_WR_Byte(0x10, OLED_CMD);      //设置显示位置—列高地址

        for (n = 0; n            OLED_WR_Byte(0, OLED_DATA);

    }//更新显示

#endif

}


/**

* @brief 在指定位置显示一个字符,包括部分字符

* @param x:0~127   y:0~63   Is_Reverse:1,反白显示  0,正常显示 charSize:选择字体 16/6

* @retval None

*/

void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t charSize, uint8_t Is_Reverse)

{

    uint8_t i = 0;

    chr -= ' '; //得到偏移后的值

    if (x > Max_Column - 1)

    {

        x = 0;

        y = y + 2;

    }

#if OLED_BUFFER_MODE

    if(charSize == 16)

    {

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

{

OLED_GRAM[y][x+i] = Is_Reverse == 0?F8X16[chr][i]:~F8X16[chr][i];

OLED_GRAM[y+1][x+i] = Is_Reverse == 0?F8X16[chr][i+8]:~F8X16[chr][i+8];

}

    }

    else if(charSize == 6)

    {

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

{

OLED_GRAM[y][x+i] = Is_Reverse == 0?F8X6[chr][i]:~F8X6[chr][i];

}

    }

#else

    if (charSize == 16)

    {

        OLED_Set_Pos(x, y);

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

            OLED_WR_Byte(Is_Reverse == 0?F8X16[chr][i]:~F8X16[chr][i], OLED_DATA);

        OLED_Set_Pos(x, y + 1);

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

            OLED_WR_Byte(Is_Reverse == 0?F8X16[chr][i + 8]:~F8X16[chr][i + 8], OLED_DATA);

    }

    else if(charSize == 6)

    {

        OLED_Set_Pos(x, y);

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

            OLED_WR_Byte(Is_Reverse == 0?F8X6[chr][i]:~F8X6[chr][i], OLED_DATA);

    }

#endif

}


/**

* @brief m^n函数

* @param None

* @retval None

*/

uint32_t oled_pow(uint8_t m, uint8_t n)

{

    uint32_t result = 1;

    while (n--)result *= m;

    return result;

}


/**

* @brief 显示2个数字

* @param x,y :起点坐标

* len :数字的位数,即显示几位有效数字

* Size:字体大小

* mode:模式 0,填充模式;1,叠加模式

*        num:数值(0~4294967295);

* @retval None

*/

void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t Size, uint8_t Is_Reverse)

{

    uint8_t t, temp;

    uint8_t enshow = 0;

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

    {

        temp = (num / oled_pow(10, len - t - 1)) % 10;

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

        {

            if (temp == 0)

            {

                OLED_ShowChar(x + 8 * t, y, ' ', Size, Is_Reverse);

                continue;

            }

            else

                enshow = 1;


        }

        OLED_ShowChar(x + 8 * t, y, temp + '0', Size, Is_Reverse);

    }

}


/**

* @brief 显示一个字符号串

* @param

* @retval None

*/

void OLED_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t charSize, uint8_t Is_Reverse)

{

    uint8_t j = 0;

    while (chr[j] != '')

    {

        OLED_ShowChar(x, y, chr[j], charSize, Is_Reverse);

        x += 8;

        if (x>120)

        {

            x = 0;

            y += 2;

        }

        j++;

    }

}


/**

* @brief 显示汉字

* @param

* @retval None

*/

void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t no, uint8_t Is_Reverse)

{

    uint8_t i;

#if OLED_BUFFER_MODE

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

    {

OLED_GRAM[y][x+i] = Is_Reverse == 0?Hzk[2 * no][i]:~Hzk[2 * no][i];

OLED_GRAM[y+1][x+i] = Is_Reverse == 0?Hzk[2 * no + 1][i]:~Hzk[2 * no + 1][i];

    }

#else

    OLED_Set_Pos(x, y);

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

    {

        OLED_WR_Byte(Is_Reverse == 0?Hzk[2 * no][i]:~Hzk[2 * no][i], OLED_DATA);

    }

    OLED_Set_Pos(x, y + 1);

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

    {

        OLED_WR_Byte(Is_Reverse == 0?Hzk[2 * no + 1][i]:~Hzk[2 * no + 1][i], OLED_DATA);

    }

#endif

}


/**

* @brief 显示显示BMP图片

* @param 显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7

* @retval None

*/

void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t BMP[], uint8_t Is_Reverse)

{

    uint16_t j = 0;

    uint8_t x, y;


    if (y1 % 8 == 0) 

y = y1 / 8;

    else 

y = y1 / 8 + 1;

#if OLED_BUFFER_MODE

    for (y = y0; y    {

        for (x = x0; x        {

OLED_GRAM[y][x] = Is_Reverse == 0?BMP[j++]:~BMP[j++];

        }

    }

#else

    for (y = y0; y    {

        OLED_Set_Pos(x0, y);

        for (x = x0; x        {

            OLED_WR_Byte(Is_Reverse == 0?BMP[j++]:~BMP[j++], OLED_DATA);

        }

    }

#endif

}


/**

* @brief 初始化SSD1306

* @param None

* @retval None

*/

void OLED_Init(void)

{

    OLED_RST_H();

    delay_ms(10);

[1] [2] [3] [4]
关键字:SPI驱动  OLED屏幕  DMA控制 引用地址:SPI驱动0.96/1.3寸 OLED屏幕,易修改为DMA控制

上一篇:【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真
下一篇:【51单片机快速入门指南】5.3:SPI控制晶联讯JLX12864G_08602 LCD屏幕

推荐阅读最新更新时间:2024-11-17 23:01

传苹果正与京东方磋商OLED屏幕供应,大规模提供仍需等待
集微网消息,据彭博社报道,知情人士透露,苹果正在就为其未来iPhone手机提供 OLED 显示屏事宜与京东方进行磋商。 其中一位知情人士说,苹果已对京东方的AMOLED显示屏进行了数月的测试,但目前尚未作出决定。由于磋商尚处于初级阶段,京东方为下一款iPhone提供显示屏的可能性不大,目标或将是 2018 款或之后的机型。    京东方在电子邮件中说,公司将斥资近 1000 亿元人民币(145亿美元)在四川省兴建两座 AMOLED 工厂。苹果不愿就此发表评论,京东方表示,有关与客户的磋商,公司一向不予置评。 手机中国联盟秘书长老杳表示,当年京东方投巨资在 OLED 面板就是因为在与苹果合作中获得了信息,不过双方在 OLED 领
[手机便携]
三星被苹果惨踢出局,OLED屏幕后续由LG供应
我们都知道,在oled屏幕技术上三星一直都是一家独大的局面,在iPhone X OLED屏幕也是由三星提供的。据报道,苹果想要寻求新的供应商,LG将会是不错的选择,只是它的技术有点令人担忧啊。 苹果正在为自家当红新机iPhone X寻找新的OLED屏幕供应商,它就是三星的韩国同胞LG。据悉,两家公司已经签订了OLED屏幕供应协议,韩国巨头将为苹果供应6000万块OLED屏幕,而LG Display的生产设备正在紧锣密鼓的准备中,预计明年6月正式量产。 当然,现在这一消息还没得到LG Display的证实,不过它们本月6日回应称:“有关苹果iPhone X OLED屏幕供应问题,我们暂时还没有细节可公布。一旦事情定下来,我们
[电源管理]
效果不输iPad?盘点搭载OLED屏幕的车型
刚刚过去的12月,数码爱好者先后经历了OPPO、vivo、华为、小米的新品发布会,天天都在“过年”。对于如今的中高端智能手机来说,OLED屏幕是标配,善于“内卷”的科技厂商还在此基础上开拓了亮度、色域、刷新率等战场。而在汽车领域,OLED作为新一代显示技术,普及速度慢得惊人。想提升自己的“Geek”属性吗?这五款搭载OLED屏幕的车型必须了解一下。 ◆ LCD VS OLED OLED屏幕产业已经相当成熟,只是在车载应用上还有待推进,挡在前面的困难有成本、良品率、使用寿命等,需要在大量的实际应用中打磨完善。 针对因有机材料老化导致的“烧屏”,主流面板厂商给出了小幅度切换像素位置、分区域控制亮度等方案,尽量保证屏
[汽车电子]
效果不输iPad?盘点搭载<font color='red'>OLED</font><font color='red'>屏幕</font>的车型
创维推自主研发OLED电视 屏幕是BOE的芯片来自华为
11月16日,创维今天联合京东方、海思在深圳总部推出了首台自主研发的OLED电视M1系列产品。 本次创维和BOE联合发布的M1系列新品为55英寸4K机型,除了拥有OLED标杆式的超薄时尚设计以外,处理器部分采用了华为海思芯片,屏幕则得到了BOE(京东方)的支持,实现了核心部件全自主研发,告别了长期以来高端OLED屏幕主要依赖国外厂商的情况。 据悉,创维自主研发OLED电视屏幕部分的合作方BOE(京东方)刚刚在上个月宣布在四川绵阳投资建立了第六代AMOLED生产线,再加上此前鄂尔多斯5.5代线和成都的6代线,京东方已经拥有三条OLED生产线。 虽然OLED面板在良品率和寿命的问题上一直是业界争论的焦点,但是随着显示技术的发展
[家用电子]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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