OLED SH1108 STM32 8080接口实际使用
目录
之前有项目使用维信诺一款OLED 核心控制器为SH1108,一直埋头搞项目,没有实际做点记录查看SH1108数据手册,感觉这个图很好,把SH1108描述的很形象,这里贴出来
硬件部分
这里需要说明的是sh1108支持的接口很多,如下表所示,8080、6800的并口方式,也支持串行接口IIC/4线SPI/三线SPI
这里需要在原理图设计的时候,注意IM0/IM1/IM2三个管脚的电平选择
本文涉及的项目是车载用的LED屏幕,所以对空间要求小,屏幕有点大,就采用并口设计的方式,加快屏幕的刷新过程,很多设计都是采用IIC也是可以的,使用的接口线少,方便硬件布局布线
IIC一般针对屏幕小,设备尺寸小,采用的一种接口方式。
项目选择是用8080接口,采用IO模拟的方式进行SH1108通信,IM0/IM1/IM2三个管脚的电平选择
0、1、1
8080接口需要使用的信号新如下图所示
明显可以看出来使用数据线D0-D8,一次刷新可以填入8bit数据,加快数据的写入
项目使用的OLED屏屏为128 COM× 160 SEG,该屏幕有128 个column与20 个Page,每Page有8 Seg即一共160 Seg。
OLED和STM32的硬件连接,STM32使用外部晶振25Mhz,倍频到72Mhz。
原理图设计的时候需要注意的是
需要把上述表格中D0-D7分别连接到MCU PX0-PX7,这样一次赋值就可以将8bit数据写入
在固件库函数中调用如下函数
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
软件部分
关于stm32和OLED的管脚定义如下所列
这里定义如下宏定义,方便实现8080写时序
//------------OLED ------------------------------------------------------------------
#define OLED_SH1108_CS_PIN GPIO_Pin_1 /* PB.1 -------> OLED_CS */
#define OLED_SH1108_CS_GPIO_PORT GPIOB /* GPIOB */
#define OLED_SH1108_CS_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_SH1108_DC_PIN GPIO_Pin_13 /* PB.13 -------> OLED_A0 */
#define OLED_SH1108_DC_GPIO_PORT GPIOB /* GPIOB */
#define OLED_SH1108_DC_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_SH1108_WR_PIN GPIO_Pin_14 /* PB.14 -------> OLED_WR */
#define OLED_SH1108_WR_GPIO_PORT GPIOB /* GPIOB */
#define OLED_SH1108_WR_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_SH1108_RD_PIN GPIO_Pin_15 /* PB.15 -------> OLED_RD */
#define OLED_SH1108_RD_GPIO_PORT GPIOB /* GPIOB */
#define OLED_SH1108_RD_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_SH1108_RES_PIN GPIO_Pin_12 /* PB.12 -------> OLED_RES */
#define OLED_SH1108_RES_GPIO_PORT GPIOB /* GPIOB */
#define OLED_SH1108_RES_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_SH1108_D0_PIN GPIO_Pin_0 /* PC.0 -------> OLED_D0 */
#define OLED_SH1108_D0_GPIO_PORT GPIOC /* GPIOC */
#define OLED_SH1108_D0_GPIO_CLK RCC_APB2Periph_GPIOC
#define OLED_SH1108_D1_PIN GPIO_Pin_1 /* PC.1 -------> OLED_D1 */
#define OLED_SH1108_D1_GPIO_PORT GPIOC /* GPIOC */
#define OLED_SH1108_D1_GPIO_CLK RCC_APB2Periph_GPIOC
#define OLED_SH1108_D2_PIN GPIO_Pin_2 /* PC.2 -------> OLED_D2 */
#define OLED_SH1108_D3_PIN GPIO_Pin_3 /* PC.3 -------> OLED_D3 */
#define OLED_SH1108_D4_PIN GPIO_Pin_4 /* PC.4 -------> OLED_D4 */
#define OLED_SH1108_D5_PIN GPIO_Pin_5 /* PC.5 -------> OLED_D5 */
#define OLED_SH1108_D6_PIN GPIO_Pin_6 /* PC.6 -------> OLED_D6 */
#define OLED_SH1108_D7_PIN GPIO_Pin_7 /* PC.7 -------> OLED_D7 */
#define OLED_SH1108_XDATA_GPIO_PORT GPIOC /* GPIOC */
#define OLED_SH1108_XDATA_GPIO_CLK RCC_APB2Periph_GPIOC
#define OLED_SH1108_RES_LOW() GPIO_ResetBits(OLED_SH1108_RES_GPIO_PORT, OLED_SH1108_RES_PIN)
#define OLED_SH1108_RES_HIGH() GPIO_SetBits(OLED_SH1108_RES_GPIO_PORT, OLED_SH1108_RES_PIN)
#define OLED_SH1108_CS_LOW() GPIO_ResetBits(OLED_SH1108_CS_GPIO_PORT, OLED_SH1108_CS_PIN)
#define OLED_SH1108_CS_HIGH() GPIO_SetBits(OLED_SH1108_CS_GPIO_PORT, OLED_SH1108_CS_PIN)
#define OLED_SH1108_DC_LOW() GPIO_ResetBits(OLED_SH1108_DC_GPIO_PORT, OLED_SH1108_DC_PIN)
#define OLED_SH1108_DC_HIGH() GPIO_SetBits(OLED_SH1108_DC_GPIO_PORT, OLED_SH1108_DC_PIN)
#define OLED_SH1108_WR_LOW() GPIO_ResetBits(OLED_SH1108_WR_GPIO_PORT, OLED_SH1108_WR_PIN)
#define OLED_SH1108_WR_HIGH() GPIO_SetBits(OLED_SH1108_WR_GPIO_PORT, OLED_SH1108_WR_PIN)
#define OLED_SH1108_RD_LOW() GPIO_ResetBits(OLED_SH1108_RD_GPIO_PORT, OLED_SH1108_RD_PIN)
#define OLED_SH1108_RD_HIGH() GPIO_SetBits(OLED_SH1108_RD_GPIO_PORT, OLED_SH1108_RD_PIN)
#define OLED_SH1108_XDATA(x) GPIO_Write(OLED_SH1108_XDATA_GPIO_PORT, x)
//#define OLED_SH1108_XDATA(x) GPIOC->ODR=(GPIOC->ODR & 0xff00) | (x & 0x00FF)
#define OLED_SH1108_SCL_LOW() GPIO_ResetBits(OLED_SH1108_XDATA_GPIO_PORT, OLED_SH1108_D0_PIN)
#define OLED_SH1108_SCL_HIGH() GPIO_SetBits(OLED_SH1108_XDATA_GPIO_PORT, OLED_SH1108_D0_PIN)
#define OLED_SH1108_SI_LOW() GPIO_ResetBits(OLED_SH1108_XDATA_GPIO_PORT, OLED_SH1108_D1_PIN)
#define OLED_SH1108_SI_HIGH() GPIO_SetBits(OLED_SH1108_XDATA_GPIO_PORT, OLED_SH1108_D1_PIN)
这里为了速度将PC口单独连接到OLED的数据线上,这样可以加快操作OLED的读写速度,OLED_SH1108_XDATA这个宏定义就是针对上述数据方式添加的。
测试main函数,实现了OLED显示汉字和字符串,部分图案显示没有测试
/******************************************************************************
* 函数名称: main()
* 功能描述: OLED测试
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明:
* 修改日期 版本号 修改人 修改内容
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* 2013/02/22 V1.0.0.0
******************************************************************************/
INT32S main (void)
{
BSP_Init(); // 系统初始化
oled_sh1108_init_program();
OLED_ShowChinese(1, 20, 4, 1);//主
OLED_ShowChinese(93, 20, 5, 1);//副
while(1)
{
sprintf((char*)oled_display_buf," ");
oled_sh1108_show_string(61, 5, oled_display_buf, 12);
sprintf((char*)oled_display_buf,"%4.4d-%2.2d-%2.2d", 2022, 1, 1);
oled_sh1108_show_string(1, 5, oled_display_buf, 12);
sprintf((char*)oled_display_buf,"%2.2d:%2.2d:%2.2d", 10, 10, 10);
oled_sh1108_show_string(105, 5, oled_display_buf, 12);
oled_sh1108_refresh_gram();
}
return (0);
}
STM32内部缓存定义,每次更改该数据,一定时间,或者及时将该数据刷新
/* OLED的显存
* 存放格式如下.
* [0]0 1 2 3 ... 127
* [1]0 1 2 3 ... 127
* [2]0 1 2 3 ... 127
*
* [19]0 1 2 3 ... 127
*/
static unsigned char OLED_GRAM[128][20];
刷新缓存到OLED,该函数实现将缓存数据刷新到OLED
/******************************************************************************
* 函数名称: oled_sh1108_all_screen()
* 功能描述: 更新显存到LCD
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明:
* 修改日期 版本号 修改人 修改内容
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* 2013/02/22 V1.0.0.0
******************************************************************************/
void oled_sh1108_refresh_gram(void)
{
unsigned char i, j;
// for(i = 0 ; i < 8; i++)
// {
// OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
// OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
// OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
// for(n=0;n<128;n++)
// OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
// }
for(i = 0; i < 20; i++)
{
oled_sh1108_write_c(0xb0);
oled_sh1108_write_c(0x00 + i);
oled_sh1108_write_c(0x00);
oled_sh1108_write_c(0x11);
for(j = 0; j < 128; j++)
{
oled_sh1108_write_d(OLED_GRAM[j][i]);
}
}
}