硬件说明
- A5 : SCK
- A7 :SDA(MOSI)
- A3 :RST
- A4 : D/C
- VCC : 3.3v
- GND :GND
SPI 说明
- SPI 是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口
- SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)
- 1)SDO/MOSI – 主设备数据输出,从设备数据输入;
- (2)SDI/MISO – 主设备数据输入,从设备数据输出;
- (3)SCLK – 时钟信号,由主设备产生;
- (4)CS/SS – 从设备使能信号,由主设备控制。当有多个从设备的时候,因为每个从设 备上都有一个片选引脚接入到主设备机中,当我们的主设备和某个从设备通信时将需要将从设备对应的片选引脚电平拉低或者是拉高。
- 我们SPI通信有4种不同的模式,不同的从设备可能在出厂是就是配置为某种模式,这是不能改变的;但我们的通信双方必须是工作在同一模式下,所以我们可以对我们的主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来控制我们主设备的通信模
易错点
- 国民技术 SPI 的SPI接口很清楚,但配置SPI时,对 CPOL、CPHA理解时,则会通讯不上
- SSD1306的SPI 配置需要 配置为 CPOL=1 CPHA=1才行
最终代码如下
- 驱动头文件 ssd1306_spi.h
#ifndef _INCLUDE_SSD1306_SPI_H_
#define _INCLUDE_SSD1306_SPI_H_
#include "n32l43x.h"
#include "n32l43x_conf.h"
#define SSD1306_Clear() SSD1306_Fill(0xff)
void SSD1306_WriteData(uint8_t uiData);
void SSD1306_SetPosition(uint8_t uiColumn, uint8_t uiPage);
void SSD1306_Fill(uint8_t uiByte);
void SSD1306_Initialize(void);
#endif
#endif
- main 调用
#include "ssd1306_spi.h"
int main(void)
{
SSD1306_Initialize();
while (1)
{
}
}
}
- 驱动代码 ssd1306_spi.c
#include "ssd1306_spi.h"
// RST
#define SPI_SSD1306_RST_LOW() GPIO_ResetBits(GPIOA, GPIO_PIN_3)
#define SPI_SSD1306_RST_HIGH() GPIO_SetBits(GPIOA, GPIO_PIN_3)
// DC
#define SPI_SSD1306_DC_LOW() GPIO_ResetBits(GPIOA, GPIO_PIN_4)
#define SPI_SSD1306_DC_HIGH() GPIO_SetBits(GPIOA, GPIO_PIN_4)
#define SPI_SSD1306_MODE_CMD() SPI_SSD1306_DC_LOW()
#define SPI_SSD1306_MODE_DAT() SPI_SSD1306_DC_HIGH()
static void SSD1306_InitializeGPIO(void);
static void SSD1306_InitializeSPI(void);
static void SSD1306_WriteByte(uint8_t uiData);
void SSD1306_InitializeGPIO(void)
{
/* Enable peripheral clocks --------------------------------------------------*/
/* GPIOA clock enable */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_AFIO, ENABLE);
/* SPI1*/
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1, ENABLE);
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
/* Configure SPI1 pins: SCK, MISO and MOSI ---------------------------------*/
/* Confugure SCK and MOSI pins as Alternate Function Push Pull */
GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
// RST / DC
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_3 | GPIO_PIN_4;
GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}
/*****************************************************************************/
/** Function Name: SSD1306_InitializeSPI. **/
/** Purpose: Initialize hardware SPI controler for OLED. **/
/** Params: None. **/
/** Return: None. **/
/*****************************************************************************/
void SSD1306_InitializeSPI(void)
{
SPI_InitType SPI_InitStructure;
SPI_InitStructure.DataDirection = SPI_DIR_SINGLELINE_TX;
SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* Enable SPI1 */
SPI_Enable(SPI1, ENABLE);
}
/*****************************************************************************/
/** Function Name: SSD1306_WriteByte. **/
/** Purpose: Simulate SPI communication timing to write a byte **/
/** to OLED controler. **/
/** Params: **/
/** @ uiByte: Byte will be write. **/
/** Return: None. **/
/** Limitation: None. **/
/*****************************************************************************/
void SSD1306_WriteByte(uint8_t uiByte)
{
/* Wait for SPI1 Tx buffer empty */
while (SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == RESET)
;
SPI_I2S_TransmitData(SPI1, uiByte);
}
/*****************************************************************************/
/* Function Name: SSD1306_WriteData. **/
/* Purpose: Write a data byte to OLED coltroler. **/
/* Resources: None. **/
/* Params: **/
/* @ uiData: One byte data will be write. **/
/* Return: None. **/
/* Limitation: None. **/
/*****************************************************************************/
void SSD1306_WriteData(uint8_t uiData)
{
/*----------------------------------*/
/* Process */
/*----------------------------------*/
SPI_SSD1306_MODE_DAT();
SSD1306_WriteByte(uiData);
}
/*****************************************************************************/
/* Function Name: SSD1306_WriteCommand. **/
/* Purpose: Write a command byte to OLED coltroler. **/
/* Resources: None. **/
/* Params: **/
/* @ uiCommand: One byte command will be write. **/
/* Return: None. **/
/* Limitation: None. **/
/*****************************************************************************/
void SSD1306_WriteCommand(uint8_t uiCommand)
{
/*----------------------------------*/
/* Process */
/*----------------------------------*/
SPI_SSD1306_MODE_CMD();
SSD1306_WriteByte(uiCommand);
}
/*****************************************************************************/
/* Function Name: SSD1306_SetPosition. **/
/* Purpose: Set current position of page and colomn. **/
/* Resources: None. **/
/* Params: **/
/* @ uiColumn: Position of column. **/
/* @ uiPage: Position of page. **/
/* Return: None. **/
/* Limitation: None. **/
/*****************************************************************************/
void SSD1306_SetPosition(uint8_t uiColumn, uint8_t uiPage)
{
/*----------------------------------*/
/* Process */
/*----------------------------------*/
SSD1306_WriteCommand(0xB0 | uiPage);
SSD1306_WriteCommand(((uiColumn & 0xF0) >> 4) | 0x10);
SSD1306_WriteCommand((uiColumn & 0x0F));
}
/*****************************************************************************/
/* Function Name: SSD1306_Fill. **/
/* Purpose: Fill screen. **/
/* Resources: None. **/
/* Params: **/
/* @uiByte: Filled data for each display unit. **/
/* Return: None. **/
/* Limitation: None. **/
/*****************************************************************************/
void SSD1306_Fill(uint8_t uiByte)
{
uint8_t y, x;
for (y = 0; y < 8; y++)
{
SSD1306_WriteCommand(0xb0 + y);
SSD1306_WriteCommand(0x01);
SSD1306_WriteCommand(0x10);
for (x = 0; x < 128; x++)
SSD1306_WriteData(uiByte);
}
}
/*****************************************************************************/
/** Function Name: SSD1306_Initialize **/
/** Purpose: Run the device initialize sequence. **/
/** Params: None. **/
/** Return: None. **/
/** Limitation: Initialize sequence must executed after power on 500ms. **/
/*****************************************************************************/
static void Delay(uint32_t count)
{
for (; count > 0; count--)
;
}
void SSD1306_Initialize(void)
{
/*----------------------------------*/
/* Process */
/*----------------------------------*/
// Initialize GPIO
SSD1306_InitializeGPIO();
SPI_SSD1306_RST_LOW();
Delay(0x1fffff);
// Initialize SPI control.
SSD1306_InitializeSPI();
/* Clear reset singal. */
SPI_SSD1306_RST_HIGH();
SSD1306_WriteCommand(0xae);
SSD1306_WriteCommand(0xae); //--turn off oled panel
SSD1306_WriteCommand(0x00); //---set low column address
SSD1306_WriteCommand(0x10); //---set high column address
SSD1306_WriteCommand(0x40); //--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
SSD1306_WriteCommand(0x81); //--set contrast control register
SSD1306_WriteCommand(0xcf); // Set SEG Output Current Brightness
SSD1306_WriteCommand(0xa0); //--Set SEG/Column Mapping 0xa0,0xa1
SSD1306_WriteCommand(0xc0); // Set COM/Row Scan Direction 0xc0,0xc8
SSD1306_WriteCommand(0xa6); //--set normal display
SSD1306_WriteCommand(0xa8); //--set multiplex ratio(1 to 64)
SSD1306_WriteCommand(0x3f); //--1/64 duty
SSD1306_WriteCommand(0xd3); //-set display offset Shift Mapping RAM Counter (0x00~0x3F)
SSD1306_WriteCommand(0x00); //-not offset
SSD1306_WriteCommand(0xd5); //--set display clock divide ratio/oscillator frequency
SSD1306_WriteCommand(0x80); //--set divide ratio, Set Clock as 100 Frames/Sec
SSD1306_WriteCommand(0xd9); //--set pre-charge period
SSD1306_WriteCommand(0xf1); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
SSD1306_WriteCommand(0xda); //--set com pins hardware configuration
SSD1306_WriteCommand(0x12);
SSD1306_WriteCommand(0xdb); //--set vcomh
SSD1306_WriteCommand(0x40); // Set VCOM Deselect Level
SSD1306_WriteCommand(0x20); //-Set Page Addressing Mode (0x00/0x01/0x02)
SSD1306_WriteCommand(0x02); //
SSD1306_WriteCommand(0x8d); //--set Charge Pump enable/disable
SSD1306_WriteCommand(0x14); //--set(0x10) disable
SSD1306_WriteCommand(0xa4); // Disable Entire Display On (0xa4/0xa5)
SSD1306_WriteCommand(0xa6); // Disable Inverse Display On (0xa6/a7)
SSD1306_WriteCommand(0xaf); //--turn on oled panel
SSD1306_Clear();
SSD1306_SetPosition(0, 0);
}
}
|