ARM-SPI屏幕案例
学习目标
- 掌握移植方法
- 掌握调试方式
学习内容
需求
官方测试示例
选择对应的平台
测试示例中,找到芯片对应平台,我们选择的是STM32F407
修改例程
已知错误修改:
oled.h中类型未定义错误
#ifndef u8
#define u8 uint8_t
#endif#ifndef u16
#define u16 uint16_t
#endif#ifndef u32
#define u32 uint32_t
#endif
引脚定义修改:
oled.h中引脚定义修改
#define CLK_RCU RCC_AHB1Periph_GPIOA
#define CLK_PORT GPIOA
#define CLK_PIN GPIO_Pin_5#define MOSI_RCU RCC_AHB1Periph_GPIOA
#define MOSI_PORT GPIOB
#define MOSI_PIN GPIO_Pin_7#define DC_RCU RCC_AHB1Periph_GPIOA
#define DC_PORT GPIOB
#define DC_PIN GPIO_Pin_2#define CS1_RCU RCC_AHB1Periph_GPIOA
#define CS1_PORT GPIOA
#define CS1_PIN GPIO_Pin_3#define MISO_RCU RCC_AHB1Periph_GPIOA
#define MISO_PORT GPIOB
#define MISO_PIN GPIO_Pin_6#define CS2_RCU RCC_AHB1Periph_GPIOC
#define CS2_PORT GPIOA
#define CS2_PIN GPIO_Pin_5#define OLED_SCL_Clr() GPIO_ResetBits(CLK_PORT, CLK_PIN)//SCL
#define OLED_SCL_Set() GPIO_SetBits(CLK_PORT, CLK_PIN)#define OLED_SDA_Clr() GPIO_ResetBits(MOSI_PORT,MOSI_PIN)//SDA
#define OLED_SDA_Set() GPIO_SetBits(MOSI_PORT,MOSI_PIN)#define OLED_DC_Clr() GPIO_ResetBits(DC_PORT,DC_PIN)//DC
#define OLED_DC_Set() GPIO_SetBits(DC_PORT,DC_PIN)#define OLED_CS_Clr() GPIO_ResetBits(CS1_PORT,CS1_PIN)//CS1
#define OLED_CS_Set() GPIO_SetBits(CS1_PORT,CS1_PIN)#define OLED_READ_FS0() GPIO_ReadInputDataBit(MISO_PORT,MISO_PIN)//FS0#define OLED_ROM_CS_Clr() GPIO_ResetBits(CS2_PORT,CS2_PIN)//CS2
#define OLED_ROM_CS_Set() GPIO_SetBits(CS2_PORT,CS2_PIN)
初始化逻辑修改:
oled.c的OLED_Init函数修改
GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(CLK_RCU,ENABLE);//使能A端口时钟
GPIO_InitStructure.GPIO_Pin = CLK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(CLK_PORT, &GPIO_InitStructure); RCC_AHB1PeriphClockCmd(CLK_RCU,ENABLE);
GPIO_InitStructure.GPIO_Pin = MOSI_PIN;
GPIO_Init(MOSI_PORT, &GPIO_InitStructure);RCC_AHB1PeriphClockCmd(DC_RCU,ENABLE);
GPIO_InitStructure.GPIO_Pin = DC_PIN;
GPIO_Init(DC_PORT, &GPIO_InitStructure);RCC_AHB1PeriphClockCmd(CS1_RCU,ENABLE);
GPIO_InitStructure.GPIO_Pin = CS1_PIN;
GPIO_Init(CS1_PORT, &GPIO_InitStructure);RCC_AHB1PeriphClockCmd(CS2_RCU,ENABLE);
GPIO_InitStructure.GPIO_Pin = CS2_PIN;
GPIO_Init(CS2_PORT, &GPIO_InitStructure);RCC_AHB1PeriphClockCmd(MISO_RCU,ENABLE);
GPIO_InitStructure.GPIO_Pin = MISO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(MISO_PORT, &GPIO_InitStructure); //初始化GPIOA// 全部拉高
GPIO_SetBits(CLK_PORT, CLK_PIN);
GPIO_SetBits(MOSI_PORT, MOSI_PIN);
GPIO_SetBits(DC_PORT, DC_PIN);
GPIO_SetBits(CS1_PORT, CS1_PIN);
GPIO_SetBits(CS2_PORT, CS2_PIN);
烧录测试
STM32自己环境
切换自己的环境,进行测试。
- 拷贝oled文件
- 拷贝main中的核心逻辑
- 修改不兼容的api
完整代码
oled.h
#ifndef __OLED_H
#define __OLED_H #include "stm32f4xx.h"
#include "systick.h"//SCL=SCLK
//SDA=MOSI
//DC=DC
//CS=CS1
//FS0=MOSI
//CS2=CS2#ifndef u8
#define u8 uint8_t
#endif#ifndef u16
#define u16 uint16_t
#endif#ifndef u32
#define u32 uint32_t
#endif//-----------------OLED端口定义----------------
#define CLK_RCU RCC_AHB1Periph_GPIOA
#define CLK_PORT GPIOA
#define CLK_PIN GPIO_Pin_5#define MOSI_RCU RCC_AHB1Periph_GPIOA
#define MOSI_PORT GPIOB
#define MOSI_PIN GPIO_Pin_7#define DC_RCU RCC_AHB1Periph_GPIOA
#define DC_PORT GPIOB
#define DC_PIN GPIO_Pin_2#define CS1_RCU RCC_AHB1Periph_GPIOA
#define CS1_PORT GPIOA
#define CS1_PIN GPIO_Pin_3#define MISO_RCU RCC_AHB1Periph_GPIOA
#define MISO_PORT GPIOB
#define MISO_PIN GPIO_Pin_6#define CS2_RCU RCC_AHB1Periph_GPIOC
#define CS2_PORT GPIOA
#define CS2_PIN GPIO_Pin_5#define OLED_SCL_Clr() GPIO_ResetBits(CLK_PORT, CLK_PIN)//SCL
#define OLED_SCL_Set() GPIO_SetBits(CLK_PORT, CLK_PIN)#define OLED_SDA_Clr() GPIO_ResetBits(MOSI_PORT,MOSI_PIN)//SDA
#define OLED_SDA_Set() GPIO_SetBits(MOSI_PORT,MOSI_PIN)#define OLED_DC_Clr() GPIO_ResetBits(DC_PORT,DC_PIN)//DC
#define OLED_DC_Set() GPIO_SetBits(DC_PORT,DC_PIN)#define OLED_CS_Clr() GPIO_ResetBits(CS1_PORT,CS1_PIN)//CS1
#define OLED_CS_Set() GPIO_SetBits(CS1_PORT,CS1_PIN)#define OLED_READ_FS0() GPIO_ReadInputDataBit(MISO_PORT,MISO_PIN)//FS0#define OLED_ROM_CS_Clr() GPIO_ResetBits(CS2_PORT,CS2_PIN)//CS2
#define OLED_ROM_CS_Set() GPIO_SetBits(CS2_PORT,CS2_PIN)#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据void OLED_ColorTurn(u8 i);
void OLED_DisplayTurn(u8 i);
void OLED_WR_Byte(u8 dat,u8 cmd);
void OLED_Clear(void);
void OLED_address(u8 x,u8 y);
void OLED_Display_128x64(u8 *dp);
void OLED_Display_16x16(u8 x,u8 y,u8 *dp);
void OLED_Display_8x16(u8 x,u8 y,u8 *dp);
void OLED_Display_5x7(u8 x,u8 y,u8 *dp);
void Send_Command_to_ROM(u8 dat);
u8 Get_data_from_ROM(void);
void OLED_get_data_from_ROM(u8 addrHigh,u8 addrMid,u8 addrLow,u8 *pbuff,u8 DataLen);
void OLED_Display_GB2312_string(u8 x,u8 y,u8 *text);
void OLED_Display_string_5x7(u8 x,u8 y,u8 *text);
void OLED_ShowNum(u8 x,u8 y,float num,u8 len);
void OLED_Init(void);
#endif
oled.c
#include "oled.h"
#include "stdlib.h"//反显函数
void OLED_ColorTurn(u8 i)
{if(i==0){OLED_WR_Byte(0xA6,OLED_CMD);//正常显示}if(i==1){OLED_WR_Byte(0xA7,OLED_CMD);//反色显示}
}//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{if(i==0){OLED_WR_Byte(0xC8,OLED_CMD);//正常显示OLED_WR_Byte(0xA1,OLED_CMD);}if(i==1){OLED_WR_Byte(0xC0,OLED_CMD);//反转显示OLED_WR_Byte(0xA0,OLED_CMD);}
}//开启OLED显示
void OLED_DisPlay_On(void)
{OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}//关闭OLED显示
void OLED_DisPlay_Off(void)
{OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
}//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{ u8 i; if(cmd)OLED_DC_Set();else OLED_DC_Clr(); OLED_CS_Clr();for(i=0;i<8;i++){ OLED_SCL_Clr();if(dat&0x80)OLED_SDA_Set();else OLED_SDA_Clr();OLED_SCL_Set();dat<<=1; } OLED_CS_Set();OLED_DC_Set();
}//清屏函数
void OLED_Clear(void)
{u8 i,n;for(i=0;i<8;i++){OLED_WR_Byte(0xb0+i,OLED_CMD);//设置页地址OLED_WR_Byte(0x10,OLED_CMD); //设置列地址的高4位OLED_WR_Byte(0x00,OLED_CMD); //设置列地址的低4位for(n=0;n<128;n++){OLED_WR_Byte(0x00,OLED_DATA);//清除所有数据}}
}//设置起始地址
void OLED_address(u8 x,u8 y)
{OLED_WR_Byte(0xb0+y,OLED_CMD); //设置页地址OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD); //设置列地址的高4位OLED_WR_Byte((x&0x0f),OLED_CMD); //设置列地址的低4位
}//显示128x64点阵图像
void OLED_Display_128x64(u8 *dp)
{u8 i,j;for(i=0;i<8;i++){OLED_address(0,i);for(j=0;j<128;j++){OLED_WR_Byte(*dp,OLED_DATA); //写数据到OLED,每写完一个8位的数据后列地址自动加1dp++;}}
}//显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标
void OLED_Display_16x16(u8 x,u8 y,u8 *dp)
{u8 i,j;for(j=0;j<2;j++)