此篇介绍使用硬件SPI1轮询模式来实现驱动OLED显示屏 硬件连接 GND —— GND VCC —— 3.3V DO —— PA5
DI —— PA7
RES —— PB1
DC —— PB0
CS —— PA4 软件代码 SPI1配置: //SPI初始化
void SPI_Initial(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIO clock for SPI_MASTER */
RCC_AHBPeriphClk_Enable(SPI_MASTER_GPIO_CLK | RCC_SPI_CS, ENABLE);
/* Enable SPI_MASTER Periph clock */
RCC_APBPeriphClk_Enable2(SPI_MASTER_CLK, ENABLE);
//SPI SCK MOSI MISO 复用
SPI_AF_SCK;
SPI_AF_MISO;
SPI_AF_MOSI;
//GPIO_CS初始化设置
GPIO_InitStructure.Pins = PIN_SPI_CS;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.IT = GPIO_IT_NONE;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(PORT_SPI_CS, &GPIO_InitStructure);
SPI_CS_DISABLE;
/* Configure SPI_MASTER pins: SCK and MOSI ---------------------------------*/
/* Configure SCK and MOSI pins as Alternate Function Push Pull */
GPIO_InitStructure.Pins = SPI_MASTER_PIN_SCK | SPI_MASTER_PIN_MOSI;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_Init(SPI_MASTER_GPIO, &GPIO_InitStructure);
/* Configure MISO pin as Input Floating */
GPIO_InitStructure.Pins = SPI_MASTER_PIN_MISO;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_Init(SPI_MASTER_GPIO, &GPIO_InitStructure);
/* SPI_MASTER configuration ------------------------------------------------*/
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 双线全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 帧数据长度为8bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 时钟空闲电平为高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 第2个边沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 片选信号由SSI寄存器控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; // 波特率为PCLK的128分频,16M/128=125000
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 最高有效位 MSB 收发在前
SPI_InitStructure.SPI_Speed = SPI_Speed_Low; // 低速SPI
SPI_Init(SPI_MASTER, &SPI_InitStructure);
/* Enable SPI_MASTER */
SPI_Cmd(SPI_MASTER, ENABLE);
}
OLED代码: //向设备写控制命令
static void OLED_Write_CMD(unsigned char cmd)
{
#ifdef HW_I2C
unsigned char tx_buf[BUF_SIZE] = {0x00, cmd};
I2C_MasterSendDataToSlave(CW_I2C2, tx_buf, BUF_SIZE);
#endif
#ifdef SW_I2C
I2C_Start();
I2C_Send_Byte(0x78);
I2C_Wait_Ack();
I2C_Send_Byte(0x00);
I2C_Wait_Ack();
I2C_Send_Byte(cmd);
I2C_Wait_Ack();
I2C_Stop();
#endif
#ifdef HW_SPI
OLED_CS_LOW;
OLED_DC_LOW;
while (SPI_GetFlagStatus(SPI_MASTER, SPI_FLAG_TXE) == RESET);
SPI_SendData(SPI_MASTER, cmd);
while (SPI_GetFlagStatus(SPI_MASTER, SPI_FLAG_RXNE) == RESET);
SPI_ReceiveData(SPI_MASTER);
OLED_CS_HIGH;
#endif
#ifdef SW_SPI
OLED_CS_LOW;
OLED_DC_LOW;
SPI_WriteByte(cmd);
OLED_CS_HIGH;
#endif
}
//向设备写数据
static void OLED_Write_Date(unsigned char date)
{
#ifdef HW_I2C
unsigned char tx_buf[BUF_SIZE] = {0x40, date};
I2C_MasterSendDataToSlave(CW_I2C2, tx_buf, BUF_SIZE);
#endif
#ifdef SW_I2C
I2C_Start();
I2C_Send_Byte(0x78);
I2C_Wait_Ack();
I2C_Send_Byte(0x40);
I2C_Wait_Ack();
I2C_Send_Byte(date);
I2C_Wait_Ack();
I2C_Stop();
#endif
#ifdef HW_SPI
OLED_CS_LOW;
OLED_DC_HIGH;
while (SPI_GetFlagStatus(SPI_MASTER, SPI_FLAG_TXE) == RESET);
SPI_SendData(SPI_MASTER, date);
while (SPI_GetFlagStatus(SPI_MASTER, SPI_FLAG_RXNE) == RESET);
SPI_ReceiveData(SPI_MASTER);
OLED_CS_HIGH;
#endif
#ifdef SW_SPI
OLED_CS_LOW;
OLED_DC_HIGH;
SPI_WriteByte(date);
OLED_CS_HIGH;
#endif
}
//坐标设置
static void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_Write_CMD(0xB0 + y);
OLED_Write_CMD(((x & 0xF0) >> 4) | 0x10);
OLED_Write_CMD(x & 0x0F);
}
//开启OLED显示
static void OLED_Display_On(void)
{
OLED_Write_CMD(0x8D); //SET DCDC命令
OLED_Write_CMD(0x14); //DCDC ON
OLED_Write_CMD(0xAF); //DISPLAY ON
}
//关闭OLED显示
static void OLED_Display_Off(void)
{
OLED_Write_CMD(0x8D); //SET DCDC命令
OLED_Write_CMD(0x10); //DCDC OFF
OLED_Write_CMD(0xAE); //DISPLAY OFF
}
//OLED清屏
void OLED_Clear(void)
{
unsigned char cnt, count;
for(cnt = 0; cnt < 8; cnt++)
{
OLED_Write_CMD(0xB0 + cnt);
OLED_Write_CMD(0x00);
OLED_Write_CMD(0x10);
for(count = 0; count < 128; count++)
{
OLED_Write_Date(0x00);
}
}
}
//OLED清行
void OLED_Clear_Row(unsigned char n)
{
unsigned char count;
OLED_Write_CMD(0xB0 + n);
OLED_Write_CMD(0x00);
OLED_Write_CMD(0x10);
for(count = 0; count < 128; count++)
{
OLED_Write_Date(0x00);
}
}
//OLED填满屏幕
void OLED_Fill(void)
{
unsigned char cnt, count;
for(cnt = 0; cnt < 8; cnt++)
{
OLED_Write_CMD(0xB0 + cnt); //设置页地址(0~7)
OLED_Write_CMD(0x00); //设置显示位置—列低地址
OLED_Write_CMD(0x10); //设置显示位置—列高地址
for(count = 0; count < 128; count++)
{
OLED_Write_Date(0x01);
}
}
}
//指定位置显示一个字符
//x:0~127
//y:0~63
//chr:字符
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr, unsigned char size)
{
unsigned char offset = 0, cnt = 0;
offset = chr - ' '; //计算偏移量
if(x > 128 - 1)
{
x = 0;
y = y + 2;
}
if(size == 16)
{
OLED_Set_Pos(x, y);
for(cnt = 0; cnt < 8; cnt++)
{
OLED_Write_Date(F8x16[offset * 16 + cnt]);
}
OLED_Set_Pos(x, y + 1);
for(cnt = 0; cnt < 8; cnt++)
{
OLED_Write_Date(F8x16[offset * 16 + cnt + 8]);
}
}
else
{
OLED_Set_Pos(x, y);
for(cnt = 0; cnt < 6; cnt++)
{
OLED_Write_Date(F6x8[offset][cnt]);
}
}
}
unsigned int oled_pow(unsigned char m, unsigned char n)
{
unsigned int result = 1;
while(n--)
{
result *= m;
}
return result;
}
//指定位置显示一个数字
//x,y:起点坐标
//num:数值(0~4294967295)
//len:数字的位数
//size:字体大小
//mode:模式 0,填充模式;1,叠加模式
void OLED_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len, unsigned char size)
{
unsigned char cnt, temp;
unsigned char show = 0;
for(cnt = 0; cnt < len; cnt++)
{
temp = (num / oled_pow(10, len - cnt - 1)) % 10;
if(show == 0 && cnt < (len - 1))
{
if(temp == 0)
{
OLED_ShowChar(x + (size / 2) * cnt, y, ' ', size);
continue;
}
else
{
show = 1;
}
}
OLED_ShowChar(x + (size / 2) * cnt, y, temp + '0', size);
}
}
//指定位置显示字符串
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *chr, unsigned char size)
{
unsigned char cnt = 0;
while(chr[cnt] != '\0')
{
OLED_ShowChar(x, y, chr[cnt], size);
x += 8;
if(x > 120)
{
x = 0;
y += 2;
}
cnt++;
}
}
//显示汉字
void OLED_ShowCHinese(unsigned char x, unsigned char y, unsigned char no)
{
unsigned char cnt, addr = 0;
OLED_Set_Pos(x, y);
for(cnt = 0; cnt < 16; cnt++)
{
OLED_Write_Date(Hzk[2 * no][cnt]);
addr++;
}
OLED_Set_Pos(x, y + 1);
for(cnt = 0; cnt < 16; cnt++)
{
OLED_Write_Date(Hzk[2 * no + 1][cnt]);
addr++;
}
}
//显示图片
/*
@brief 显示图片
@param x0:起始列地址
y0:起始页地址
x1:终止列地址
y1:终止页地址
BMP[]:存放图片代码的数组
@retval 无
*/
void OLED_DrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[])
{
unsigned int j = 0; //定义变量
unsigned char x, y; //定义变量
if(y1 % 8 == 0)
{
y = y1 / 8; //判断终止页是否为8的整数倍
}
else
{
y = y1 / 8 + 1;
}
for(y = y0; y < y1; y++) //从起始页开始,画到终止页
{
OLED_Set_Pos(x0, y); //在页的起始列开始画
for(x = x0; x < x1; x++) //画x1 - x0 列
{
OLED_Write_Date(BMP[j++]); //画图片的点
}
}
}
//显示动图
/*
@brief 显示动图
@param x0:起始列地址
y0:起始页地址
x1:终止列地址
y1:终止页地址
k: 帧个数
m: 单帧数组大小
BMP[][m]:存放动图代码的数组
@retval 无
*/
void OLED_DrawGIF(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char k, int m, const unsigned char GIF[][m])
{
unsigned int j = 0; //定义变量
unsigned char x, y, i; //定义变量
if(y1 % 8 == 0)
{
y = y1 / 8; //判断终止页是否为8的整数倍
}
else
{
y = y1 / 8 + 1;
}
for (i = 0; i < k; i++) //从第一帧开始画
{
j = 0;
for(y = y0; y < y1; y++) //从起始页开始,画到终止页
{
OLED_Set_Pos(x0, y); //在页的起始列开始画
for(x = x0; x < x1; x++) //画x1 - x0 列
{
OLED_Write_Date(GIF[i][j++]); //画图片的点
}
}
//Delay_Ms(80);
}
}
#if defined SW_SPI || defined HW_SPI
//SPI驱动方式DC、RES引脚初始化
void OLED_SPI_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//根据GPIO组初始化GPIO时钟
RCC_AHBPeriphClk_Enable( RCC_OLED_DC | RCC_OLED_RES, ENABLE);
//GPIO_DC初始化设置
GPIO_InitStructure.Pins = PIN_OLED_DC;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.IT = GPIO_IT_NONE;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(PORT_OLED_DC, &GPIO_InitStructure);
//GPIO_RES初始化设置
GPIO_InitStructure.Pins = PIN_OLED_RES;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.IT = GPIO_IT_NONE;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(PORT_OLED_RES, &GPIO_InitStructure);
OLED_RES_LOW;
Delay_Ms(200);
OLED_RES_HIGH;
}
#endif
//OLED初始化
void OLED_Init(void)
{
#ifdef SW_I2C
I2C_Init();
#endif
#ifdef HW_I2C
I2C_Init();
#endif
#ifdef SW_SPI
SPI_Initial();
OLED_SPI_GPIO_Init();
#endif
#ifdef HW_SPI
SPI_Initial();
OLED_SPI_GPIO_Init();
#endif
Delay_Ms(200);
OLED_Write_CMD(0xAE); //display off
OLED_Write_CMD(0x00); //set low column address
OLED_Write_CMD(0x10); //set high column address
OLED_Write_CMD(0x40); //set start line address
OLED_Write_CMD(0xB0); //set page address
OLED_Write_CMD(0x81); //contract control
OLED_Write_CMD(0xFF); //128
OLED_Write_CMD(0xA1); //set segment remap
OLED_Write_CMD(0xA6); //normal / reverse
OLED_Write_CMD(0xA8); //set multiplex ratio(1 to 64)
OLED_Write_CMD(0x3F); //1/32 duty
OLED_Write_CMD(0xC8); //Com scan direction
OLED_Write_CMD(0xD3); //set display offset
OLED_Write_CMD(0x00); //
OLED_Write_CMD(0xD5); //set osc division
OLED_Write_CMD(0x80); //
OLED_Write_CMD(0xD8); //set area color mode off
OLED_Write_CMD(0x05); //
OLED_Write_CMD(0xD9); //Set Pre-Charge Period
OLED_Write_CMD(0xF1); //
OLED_Write_CMD(0xDA); //set com pin configuartion
OLED_Write_CMD(0x12); //
OLED_Write_CMD(0xDB); //set Vcomh
OLED_Write_CMD(0x30); //
OLED_Write_CMD(0x8D); //set charge pump enable
OLED_Write_CMD(0x14); //
OLED_Write_CMD(0xAF); //turn on oled panel
}
运行测试
测试代码
CW32F030CxTx_HW_SPI_OLED.zip
(261.26 KB)
|