一、无聊的废话
一直以来都是使用的标准库开发STM32,偶尔接触的使用STM32CubeMx开发STM32,觉得确实很方便,考研也是结束了,转换思路学习STM32CubeMx开发。
一开始点灯什么的都很方便,顺利的实现了。但是最近入手的一块1.5寸的OLED屏幕却死活点不亮。我的思路是利用STM32CubeMx生成模板,初始化对应的引脚,然后手动添加商家给的OLED驱动函数。
以上都成功实现了,虽然一堆的报错,但是慢慢的终于是修改到了0报错了,想着驱动代码是底层原理应该是不用修改,只需要对引脚定义加以修改就行,按上述的思路,最终还是没有点亮OLED屏幕。
二、出现的问题及解决方法:
1、引入驱动函数之后,编译报错函数RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);为无效值。通过查找基于HAL库的GPIOA使能函数解决;
2、延时函数报错。通过使用HAL库的延时函数解决;
3、引脚的置0置1方式是标准库的方式。通过修改为HAL库函数的方式解决。
4、要注意头文件的引用!
5、一切准备妥当,无报错但是仍然无法点亮OLED,定位是初始化的问题,自己又不停的修改,但是仍然未能解决,准备放弃的时候,偶然看到了一篇文章,里面的有一段初始化代码让我眼前一亮。即使使使用的STM32CubeMx开发,针对引脚已经进行了初始化,但是不是简单的调用初始化函数就可以的,针对IIC来说,需要在OLED初始化函数里再进行特定的初始化才行!
错误想法是:直接将生成的引脚初始化函数放进去,
//OLED的初始化
void OLED_Init(void)
{
MX_I2C1_Init();
HAL_Delay(200);
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0xFD,OLED_CMD);
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0xA0,OLED_CMD);
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xBF,OLED_CMD);// Set SEG Output Current Brightness
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0x25,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x34,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD);
}
正确方法是:
//OLED的初始化
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
//SCL
GPIO_InitStruct.Pin = SCL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
//SDA
GPIO_InitStruct.Pin = SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
HAL_Delay(200);
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0xFD,OLED_CMD);
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0xA0,OLED_CMD);
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xBF,OLED_CMD);// Set SEG Output Current Brightness
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0x25,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x34,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD);
}
最终困扰我一天的问题终于结局。自学嵌入式真的,问题出现的就很磨练心性!
三、 成品展示
基于HAL库&标准库开发的1.5寸OLED驱动
四、工程实现过程
文字内容太多,暂时不写了,有需要工程文件的可以留言。