U8g2 软件i2c移植到stm32
使用stm32f407,软件i2c驱动oled屏幕
屏幕为
128*64 ,0.96寸 单色oled屏,驱动芯片ssd1306
开发环境:
VSCODE+EIDE
开发语言:
C/C++混编
第一步:准备资料
U8g2源码https://github.com/olikraus/u8g2 下载 下载解压以后的目录 我们主要是要 csrc 文件夹中的内容 1.将该文件夹添加到你的工程目录中,随便改名,我这里改名叫U8g2_drv 2.不要忘了在将文件夹添加到包含目录 图片不完整,还有很多,有几点注意以下: 1.mui开头的文件不用添加 2.u8x8_d_*****.c等是驱动文件,选择我们要的,u8x8_d_ssd1306_128x64_noname.c ,其它可以添加也可以不添加 3.除上述不添加的,添加其它.c文件 其中my_u8g2.c是用来存放我们自己写的代码,主要是驱动内容
第二步写驱动:
目标: PE0-SCL PE1-SDA 软件IIC
my_u8g2.c 文件
#include "my_u8g2.h"
#define SCL_Pin GPIO_PIN_0
#define SDA_Pin GPIO_PIN_1
#define I2C_GPIO GPIOE
void I2C_init(void)
{
GPIO_RCC_ENABLE(I2C_GPIO);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = SCL_Pin|SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(I2C_GPIO, &GPIO_InitStruct);
}
uint8_t STM32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DELAY_100NANO:
__NOP();
break;
case U8X8_MSG_DELAY_10MICRO:
HAL_Delay(10);
break;
case U8X8_MSG_DELAY_MILLI:
HAL_Delay(1);
break;
case U8X8_MSG_DELAY_I2C:
HAL_Delay_us(5);
case U8X8_MSG_GPIO_I2C_CLOCK:
if(arg_int == 1)
{
HAL_GPIO_WritePin(I2C_GPIO, SCL_Pin, GPIO_PIN_SET);
}
else if(arg_int == 0)
{
HAL_GPIO_WritePin(I2C_GPIO, SCL_Pin, GPIO_PIN_RESET);
}
break;
case U8X8_MSG_GPIO_I2C_DATA:
if(arg_int == 1)
{
HAL_GPIO_WritePin(I2C_GPIO, SDA_Pin, GPIO_PIN_SET);
}
else if(arg_int == 0)
{
HAL_GPIO_WritePin(I2C_GPIO, SDA_Pin, GPIO_PIN_RESET);
}
break;
default:
u8x8_SetGPIOResult(u8x8, 1);
break;
}
return 1;
}
my_u8g2.h 文件
#ifndef _MY_U8G2_H__
#define _MY_U8G2_H__
#include "my_sys.h"
#include "u8g2.h"
void I2C_init(void);
uint8_t STM32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
#endif
第三步:修改u8g2源文件
1.修改u8g2_d_setup.c
注释所有函数, 保留以下两个函数,其它不需要做更改
void u8g2_Setup_ssd1306_i2c_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
uint8_t tile_buf_height;
uint8_t *buf;
u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
buf = u8g2_m_16_8_1(&tile_buf_height);
u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}
void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
uint8_t tile_buf_height;
uint8_t *buf;
u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
buf = u8g2_m_16_8_f(&tile_buf_height);
u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}
2.修改u8g2_d_memory.c
注释所有函数,然后编译,查找报错信息,看缺少什么函数,找到他并相应取消注释即可 当然现在对于我这个芯片已经是找到了,直接拿给你,如果你的屏幕不一样,就要用你自己缺的 同样也是两个函数
uint8_t *u8g2_m_16_8_1(uint8_t *page_cnt)
{
#ifdef U8G2_USE_DYNAMIC_ALLOC
*page_cnt = 1;
return 0;
#else
static uint8_t buf[128];
*page_cnt = 1;
return buf;
#endif
}
uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{
#ifdef U8G2_USE_DYNAMIC_ALLOC
*page_cnt = 8;
return 0;
#else
static uint8_t buf[1024];
*page_cnt = 8;
return buf;
#endif
}
至此修改工作已经完成,已经完成一大半了,剩下就比较简单了
第四步:开始写main.cpp
为什么是main.cpp呢,因为我的环境是C/C++混编,对于你们就是main.c 就行了,区别会讲明
1.C++引入C文件需要像这样,否则会报错提示找不到函数/信息丢失等
extern "C"
{
#include "u8g2.h"
#include "my_u8g2.h"
}
#include "u8g2.h"
#include "my_u8g2.h"
2.主函数添加代码
int main(void)
{
.....
I2C_init();
u8g2_t u8g2;
u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, STM32_gpio_and_delay);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
u8g2_ClearBuffer(&u8g2);
u8g2_SendBuffer(&u8g2);
u8g2_SetFont(&u8g2,u8g2_font_DigitalDiscoThin_tf);
u8g2_DrawStr(&u8g2,30,50,"Test_code");
u8g2_SendBuffer(&u8g2);
u8g2_DrawCircle(&u8g2,64,32,10,U8G2_DRAW_ALL);
u8g2_SendBuffer(&u8g2);
}
接着就可以编译下载了
效果图片
!!!可能存在的报错(必看)
1.C++类兼容错误(使用C忽略)
1.可能是头文件引用等错误 2.可能是–cpp11 --c99 等错误 VSCODE中EIDE 解决方法:
##########################################################################################
# Append Compiler Options For Source Files
#
# syntax:
# <your matcher expr>: <your compiler command>
#
# examples:
# 'main.cpp': --cpp11 -Og ...
# 'src/*.c': -gnu -O2 ...
# 'src/lib/**/*.cpp': --cpp11 -Os ...
# '!Application/*.c': -O0
# '**/*.c': -O2 -gnu ...
#
# For more syntax, please refer to: https:
#
##########################################################################################
version: '1.0'
#
# for source files with filesystem paths
#
files:
# './test/**/*.c': --c99
'./MY-DRIVERS/**/*.c': --cpp11
'./MY-DRIVERS/**/*.cpp': --cpp11
'./Core/**/*.c': --cpp11
'./Core/**/*.cpp': --cpp11
#
# for source files with virtual paths
#
virtualPathFiles:
# 'virtual_folder/**/*.c': --c99
2.报内存超出错误 No space in execution regions
先排查原因 ,首先注释上文main.c中的 u8g2_SetFont(&u8g2,u8g2_font_DigitalDiscoThin_tf); u8g2_DrawStr(&u8g2,30,50,“Test_code”); u8g2_SendBuffer(&u8g2); 等三句话,主要是u8g2_SetFont 函数
如果还报错,需要更改代码优化等级
keil版
在keil中实测改到level 1 就可以了 优化等级改高了可能会出现意料之外的优化结果,特别是使用系统等(非裸机)
EIDE版
1.打开构建器选项 2.选择C/C++编译器 选择更换代码优化级别,经实测可以改成level 1 或者-Ospace(for code size) 我最终还是选择了-Ospace(for code size)
|