Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)

爱车的诺诺 2018-03-06

在裸板下使用 SPI 的话,有两种方法可选:

  1. 使用 IO 口模拟 SPI 进行操作
  2. 使用 SPI 控制器进行操作

这里我们选用控制器的方式,简单方便。

初始化 SPI

static void SPIControllerInit(void)
{
    /* 设置频率 */
    SPPRE0 = 2;
    SPPRE1 = 2;

    /* 配置 SPI */
    SPCON0 = (1<<4) | (1<<3);
    SPCON1 = (1<<4) | (1<<3);
}

Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)
如手册所示,频率配置公式如下:

Baud rate = PCLK / 2 / (Prescaler value + 1)

PCLK = 50MHZ

设置 SPPREn = 2,符合 OLED 的频率要求。

Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)
配置 SPCONn 寄存器如下:

/* [6:5] : 00, polling mode
    * [4]   : 1 = enable 
    * [3]   : 1 = master
    * [2]   : 0 = active high
    * [1]   : 0 = format A
    * [0]   : 0 = normal mode
    */

SPI 的发送与接收

/* 发送一字节 */
void SPISendByte(unsigned char val)
{
    /* 等待发送或接收 ready */
    while (!(SPSTA1 & 1));
    SPTDAT1 = val;    
}

/* 接收一字节 */
unsigned char SPIRecvByte(void)
{
    SPTDAT1 = 0xff;    
    
    /* 等待发送或接收 ready */
    while (!(SPSTA1 & 1));
    return SPRDAT1;    
}

OLED 初始化

我们选用的是 SSD1306 这款 OLED,根据手册说明,它有 4 种操作接口可以选择,如图所示:
Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)

Different MCU mode can be set by hardware selection on BS[2:0] pins.

可以通过 BS[2:0] 来选择模式,如下图所示:
Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)

参照如下流程图写出 OLED 的初始化程序:
Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)

void OLEDInit(void)
{
    /* 向 OLED 发命令以初始化 */
    OLEDWriteCmd(0xAE); /*display off*/ 
    OLEDWriteCmd(0x00); /*set lower column address*/ 
    OLEDWriteCmd(0x10); /*set higher column address*/ 
    OLEDWriteCmd(0x40); /*set display start line*/ 
    OLEDWriteCmd(0xB0); /*set page address*/ 
    OLEDWriteCmd(0x81); /*contract control*/ 
    OLEDWriteCmd(0x66); /*128*/ 
    OLEDWriteCmd(0xA1); /*set segment remap*/ 
    OLEDWriteCmd(0xA6); /*normal / reverse*/ 
    OLEDWriteCmd(0xA8); /*multiplex ratio*/ 
    OLEDWriteCmd(0x3F); /*duty = 1/64*/ 
    OLEDWriteCmd(0xC8); /*Com scan direction*/ 
    OLEDWriteCmd(0xD3); /*set display offset*/ 
    OLEDWriteCmd(0x00); 
    OLEDWriteCmd(0xD5); /*set osc division*/ 
    OLEDWriteCmd(0x80); 
    OLEDWriteCmd(0xD9); /*set pre-charge period*/ 
    OLEDWriteCmd(0x1f); 
    OLEDWriteCmd(0xDA); /*set COM pins*/ 
    OLEDWriteCmd(0x12); 
    OLEDWriteCmd(0xdb); /*set vcomh*/ 
    OLEDWriteCmd(0x30); 
    OLEDWriteCmd(0x8d); /*set charge pump enable*/ 
    OLEDWriteCmd(0x14); 

    OLEDSetPageAddrMode();

    OLEDClear();
    
    OLEDWriteCmd(0xAF); /*display ON*/    
}

设置为页显示模式:

static void OLEDSetPageAddrMode(void)
{
    OLEDWriteCmd(0x20);
    OLEDWriteCmd(0x02);
}

OLED 的分辨率为 128 x 64,每 8 行为一页,我们选用 8 x 16 的字模进行显示。

显示一个字符

void OLEDPutChar(int page, int col, char c)
{
    int i = 0;
    
    /* 得到字模 */
    const unsigned char *dots = oled_asc2_8x16[c - ' '];

    /* 发给 OLED */
    OLEDSetPos(page, col);
    
    /* 发出 8 字节数据 */
    for (i = 0; i < 8; i++)
        OLEDWriteDat(dots[i]);

    OLEDSetPos(page+1, col);
    
    /* 发出 8 字节数据 */
    for (i = 0; i < 8; i++)
        OLEDWriteDat(dots[i+8]);

}

页模式下定位方法:
Mini2440 通过 SPI 操作 OLED (裸板下使用 SPI 控制器)
即:

static void OLEDSetPos(int page, int col)
{
    OLEDWriteCmd(0xB0 + page);         /* page address */
    OLEDWriteCmd(col & 0xf);           /* Lower Column Start Address */
    OLEDWriteCmd(0x10 + (col >> 4));   /* Lower Higher Start Address */
}

下篇将写出在 Linux 下操作 OLED 的驱动及应用程序。

相关推荐