在裸板下使用 SPI 的話,有兩種方法可選: 1. 使用 IO 口模擬 SPI 進行操作 2. 使用 SPI 控制器進行操作 這裡我們選用控制器的方式,簡單方便。 初始化 SPI ~~~~ static void SPIControllerInit(void) { / 設置頻率 / SPPRE0 = ...
在裸板下使用 SPI 的話,有兩種方法可選:
- 使用 IO 口模擬 SPI 進行操作
- 使用 SPI 控制器進行操作
這裡我們選用控制器的方式,簡單方便。
初始化 SPI
static void SPIControllerInit(void)
{
/* 設置頻率 */
SPPRE0 = 2;
SPPRE1 = 2;
/* 配置 SPI */
SPCON0 = (1<<4) | (1<<3);
SPCON1 = (1<<4) | (1<<3);
}
如手冊所示,頻率配置公式如下:
Baud rate = PCLK / 2 / (Prescaler value + 1)
PCLK = 50MHZ
設置 SPPREn = 2,符合 OLED 的頻率要求。
配置 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 種操作介面可以選擇,如圖所示:
Different MCU mode can be set by hardware selection on BS[2:0] pins.
可以通過 BS[2:0] 來選擇模式,如下圖所示:
參照如下流程圖寫出 OLED 的初始化程式:
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]);
}
頁模式下定位方法:
即:
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 的驅動及應用程式。