注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
lugl4313820的个人空间 https://home.eeworld.com.cn/space-uid-1269709.html [收藏] [复制] [分享] [RSS]
日志

【ACM32G103RCT6】硬件SPI驱动sh1106OLED

已有 372 次阅读2024-1-23 13:13

【ACM32G103RCT6】spi驱动SH1106OLED

上篇是用模拟SPI实现了驱动,下面修改为硬件SPI来驱动。

其实驱动LCD最后配适的就是SPI的驱动与向SPI总结写入一个字节的的适配,了解了这个原理后,我们只需要修改如何修改spi的SCK、MOSI(因为此屏不需要读取数)这两个IO的驱动就行了。

为了兼容模拟与硬件,我们采用条件编译来实现,用宏定义如下:


#define H_SPI

1、修改初始化函数如下:

//OLED的初始化
void OLED_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;

	__HAL_RCC_GPIOA_CLK_ENABLE();
#ifdef H_SPI
		
		GPIO_InitStruct.Pin       = OLED_RES_PIN | OLED_DC_PIN | OLED_CS_PIN ;
    GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Drive     = GPIO_DRIVE_LEVEL3;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;

    HAL_GPIO_Init(OLED_PORT, &GPIO_InitStruct);
	
		GPIO_InitStruct.Pin = OLED_SCL_PIN | OLED_SDA_PIN;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		GPIO_InitStruct.Drive = GPIO_DRIVE_LEVEL3;
		GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	   /* Clear Pending Interrupt */
    NVIC_ClearPendingIRQ(SPI1_IRQn);
		/* Enable External Interrupt */
    NVIC_EnableIRQ(SPI1_IRQn);
		
		SPI_Handle.Instance                 = SPI1;
    SPI_Handle.Init.SPI_Mode            = SPI_MODE_MASTER;
    SPI_Handle.Init.SPI_Work_Mode       = SPI_WORK_MODE_0;
    SPI_Handle.Init.X_Mode              = SPI_1X_MODE;
    SPI_Handle.Init.First_Bit           = SPI_FIRSTBIT_MSB;
    SPI_Handle.Init.BaudRate_Prescaler  = SPI_BAUDRATE_PRESCALER_64;

    HAL_SPI_Init(&SPI_Handle);
#else
	  GPIO_InitStruct.Pin       = OLED_SCL_PIN | OLED_SDA_PIN | OLED_RES_PIN | OLED_DC_PIN | OLED_CS_PIN ;
    GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Drive     = GPIO_DRIVE_LEVEL3;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;

    HAL_GPIO_Init(OLED_PORT, &GPIO_InitStruct);
#endif
	OLED_RES_Clr();
	HAL_Delay(200);
	OLED_RES_Set();
	
	OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/ 
	OLED_WR_Byte(0x02,OLED_CMD); /*set lower column address*/ 
	OLED_WR_Byte(0x10,OLED_CMD); /*set higher column address*/ 
	OLED_WR_Byte(0x40,OLED_CMD); /*set display start line*/ 
	OLED_WR_Byte(0xB0,OLED_CMD); /*set page address*/
	OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/ 
	OLED_WR_Byte(0xcf,OLED_CMD); /*128*/ 
	OLED_WR_Byte(0xA1,OLED_CMD); /*set segment remap*/ 
	OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/ 
	OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/ 
	OLED_WR_Byte(0x3F,OLED_CMD); /*duty = 1/64*/ 
	OLED_WR_Byte(0xad,OLED_CMD); /*set charge pump enable*/ 
	OLED_WR_Byte(0x8b,OLED_CMD); /* 0x8B 内供 VCC */ 
	OLED_WR_Byte(0x33,OLED_CMD); /*0X30---0X33 set VPP 9V */ 
	OLED_WR_Byte(0xC8,OLED_CMD); /*Com scan direction*/ 
	OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/ 
	OLED_WR_Byte(0x00,OLED_CMD); /* 0x20 */ 
	OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/ 
	OLED_WR_Byte(0x80,OLED_CMD); 
	OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/ 
	OLED_WR_Byte(0x1f,OLED_CMD); /*0x22*/ 
	OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/ 
	OLED_WR_Byte(0x12,OLED_CMD); 
	OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/ 
	OLED_WR_Byte(0x40,OLED_CMD);
	OLED_Clear();
	OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
}

2、候改发送数据如下:

void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{	
	uint8_t i;			  
	if(cmd)
	  OLED_DC_Set();
	else
	  OLED_DC_Clr();
	OLED_CS_Clr();
#ifdef H_SPI
	HAL_SPI_Transmit(&SPI_Handle, &dat, 1, 0);  
#else
	for(i=0;i<8;i++)
	{
		OLED_SCL_Clr();
		if(dat&0x80)
		   OLED_SDA_Set();
		else 
		   OLED_SDA_Clr();
		OLED_SCL_Set();
		dat<<=1;   
	}
#endif	
	OLED_CS_Set();
	OLED_DC_Set();   	  
}

这样我们就可以实现硬件与软件模拟的同一套代码,通过宏定义来实现转换,下载到开发板后效果是一样的。

本文来自论坛,点击查看完整帖子内容。

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章