0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于极海APM32F411 MCU移植U8g2驱动OLED指南

Geehy极海半导体 ? 来源:21ic论坛极海半导体专区 ? 2025-07-17 14:45 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

来源:转载自21ic论坛极海半导体专区

1、前言

最近拿到了极海的APM32F411 TINY 板卡,APM32F411是其新推出的新品,资源如下:

基于Arm Cortex-M4F内核,工作主频120MHz,具有高速运算能力、多种工作模式、以及丰富的高精度外设和通讯接口;内置CRC32运算单元,可为用户提供高集成度、高可靠性的SoC方案;作为APM32F4系列MCU的超值型拓展产品,能很好的满足用户对功耗、性能、性价比方面的产品均衡需求,可适用于电力,仪器仪表,工控,家电,物联网新能源,智慧楼宇等广泛的应用领域。

更多内容可以看他们的官网:[APM32F411 (geehy.com)](https://geehy.com/apm32?id=81)

拿到了他们的APM32F411 TINY 板卡后想着搞点事情,手上有一个0.96寸的OLED屏幕,想着拿这个板卡点亮这个屏幕,但想着点亮多没意思,于是便有了这个笔记“基于APM32F411 移植 U8g2”。刚好这个 TINY 板卡是没有屏幕显示的,后面的小伙伴也可以在我做的demo上做一些自己的应用显示。

那话不多说,现在开始吧。

2、 APM32F411 源码准备

APM32F411 的评估源码可以在他们官网获取:https://geehy.com/uploads/tool/APM32F4xx_SDK_V1.4.zip

我手上的OLED使用的是I2C进行驱动的,所以我这里直接在他们的“APM32F4xx_SDK_V1.4ExamplesI2C”目录下复制“I2C_TwoBoards_Master”demo并改名为“I2C_U8g2”。

我们将在这个demo的基础上实现U8g2适配。

a7ba73ce-607c-11f0-baa5-92fbcf53809c.png

3、 U8g2源码准备

U8g2的源码在GitHub上开源:https://github.com/olikraus/u8g2

我们把它的源码下载下来。

4、 移植U8g2至APM32F411

4.1 复制U8g2源码

我们在APM32F4xx_SDK_V1.4Middlewares下新建U8g2文件夹用于保存我们工程所需的U8g2源码。

a7e4ba12-607c-11f0-baa5-92fbcf53809c.png

由于U8g2支持多种显示驱动的屏幕,因为源码中也包含了各个驱动对应的文件(所以不需要自己去写屏幕底层驱动了),为了减小整个工程的代码体积,我们在移植U8g2时,可以删除一些对本工程来说无用的文件。

这里我们主要关注的是**U8g2库文件**中的**csrc文件**。我们把csrc文件夹中的内容添加入我们的APM32F4xx_SDK_V1.4MiddlewaresU8g2中。

4.2 工程包含U8g2源码

在工程下新建“U8g2”分组用于存放U8g2源码。

a7f0f44e-607c-11f0-baa5-92fbcf53809c.png

由于“u8x8_d_sxxx.c”等源码是驱动屏幕的驱动文件,这里我们选用“u8x8_d_ssd1306_128x64_noname.c”,又因为u8g2_d_memory.c,u8g2_d_setup.c是必须的驱动函数所在文件这两个我们保留。(即:u8x8_d_sxxx.c样式的文件仅保留u8x8_d_ssd1306_128x64_noname.c、u8g2_d_memory.c、u8g2_d_setup.c)。

4.3 添加延时函数功能

APM32F4的SDK中已经有一个“bsp_delay.c”文件使用滴答定时器做的延时,我们包含进工程。

a7fa0976-607c-11f0-baa5-92fbcf53809c.png

包含进工程后,我们要把“APM_DelayTickDec()”函数放置至 apm32f4xx_int.c中的滴答定时器中断。

a803630e-607c-11f0-baa5-92fbcf53809c.png

如此一来我们便可以正常使用“APM_DelayMs”及“APM_DelayUs”函数了。

4.4 完善I2C初始化及发送函数

由于本demo使用的是I2C的主机功能,且只需要发送功能,我们把I2C的初始化函数编写如下:

/*!

* I2C Init

*

* @param None

*

* @retval None

*/

void I2CInit(void)

{

GPIO_Config_T gpioConfigStruct;

I2C_Config_T i2cConfigStruct;

/* Enable I2C related Clock */

RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);

RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);

/* Free I2C_SCL and I2C_SDA */

GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_6, GPIO_AF_I2C1);

GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_7, GPIO_AF_I2C1);

gpioConfigStruct.mode = GPIO_MODE_AF;

gpioConfigStruct.speed = GPIO_SPEED_50MHz;

gpioConfigStruct.pin = GPIO_PIN_6 | GPIO_PIN_7;

gpioConfigStruct.otype = GPIO_OTYPE_OD;

gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;

GPIO_Config(GPIOB, &gpioConfigStruct);

/* Config I2C1 */

I2C_Reset(I2C1);

i2cConfigStruct.mode = I2C_MODE_I2C;

i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;

i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;

i2cConfigStruct.ownAddress1 = 0XA0;

i2cConfigStruct.ack = I2C_ACK_ENABLE;

i2cConfigStruct.clockSpeed = 100000;

I2C_Config(I2C1, &i2cConfigStruct);

I2C_DisableDualAddress(I2C1);

/* Enable I2Cx */

I2C_Enable(I2C1);

}

原demo是使用字符串结束符来判断发送内容的结束的,我们简单修改一下发送函数,传参内容有:

1. 目标I2C从机地址

2. 发送数组

3. 发送数据的大小

这里我们固定I2C从机地址为7bit。

/*!

* Write data to the I2C1

*

* @param pBuffer: wiret buffer

*

* @retval 0: Error 1:Succee

*/

uint8_t I2C_Write_Buff(uint16_t DevAddress, uint8_t *pBuffer, uint16_t Size)

{

uint16_t tx_size = Size;

uint16_t I2CTimeout = I2CT_LONG_TIMEOUT;

while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)

{

I2CInit();

if ((I2CTimeout--) == 0)

{

return I2C_TIMEOUT_UserCallback(4);

}

}

I2C_DisableInterrupt(I2C1, I2C_INT_EVT);

/* Send START condition */

I2C_EnableGenerateStart(I2C1);

I2CTimeout = I2CT_FLAG_TIMEOUT;

while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) //EV5

{

if ((I2CTimeout--) == 0)

{

return I2C_TIMEOUT_UserCallback(5);

}

}

/* Send address for write */

I2C_Tx7BitAddress(I2C1, DevAddress, I2C_DIRECTION_TX);

I2CTimeout = I2CT_FLAG_TIMEOUT;

while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EV6

{

if ((I2CTimeout--) == 0)

{

return I2C_TIMEOUT_UserCallback(6);

}

}

/* While there is data to be written */

while (tx_size > 0u)

{

I2CTimeout = I2CT_LONG_TIMEOUT;

/* Send the current byte */

I2C_TxData(I2C1, *pBuffer);

while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) //EV8

{

if ((I2CTimeout--) == 0)

{

return I2C_TIMEOUT_UserCallback(8);

}

}

/* Point to the next byte to be written */

pBuffer++;

tx_size --;

}

while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //EV8-2

{

if ((I2CTimeout--) == 0)

{

return I2C_TIMEOUT_UserCallback(9);

}

}

I2C_EnableGenerateStop(I2C1);

return 1;

}

4.5 修改u8g2_d_memory.c

该源文件中包含着各个屏幕的驱动缓存,这里我们仅保留“uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)”,其他函数进行注释。

a80d50e4-607c-11f0-baa5-92fbcf53809c.png

4.6 修改u8g2_d_setup.c

该源文件中包含着各个屏幕的驱动缓存,这里我们仅保留“uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)”,其他函数进行注释。

a8174cca-607c-11f0-baa5-92fbcf53809c.png

5、 编写u8g2初始化代码

我们要使用u8g2需要对其进行一些初始化操作,我们新建 一个“apm32_u8g2.c”保存这部分内容。这里主要写一下“u8x8_byte_hw_i2c”函数内容,需要吧I2C初始化和I2C发送函数放在这里面。

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)

{

/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */

static uint8_t buffer[128];

static uint8_t buf_idx;

uint8_t *data;

switch (msg)

{

case U8X8_MSG_BYTE_INIT:

{

/* add your custom code to init i2c subsystem */

I2CInit();

}

break;

case U8X8_MSG_BYTE_START_TRANSFER:

{

buf_idx = 0;

}

break;

case U8X8_MSG_BYTE_SEND:

{

data = (uint8_t *)arg_ptr;

while (arg_int > 0)

{

buffer[buf_idx++] = *data;

data++;

arg_int--;

}

}

break;

case U8X8_MSG_BYTE_END_TRANSFER:

{

if (I2C_Write_Buff( OLED_ADDRESS, buffer, buf_idx) != 1)

return 0;

}

break;

case U8X8_MSG_BYTE_SET_DC:

break;

default:

return 0;

}

return 1;

}

6、 编写OLED测试函数

OLED需要进行一些测试,如画点,画圆等操作,我这里写了一个“oled_test.c”文件进行了测试验证。因为这里面的代码比较多就不一一说明了。

7、 最终效果

完成代码编写后,即可通过APM32F411TINY板卡的板载仿真器进行程序下载啦。

a82a393e-607c-11f0-baa5-92fbcf53809c.png

程序运行如下所示:

a833385e-607c-11f0-baa5-92fbcf53809c.gif

注:文章作者在原帖中提供了例程文件,有需要请至原文21ic论坛下载

原文地址:https://bbs.21ic.com/icview-3326714-1-1.html

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    18041

    浏览量

    369790
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9375

    浏览量

    379175
  • OLED
    +关注

    关注

    120

    文章

    6291

    浏览量

    228696
  • 移植
    +关注

    关注

    1

    文章

    401

    浏览量

    28768
  • 极海半导体
    +关注

    关注

    0

    文章

    168

    浏览量

    4825

原文标题:APM32芯得 EP.61 | 基于APM32F411移植U8g2驱动OLED完整教程

文章出处:【微信号:geehysemi,微信公众号:Geehy极海半导体】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    STM32移植U8g2图形库的方法 实现OLED图形显示

    本篇介绍了如何将U8g2图形库移植到STM32中。
    的头像 发表于 06-07 08:29 ?1.3w次阅读
    STM32<b class='flag-5'>移植</b><b class='flag-5'>U8g2</b>图形库的方法 实现<b class='flag-5'>OLED</b>图形显示

    APM32F411微控制器硬件FPU使用指南

    APM32F411是一款基于32位Arm Cortex-M4F内核的微控制器。硬件FPU是Arm Cortex-M4F的一大优势。合理应用硬件FPU可以大大缩短运算时间。
    的头像 发表于 06-28 11:23 ?947次阅读
    <b class='flag-5'>极</b><b class='flag-5'>海</b><b class='flag-5'>APM32F411</b>微控制器硬件FPU使用<b class='flag-5'>指南</b>

    【CH32V208开发板】图形库u8g2oled显示

    灵活配置),基于 32 位 RISC-V 指令集及架构设计,芯片内部集成了ETH-10M(+PHY)以太网和蓝牙。 本篇讲述使用u8g2图形库驱动oled显示,使用改图形库优势功能强大,具有字体库
    发表于 07-29 23:11

    【RA-Eco-RA6M4开发板评测】2、I2C外设驱动OLED屏幕和移植u8g2

    ://wiki.seeedstudio.com/Grove-OLED-Display-0.96-SSD1315/ u8g2移植简述 在SeeedStudio官方的使用手中,在Arduino平台上使用
    发表于 07-23 13:51

    U8G2库简介

    是针对arduino平台的,但是使用方法在stm32平台上也是大同小异。U8G2库的下载及硬件平台U8G2库是一个开源的github项目,通过github可以直接下载 。下载地址此次使用的mcu是stm32
    发表于 08-10 06:02

    oledu8g2库使用说明

    [arduino][u8g2][12864] oledu8g2库使用说明(例子是12864液晶屏)首先说一下写这个文档的目的,一是给自己做个笔记来以备后边使,二是写个文档给大家看,我从网上找了很多
    发表于 01-11 06:51

    U8G2图形库移植介绍

    stm32移植U8G2图像库指南U8G2图形库介绍移植准备工作开始移植文件修改keil配置修改
    发表于 02-17 07:10

    【平头哥RVB2601创意应用开发】实践2-移植U8g2图形库

    OLED和LCD,并支持如SSD1306等多种类型的OLED驱动U8g2源码的开源库地址:https://github.com/olikraus/
    发表于 03-27 20:06

    【国民技术N32项目移植】SPI U8G2驱动 oled

    OLED_SPI_PIN_CS GET_PIN(C,9)#define OLED_SPI_PIN_CLKGET_PIN(B,13)#define OLED_SPI_PIN_MOSIGET_PIN(B,15)
    发表于 02-25 12:39

    esp8266学习笔记⑨:OLED 屏幕的使用(u8g2图形库模块)

    一、使用前的准备首先先将u8g2的模块烧录到nodemcu中,选择OLED 屏幕所支持的u8g图形库,和所需要的字体,如下图:构建完成之后,下载烧录到开发板中。二、u8g2模块的主要函
    发表于 11-26 09:36 ?18次下载
    esp8266学习笔记⑨:<b class='flag-5'>OLED</b> 屏幕的使用(<b class='flag-5'>u8g2</b>图形库模块)

    ESP8266驱动SH1306-1.3寸OLED屏幕(u8g2图形库)

    OLED屏模块的同学几乎离不开u8g2开源库,因为…真的很强大!目前在github上1.7K star,接近2000次commit,基本支持主流的OLED驱动。具体可以看图中支持的型
    发表于 12-22 18:43 ?14次下载
    ESP8266<b class='flag-5'>驱动</b>SH1306-1.3寸<b class='flag-5'>OLED</b>屏幕(<b class='flag-5'>u8g2</b>图形库)

    stm32移植U8G2图像库指南

    stm32移植U8G2图像库指南U8G2图形库介绍移植准备工作开始移植文件修改keil配置修改
    发表于 12-22 18:55 ?26次下载
    stm32<b class='flag-5'>移植</b><b class='flag-5'>U8G2</b>图像库<b class='flag-5'>指南</b>

    半导体推出APM32F411系列高性能高适配型MCU

    面向能耗与成本敏感的中高端工业应用市场,不仅对芯片性能与功耗有更高要求,复杂的功能需求也考量着芯片的适配性与稳定性。为平衡客户对产品低功耗、高性能与高性价比等综合需求,正式推出APM32F411
    发表于 08-06 10:32 ?859次阅读
    <b class='flag-5'>极</b><b class='flag-5'>海</b>半导体推出<b class='flag-5'>APM32F411</b>系列高性能高适配型<b class='flag-5'>MCU</b>

    关于stm32,u8g2菜单之间切换(1)

    移植U8g2
    的头像 发表于 03-05 16:43 ?608次阅读

    关于stm32,u8g2菜单之间切换(二)u8g2移植

    移植是基于stm32cubeide,oled屏是1306驱动128x64的。接口用iic软件模拟,hal库iic硬件貌似有bug。 1,先在网上下载u8g2包。
    的头像 发表于 03-04 09:52 ?1107次阅读
    关于stm32,<b class='flag-5'>u8g2</b>菜单之间切换(二)<b class='flag-5'>u8g2</b>的<b class='flag-5'>移植</b>