SPI_OLED模块操作方法

一、硬件

1.1 硬件资料

在这里插入图片描述

1.2 原理图

在这里插入图片描述

1.3 连接方式

请添加图片描述

二、OLED操作原理

在这里插入图片描述

要操作OLED,只需要使用spi接口发送数据,并不需要使用SPI接口读取数据。除此之外,还需要控制D/C引脚

  • 当D/C引脚是低电平时,是命令:比如复位、打开显示、设置地址
  • 当D/C引脚是高电平时,是数据:写入要显示的数据

2.1 显存和像素

OLED上有128*64个像素,每个像素只有2中状态:亮、灭。
在这里插入图片描述

OLED内部有显存GDDRAM(Graphic Display Data RAM):
在这里插入图片描述

显存中,每位对应一个像素,如下图所示:
在这里插入图片描述

2.2 显存寻址模式

OLED有三种寻址模式:

  • 页地址模式(Page addressing mode):每写入1个字节,行地址不变,列地址增1,列地址达到127后会从0开始
    在这里插入图片描述

  • 水平地址模式(Horizontal addressing mode):

    • 每写入1个字节,行地址不变,列地址增1
    • 列地址达到127后从0开始,行地址指向下一页
    • 列地址达到127、行地址达到7时,列地址和行地址都被复位为0,指向左上角
      在这里插入图片描述
  • 垂直地址模式(Vertical addressing mode):

    • 每写入1个字节,行地址增1,列地址不变
    • 行地址达到7后从0开始,列地址指向下一列
    • 列地址达到127、行地址达到7时,列地址和行地址都被复位为0,指向左上角
      在这里插入图片描述

2.3 具体操作

2.3.1 初始化

对于OLED的初始化,在参考手册中,列出了流程图:
在这里插入图片描述

2.3.2 设置地址

  • 设置地址模式,如果为页地址模式时,先写命令0x22,在写命令0x02,页地址模式是默认的,可以不设置。
    在这里插入图片描述

  • 设置页地址:有0~7页,想设置哪一页(n)就发出命令:0xB0|n
    在这里插入图片描述

  • 设置列地址:列地址范围是0~127,需要使用2个命令来设置列地址
    在这里插入图片描述

2.3.4 写入数据

让D/C引脚为高,发起SPI写操作就可以了。
DC引脚使用GPIO0_B5,在APP里直接控制DC引脚,无需在设备树里指定。
引脚号为 = 0 * 32 + 1 * 8 + 5 = 13

三、在OLED上显示文字

3.1 设备树配置

&spi0 {
    oled: oled@00{
        compatible = "spidev";
        reg = <0>;
        spi-max-frequency = <10000000>;
        status="okay";
    };
};

3.2 编写代码

// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <linux/types.h>
#include <linux/spi/spidev.h>

#include "font.h"

#define OLED_CMD  0
#define OLED_DATA 1

static int fd_spidev;
static int dc_pin_num;

void dc_pin_init(int number)
{
        char cmd[100];

        dc_pin_num = number;

        sprintf(cmd, "echo %d > /sys/class/gpio/export", dc_pin_num);
        system(cmd);

        sprintf(cmd, "echo out > /sys/class/gpio/gpio%d/direction", dc_pin_num);
        system(cmd);
}

void oled_set_dc_pin(int val)
{
        char cmd[100];
        sprintf(cmd, "echo %d > /sys/class/gpio/gpio%d/value", val, dc_pin_num);
        system(cmd);
}

void spi_write_datas(unsigned char *buf, int len)
{
        write(fd_spidev, buf, len);
}

void oled_write_cmd_data(unsigned char uc_data, unsigned char uc_cmd)
{
        unsigned char uc_read = 0;
        if(uc_cmd == 0) {
                oled_set_dc_pin(0);
        } else {
                oled_set_dc_pin(1);
        }
        spi_write_datas(&uc_data, 1);
}

int oled_init(void)
{
        oled_write_cmd_data(0xae, OLED_CMD);

        oled_write_cmd_data(0x00, OLED_CMD);
        oled_write_cmd_data(0x10, OLED_CMD);

        oled_write_cmd_data(0x40, OLED_CMD);

        oled_write_cmd_data(0xb0, OLED_CMD);

        oled_write_cmd_data(0x81, OLED_CMD);
        oled_write_cmd_data(0x66, OLED_CMD);

        oled_write_cmd_data(0xa1, OLED_CMD);

        oled_write_cmd_data(0xa6, OLED_CMD);

        oled_write_cmd_data(0xa8, OLED_CMD);
        oled_write_cmd_data(0x3f, OLED_CMD);

        oled_write_cmd_data(0xc8, OLED_CMD);

        oled_write_cmd_data(0xd3, OLED_CMD);
        oled_write_cmd_data(0x00, OLED_CMD);

        oled_write_cmd_data(0xd5, OLED_CMD);
        oled_write_cmd_data(0x80, OLED_CMD);

        oled_write_cmd_data(0xd9, OLED_CMD);
        oled_write_cmd_data(0x1f, OLED_CMD);

        oled_write_cmd_data(0xda, OLED_CMD);
        oled_write_cmd_data(0x12, OLED_CMD);

        oled_write_cmd_data(0xdb, OLED_CMD);
        oled_write_cmd_data(0x30, OLED_CMD);

        oled_write_cmd_data(0x8d, OLED_CMD);
        oled_write_cmd_data(0x14, OLED_CMD);

        oled_write_cmd_data(0xaf, OLED_CMD);

        return 0;
}

void OLED_DIsp_Set_Pos(int x, int y)
{
        oled_write_cmd_data(0xb0+y, OLED_CMD);
        oled_write_cmd_data((x&0x0f), OLED_CMD);
        oled_write_cmd_data(((x&0xf0)>>4)|0x10, OLED_CMD);
}

void OLED_DIsp_Char(int x, int y, unsigned char c)
{
        int i=0;
        const unsigned char *dots = oled_asc2_8x16[ c - ' '];

        OLED_DIsp_Set_Pos(x, y);
        for(i=0;i<8;i++) {
                oled_write_cmd_data(dots[i], OLED_DATA);
        }

        OLED_DIsp_Set_Pos(x, y+1);
        for(i=0;i<8;i++) {
                oled_write_cmd_data(dots[i+8], OLED_DATA);
        }
}

void OLED_DIsp_String(int x, int y, char *str)
{
        unsigned char j=0;
        while(str[j]) {
                OLED_DIsp_Char(x, y, str[j]);
                x += 8;
                if(x > 127) {
                        x = 0;
                        y += 2;
                }
                j++;
        }
}

void OLED_DIsp_Test(void)
{
        int i;

        OLED_DIsp_String(0, 0, "wiki.100ask.net");
        OLED_DIsp_String(0, 2, "book.100ask.net");
        OLED_DIsp_String(0, 4, "bbs.100ask.net");

}

/* spi_oled /dev/spidevB.D */
int main(int argc, char **argv)
{
        int dc_pin;

        if(argc != 3) {
                printf("Usage: %s </dev/spidevB.D> <DC_pin_number>\n", argv[0]);
                return -1;
        }

        fd_spidev = open(argv[1], O_RDWR);
        if(fd_spidev < 0) {
                printf("open %s failed\n", argv[1]);
                return -1;
        }

        dc_pin = strtoul(argv[2], NULL, 0);
        dc_pin_init(dc_pin);

        oled_init();

        OLED_DIsp_Test();

        close(fd_spidev);
        return 0;
}

最后效果


[root@firefly-rk3288:/home/picture/spi]# ./spidev-oled /dev/spidev0.0 13
[root@firefly-rk3288:/home/picture/spi]#

请添加图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

习惯就好zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值