基于单片机的SPI接口OLED显示

描述

8.1 原理图分析

查看EK-RA6M4的原理图,如下图所示,该开发板上的MikroBus接口上有提供一个SPI接口。

SPI

根据原理图可知,SPI接口的四个引脚分别为:

功能 引脚
MISO P202
MOSI P203
SCK P204
CS P205

这里我们将在该SPI接口上连接 SPI OLED显示屏(3.3V供电),该OLED显示屏的接口定义如下:

引脚 功能 EK-RA6M4引脚
GND GND GND
VCC 3.3V 3.3V
D0 SCK P204
D1 MOSI P203
RST 复位(必须要控制 0->1) P207
DC Data(高电平)/Command(低电平) P206
CS 已接地,不用接

8.2 SPI接口配置

首先,在FSP配置中将SPI所用的两个口P203、P204配置成SPI模式。

SPI

然后,在FSP配置中将数据命令选择(DC)和两个引脚P206、P207配置成GPIO模式。

SPI

SPI

接着选择 Stacks ,点击 "New Stack" -> "Connectivity" -> "SPI(r_spi)" 添加 SPI 协议栈。

SPI

接下来设置SPI的相关配置,并重新生成代码。

SPI

SPI

  • 通过 Name 字段可以修改SPI中断的名称为 g_spi0_master,它将在IDE自动生成的文件 ra_gen/hal_data.c/h 中定义SPI操作相关的变量;
  • 通过 Channel 字段可以修改SPI的通道号,这里设置为0,下面的 Pins 将自动选择 P202、P203和 P204 这个引脚;
  • 在这里选择使能所有的SPI中断并设置优先级为2级别,在这里保持默认的SPI的工作模式、工作极性等;
  • 通过 Callback 字段设置SPI收发的中断回调函数 spi0_master_callback ,它将配置在 g_spi0_master_cfg 变量中,该函数需要我们自己实现;
  • 通过 Full or Transmit Only Mode 字段,我们设置SPI工作在 Transmit Only 模式,这是因为我们的MCU会给OLED发送数据,而不会接收;
  • 通过 Bitrate 字段,可以修改SPI的速率。事实上这里设置为默认的16MHz,OLED显示屏也是可以正常工作的。

6.3 源码修改

创建OLED操作相关的头文件 src/bsp_oled.h 如下:

#ifndef BSP_OLED_H_
#define BSP_OLED_H_

#include 

extern void OLED_Init(void);
extern void OLED_Show_Picture(void);

#endif /* BSP_OLED_H_ */

创建OLED操作相关的c文件 src/bsp_oled.c 如下:

#include 
#include 
#include "r_spi_api.h"
#include "hal_data.h"


#define RESET_VALUE         0x00

static volatile spi_event_t spi_event;    // Master Transfer Event completion flag

static fsp_err_t spi_init(void);
static fsp_err_t spi_write(uint8_t *data, uint32_t bytes);
static fsp_err_t spi_read(uint8_t *buf, uint32_t size);

static inline void OLED_WrDat(uint8_t data)
{
    R_BSP_PinWrite(oled_cd, BSP_IO_LEVEL_HIGH);
    spi_write(&data, 1);
}

static inline void OLED_WrCmd(uint8_t cmd)
{
    R_BSP_PinWrite(oled_cd, BSP_IO_LEVEL_LOW);
    spi_write(&cmd, 1);
}

void OLED_Init()
{
    if( FSP_SUCCESS != spi_init() )
        return ;

    printf("Reset and initial OLED panel
");

    R_BSP_PinWrite(oled_rst, BSP_IO_LEVEL_LOW);
    R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
    R_BSP_PinWrite(oled_rst, BSP_IO_LEVEL_HIGH);

    OLED_WrCmd(0xAE);   //display off
    OLED_WrCmd(0x20);    //Set Memory Addressing Mode
    OLED_WrCmd(0x10);    //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
    OLED_WrCmd(0xb0);    //Set Page Start Address for Page Addressing Mode,0-7
    OLED_WrCmd(0xc8);    //Set COM Output Scan Direction
    OLED_WrCmd(0x00);//---set low column address
    OLED_WrCmd(0x10);//---set high column address
    OLED_WrCmd(0x40);//--set start line address
    OLED_WrCmd(0x81);//--set contrast control register
    OLED_WrCmd(0x7f);
    OLED_WrCmd(0xa1);//--set segment re-map 0 to 127
    OLED_WrCmd(0xa6);//--set normal display
    OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
    OLED_WrCmd(0x3F);//
    OLED_WrCmd(0xa4);//0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    OLED_WrCmd(0xd3);//-set display offset
    OLED_WrCmd(0x00);//-not offset
    OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
    OLED_WrCmd(0xf0);//--set divide ratio
    OLED_WrCmd(0xd9);//--set pre-charge period
    OLED_WrCmd(0x22); //
    OLED_WrCmd(0xda);//--set com pins hardware configuration
    OLED_WrCmd(0x12);
    OLED_WrCmd(0xdb);//--set vcomh
    OLED_WrCmd(0x20);//0x20,0.77xVcc
    OLED_WrCmd(0x8d);//--set DC-DC enable
    OLED_WrCmd(0x14);//
    OLED_WrCmd(0xaf);//--turn on oled panel

    R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
}

/*+--------------------+
 *|   Show Picture API |
 *+--------------------+
 */
uint8_t picture_code[]=
{
0x00,0x06,0x0A,0xFE,0x0A,0xC6,0x00,0xE0,0x00,0xF0,0x00,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0xFE,0x7D,0xBB,0xC7,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xC7,0xBB,0x7D,
0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
0x0C,0xFE,0xFE,0x0C,0x08,0x20,0x60,0xFE,0xFE,0x60,0x20,0x00,0x00,0x00,0x78,0x48,
0xFE,0x82,0xBA,0xBA,0x82,0xBA,0xBA,0x82,0xBA,0xBA,0x82,0xBA,0xBA,0x82,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xFF,0xFF,0x00,0x00,0xFE,0xFF,0x03,
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xFF,0xFE,0x00,0x00,0x00,0x00,0xC0,0xC0,
0xC0,0x00,0x00,0x00,0x00,0xFE,0xFF,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
0xFF,0xFE,0x00,0x00,0xFE,0xFF,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xFF,
0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x0C,
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xFF,0xFF,0x00,0x00,0x00,0x00,0xE1,0xE1,
0xE1,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xFF,
0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x1F,
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x0F,0x00,0x00,0x0F,0x1F,0x18,
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x0F,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
0x1F,0x0F,0x00,0x00,0x0F,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,
0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xE2,0x92,0x8A,0x86,0x00,0x00,0x7C,0x82,0x82,0x82,0x7C,
0x00,0xFE,0x00,0x82,0x92,0xAA,0xC6,0x00,0x00,0xC0,0xC0,0x00,0x7C,0x82,0x82,0x82,
0x7C,0x00,0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0xC0,0xC0,0x00,0x7C,0x82,0x82,0x82,
0x7C,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x24,0xA4,0x2E,0x24,0xE4,0x24,0x2E,0xA4,0x24,0x00,0x00,0x00,0xF8,0x4A,0x4C,
0x48,0xF8,0x48,0x4C,0x4A,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x20,0x10,0x10,
0x10,0x10,0x20,0xC0,0x00,0x00,0xC0,0x20,0x10,0x10,0x10,0x10,0x20,0xC0,0x00,0x00,
0x00,0x12,0x0A,0x07,0x02,0x7F,0x02,0x07,0x0A,0x12,0x00,0x00,0x00,0x0B,0x0A,0x0A,
0x0A,0x7F,0x0A,0x0A,0x0A,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x40,0x40,
0x40,0x50,0x20,0x5F,0x80,0x00,0x1F,0x20,0x40,0x40,0x40,0x50,0x20,0x5F,0x80,0x00,
};

void OLED_Show_Picture(void)
{
  unsigned char x,y;
  unsigned int i=0;
  for(y=0;y<8;y++)
    {
      OLED_WrCmd(0xb0+y);
      OLED_WrCmd(0x00);
      OLED_WrCmd(0x10);
      for(x=0;x<128;x++)
        {
          OLED_WrDat(picture_code[i++]);
        }
    }
}

/*+--------------+
 *|   SPI API    |
 *+--------------+
 */
static fsp_err_t spi_init(void)
{
    fsp_err_t err = FSP_SUCCESS;

    err = R_SPI_Open (&g_spi0_master_ctrl, &g_spi0_master_cfg);
    if (FSP_SUCCESS != err)
    {
        printf("** R_SPI_Open API for SPI Master failed ** 
");
        return err;
    }

    return err;
}

void spi0_master_callback(spi_callback_args_t * p_args)
{
    if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
    {
        spi_event = SPI_EVENT_TRANSFER_COMPLETE;
    }
    else
    {
        spi_event = SPI_EVENT_TRANSFER_ABORTED;
    }
}

static inline fsp_err_t validate_spi_event(void)
{
    uint32_t local_time_out = UINT32_MAX;

    while( SPI_EVENT_TRANSFER_COMPLETE != spi_event )
    {
        --local_time_out;
        if(RESET_VALUE == local_time_out)
        {
            spi_event = (spi_event_t)RESET_VALUE;
            return FSP_ERR_TIMEOUT;
        }
    }

    if(spi_event == SPI_EVENT_TRANSFER_COMPLETE)
    {
        spi_event = (spi_event_t)RESET_VALUE;
        return FSP_SUCCESS;
    }

    spi_event = (spi_event_t)RESET_VALUE;
    return FSP_ERR_TRANSFER_ABORTED;
}

static fsp_err_t spi_write(uint8_t *data, uint32_t bytes)
{
    fsp_err_t err = FSP_SUCCESS;

    /* resetting call back event capture variable */
    spi_event = (spi_event_t)RESET_VALUE;

    err = R_SPI_Write(&g_spi0_master_ctrl, data, bytes, SPI_BIT_WIDTH_8_BITS);
    if(FSP_SUCCESS != err)
    {
        printf("Master R_SPI_Write() failed
");
        return err;
    }

    err = validate_spi_event();
    if (FSP_SUCCESS != err)
    {
        printf("** SPI write validate failed, err=%d ** 
", err);
        return err;
    }

    return FSP_SUCCESS;
}

__attribute__((unused)) static fsp_err_t spi_read(uint8_t *buf, uint32_t size)
{
    fsp_err_t err = FSP_SUCCESS;

    /* resetting call back event capture variable */
    spi_event = (spi_event_t)RESET_VALUE;

    err = R_SPI_Read(&g_spi0_master_ctrl, buf, size, SPI_BIT_WIDTH_8_BITS);
    if(FSP_SUCCESS != err)
    {
        printf("Master R_SPI_Write() failed
");
        return err;
    }

    err = validate_spi_event();
    if (FSP_SUCCESS != err)
    {
        printf("** SPI write validate failed, err=%d ** 
", err);
        return err;
    }

    return FSP_SUCCESS;
}

修改 src/hal_entry.c 源文件,在里面添加 OLED 初始化和显示的代码。

... ...
#include "bsp_oled.h"
... ...
void hal_entry(void)
{    
    ... ...

     OLED_Init();
    OLED_Show_Picture();

    while (1)
    {
    ... ...
}

8.4 编译运行

代码修改完成后,在开发板上编译运行。这时可以看到OLED上显示图片如下:

SPI

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分