硬件配置
- CPU是STM32F051
- 屏幕是0.96的SSD1306
- CPU-屏的接口是 硬件4线SPI
硬件接口
软件配置
- IDE是MDK5.24,搭配Vs code
移植
-
先用CubeMX生成初始化代码,我没有用HAL,用的LL更加适合单片机开发者的思维模式
配置模式不作细述。
- 然后去这里下载U8g2
- 下载完成后,解压,进入目录复制csrc,本次移植不考虑C++
- KEIL里面加入csrc的文件,并加入包含路径,加入文件是要注意一个u8x8_d_芯片名.c,只要加入自己需要使用的即可,其他的没有必要加入
- 重写U8g2需要的两个回调函数,根据接口不一样回调的名字也不一样。这个需要看一下github的介绍,本例是SPI
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
void *arg_ptr)
{
uint8_t *data = NULL;
switch (msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t*)arg_ptr;
do
{
while(LL_SPI_IsActiveFlag_TXE(SPI1) == RESET);
LL_SPI_TransmitData8(SPI1, *(data++));
while(LL_SPI_IsActiveFlag_BSY(SPI1) == SET){}
arg_int--;
}while(arg_int > 0);
break;
case U8X8_MSG_BYTE_INIT:
break;
case U8X8_MSG_BYTE_SET_DC:
GPIO_WriteBit(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
break;
case U8X8_MSG_BYTE_END_TRANSFER:
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8,
U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int,
U8X8_UNUSED void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
// HAL_Delay(1);
LL_mDelay(1);
break;
case U8X8_MSG_DELAY_MILLI:
LL_mDelay(arg_int);
break;
case U8X8_MSG_GPIO_CS:
GPIO_WriteBit(OLED_CS_GPIO_Port, OLED_CS_Pin, arg_int);
case U8X8_MSG_GPIO_DC:
// HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int);
GPIO_WriteBit(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int);
break;
case U8X8_MSG_GPIO_RESET:
// HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, arg_int);
GPIO_WriteBit(OLED_RST_GPIO_Port, OLED_RST_Pin, arg_int);
break;
}
return 1;
}
在使用LL库的SPI之前需要手动Enable SPI,库生成的代码有BUG,在配置完成后没有对SPI进行Enable
- 目前工程应该已经可以进行编译了,不过会有很多错误接下来对错误进行修正
- 首先要对u8_setup.c里面没有使用的函数进行注释,否则会调用大量的缓存,导致内存不够
- 内存不够:先执行上一步再执行本步不然会报大量的未定义错误,内存不够是因为U8g2支持了大量的屏幕有很多不同形式的缓冲区,只需要留下自己要用的一个即可其余的全部可以删除掉,具体缓冲区定义在U8g2_d_memory.c里面,调用是在u8x8_d_etup.c,快速的修改方法是注释掉u8g2_d_memory.c里面所有的缓冲区编译一下看哪个缓冲区报未定义,再回去取消那个缓冲存的注释。
- 然后在函数里对外设和u8g2进行初始化
static u8g2_t u8g2; //首先定义u8g2的对象
//对u8g2和屏幕进行初始化
u8g2_Setup_ssd1306_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
定义一个显示用的测试函数
void draw(u8g2_t *u8g2)
{
u8g2_SetFontMode(u8g2, 1); // Transparent
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
u8g2_DrawStr(u8g2, 0, 20, "U");
u8g2_SetFontDirection(u8g2, 1);
u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
u8g2_DrawStr(u8g2, 21,8,"8");
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
u8g2_DrawStr(u8g2, 51,30,"g");
u8g2_DrawStr(u8g2, 67,30,"\xb2");
u8g2_DrawHLine(u8g2, 2, 35, 47);
u8g2_DrawHLine(u8g2, 3, 36, 47);
u8g2_DrawVLine(u8g2, 45, 32, 12);
u8g2_DrawVLine(u8g2, 46, 33, 12);
u8g2_SetFont(u8g2, u8g2_font_4x6_tr);
u8g2_DrawStr(u8g2, 1,54,"github.com/olikraus/u8g2");
}
然后在主循环中进行调用
while (1)
{
/* USER CODE END WHILE */
u8g2_FirstPage(&u8g2);
do
{
draw(&u8g2);
} while (u8g2_NextPage(&u8g2));
/* USER CODE BEGIN 3 */
}
至此,移植就全部完成了,不是经常写文章,没有什么排版,主要是提供一个思路给各位