这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 智能手环DIY活动过程帖【OLED屏幕使用u8g2方法】

共1条 1/1 1 跳转至

智能手环DIY活动过程帖【OLED屏幕使用u8g2方法】

菜鸟
2025-10-07 17:28:06     打赏

一、硬件介绍

1、产品特点

MAX78000FTHR 开发板集成卷积神经网络加速器,将ARM Cortex-M4处理器与浮点单元 (FPU)、卷积神经网络 (CNN) 加速器和 RISC-V 内核组合在一起,包括MAX20303 PMIC,用于电池和电源管理,兼容Adafruit Feather Wing外设扩展板。评估板包括各种外设,例如CMOS VGA图像传感器、数字麦克风、低功耗立体声音频CODEC、1MB QSPI SRAM、micro SD存储卡连接器、RGB指示LED和按键。

MAX78000FTHR: Board Photo


板载的MAX32625微控制器已预先编程有 DAPLink 固件,可通过 USB 对 MAX78000 Arm 内核进行调试和编程

标准10pin引脚JTAG接口,可调试和编程MAX78000的RISC-V内核


特性

  • 双核:Arm Cortex-M4 FPU处理器,100MHz;RISC-V协处理器,60MHz

  • 512KB闪存

  • 128KB SRAM

  • 16KB 缓存

  • 卷积神经网络加速器

  • 12位并行摄像头接口

  • MAX20303可穿戴PMIC,带电量计

  • Micro SD卡连接器

  • CMOS VGA图像传感器

  • 低功耗、立体声音频编解码器

  • 数字麦克风


硬件框图

FgnPVfh_d1kmN-nDzmYpSZ04mEE0


系统框图

image-20250924223301534.png


2、功能引脚示意图 / 原理图

原理图

板载按钮

SW1:用户可编程功能按钮;

连接到 P0_2

SW2:用户可编程功能按钮;

连接到 P1_7

SW3:PMIC 电源按钮;

Power_Button:当电路板处于通电状态时,按住此按钮 12 秒将执行硬断电; 当电路板处于断电状态时,按下此按钮可重新打开电路板电源。

该按钮可以被MAX78000读取,当按下按钮时,PMIC_PFN2(P3_0)信号进入逻辑低电平状态。

SW4:连接到 RSTN 的输入;

用于复位 MCU

SW5:DAPLink 固件更新按钮;

用于 DAPLINK 固件的更新; 当按下按钮上电时,将进入固件更新模式;


板载LED

D1: 该LED可由用户控制,连接到对应的GPIO端口;

LED_R:P2_0 LED_G:P2_1 LED_B:P2_2

D2:连接到MAX20303的PMIC_LEDx输出;

这些LED可以通过I2C命令进行控制; 还可以通过 I2C 命令配置为充电状态指示灯;

PMIC_LED1(Red) PMIC_LED2(Green) PMIC_LED0(Blue)

D3:DAPLink(MAX32625)状态指示灯;

由 DAPLink 控制


引脚图


image-20250923220205380.png


image-20250923220052647.png

image-20250923220052647

image-20250923220317481



脚序名称功能
1RST主复位引脚
23V33.3V 输出 为外设提供 3.3V 电压
31V81.8V 输出 为外设提供 1.8V 电压
4GND
5P2_3GPIO 或 模拟输入(AIN3 通道)
6P2_4GPIO 或 模拟输入(AIN4 通道)
7P1_1GPIO 或 UART2_Tx
8P1_0GPIO 或 UART2_Rx
9MPC1GPIO 由 PMIC 通过 I2C 接口控制 开漏 或 推挽输出
10MPC2GPIO 由 PMIC 通过 I2C 接口控制 开漏 或 推挽输出
11P0_7GPIO 或 QSPI0 时钟 SD卡 和 板载 QSPI SRAM 共享
12P0_5GPIO 或 QSPI0 MOSI SD卡 和 板载 QSPI SRAM 共享
13P0_6GPIO 或 QSPI0 MISO SD卡 和 板载 QSPI SRAM 共享
14P2_6GPIO 或 LPUART_Rx
15P2_7GPIO 或 LPUART_Tx
16GND
17SYS这是主系统电源,可在电池电压 和 USB电源 之间自动切换 (5V)
18PWR强制关机按钮 对地短路 13 秒,则关闭 PMIC
19VBUSUSB_VBUS 当连接到 USB 时,为外设提供 5V 电压 在不使用 USB 连接时,也可以用作为电路的供电输入 (最好不要,因为没有电路防止电流回流至USB)
20P1_6GPIO
21MPC3GPIO 由 PMIC 通过 I2C 接口控制 开漏 或 推挽输出
22P0_9GPIO 或 QSPI0 SDIO3 SD 卡和板载 QSPI SRAM 共享
23P0_8GPIO 或 QSPI0 SDIO2 SD卡和板载 QSPI SRAM 共享
24P0_11GPIO 或 QSPI0_Slave
25P0_19GPIO
26P3_1GPIO 或 Wake-up 该引脚为 3.3V
27P0_16GPIO 或 I2C1_SCL 板载电平转换器允许通过 R15 或 R20 电阻器选择 1.8V 或 3.3V (详见原理图)
28P0_17GPIO 或 I2C1_SDA 板载电平转换器允许通过 R15 或 R20 电阻选择 1.8V 或 3.3V (详见原理图)


3、0.96寸OLED 黄蓝显示屏 (SSD1315)

使用文档

数据手册

黄蓝显示屏 (SSD1315) 是一款蓝色和黄色双色显示屏,该显示屏支持 3.3V 和 5V 电源电压。

可以使用 I2CSPI 接口;

若使用 SPI 需要焊接后面;

image-20250927113345290


特性

  • 兼容 3.3V / 5V 电源

  • 可更改 I2C 地址

  • 支持 SPI

  • 低功耗

  • 黄色和蓝色双色 128×64 像素

  • 高对比度,高亮度

  • 宽工作温度范围:-40℃ ~ +85 ℃


原理图

image-20250927114811657.png

image-20250927114811657


二、硬件连接

开发板通过硬件I2C的方式连接OLED屏幕;

开发板OLED屏幕



3V3VCC
GNDGND
P0_16 (I2C1_SCL)SCL
P0_17 (I2C1_SDA)SDA


实物效果

image-20250927121335643

image-20250927121335643.png



三、代码编写

MAX78000FTHR手册

MAX78000手册

SDK使用文档

u8g2使用手册


u8g2库配置

见上篇文章


u8g2接口代码编写

参考手册

1、在工程目录下新建 oled文件夹 创建 oled.c 和 oled.h文件,用来编写相关接口函数的实现;

一样在 Makefile文件中,添加源文件和头文件搜索位置时,所在的 oled 文件夹;

以下为参考手册中u8g2初始化示例,其中屏幕驱动函数 u8g2_Setup_ssd1306_128x64_noname_f

需自己实现2个回调函数 u8x8_byte_hw_i2cu8x8_gpio_and_delay

// u8g2 接口函数
// U8G2_R0 - 显示旋转角度(R0=0度,R1=90度,R2=180度,R3=270度)
// u8x8_byte_hw_i2c - I2C 字节传输回调函数,负责底层 I2C 通信
// u8x8_gpio_and_delay - GPIO 和延时回调函数,负责复位引脚控制和延时操作

void u8g2Init(u8g2_t *u8g2)
{
   u8g2_Setup_ssd1315_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay);
   u8g2_InitDisplay(u8g2);
   u8g2_SetPowerSave(u8g2, 0);
   u8g2_ClearBuffer(u8g2);
}


2、编写回调函数

oled.h

#ifndef __oled_H
#define __oled_H
#ifdef __cplusplus
extern "C"
{
#endif

/* Includes ------------------------------------------------------------------*/
#include "u8g2.h"
#include "i2c.h"
#include "mxc_delay.h"
#include "mxc_errors.h"
#include "max78000.h"
#include <stdio.h>
#include <stdint.h>

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
void u8g2Init(u8g2_t *u8g2);
   
#ifdef __cplusplus
}
#endif
#endif /*__ i2c_H */


oled.c

oled_i2c_init:I2C初始化(硬件I2C);

oled_i2c_write(uint8_t addr, uint8_t *data, int len):I2C数据发送函数;

#include "oled.h"

#define OLED_I2C MXC_I2C1
#define I2C_FREQ 400000 //  400KHz
#define OLED_ADDR 0x3C  // SSD1315:I2C地址 0x78(8位) 0x3C为7位地址

// 硬件I2C初始化
static int oled_i2c_init(void)
{
   int error;
   // 初始化 I2C 为主机模式
   error = MXC_I2C_Init(OLED_I2C, 1, 0);
   if (error != E_NO_ERROR)
   {
       printf("I2C 初始化失败: %d\n", error);
       return error;
   }
   // 设置 I2C 频率
   error = MXC_I2C_SetFrequency(OLED_I2C, I2C_FREQ);
   if (error < E_NO_ERROR)
   {
       printf("I2C 频率设置失败: %d\n", error);
       return error;
   }
   return E_NO_ERROR;
}

// I2C 发送函数
static int oled_i2c_write(uint8_t addr, uint8_t *data, int len)
{
   mxc_i2c_req_t oled;
   oled.i2c = OLED_I2C;
   oled.addr = addr;
   oled.tx_buf = data;
   oled.tx_len = len;
   oled.rx_buf = NULL;
   oled.rx_len = 0;
   oled.restart = 0;
   oled.callback = NULL;
   return MXC_I2C_MasterTransaction(&oled);
}

// 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[32];
   static uint8_t buf_idx;
   uint8_t *data;
   
   switch (msg)
   {
   case U8X8_MSG_BYTE_INIT:
   {
       /* add your custom code to init i2c subsystem */
       oled_i2c_init(); // I2C初始化
   }
   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 (oled_i2c_write(OLED_ADDR, buffer, buf_idx) == E_NO_ERROR) //数据传输
           return 0;
   }
   break;

   case U8X8_MSG_BYTE_SET_DC:
       break;

   default:
       return 0;
   }

   return 1;
}

// GPIO 和延时设置 回调函数
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
   switch (msg)
   {
   case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
       __NOP();
       break;
   case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
       MXC_Delay(arg_int * 10);
       break;
   case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
       MXC_Delay(arg_int * 1000);
       break;
   case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
      // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
       MXC_Delay(1);
       break;
   case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
       break;                    // arg_int=1: Input dir with pullup high for I2C clock pin
   case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
       break;                    // arg_int=1: Input dir with pullup high for I2C data pin
   case U8X8_MSG_GPIO_MENU_SELECT:
       u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
       break;
   case U8X8_MSG_GPIO_MENU_NEXT:
       u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
       break;
   case U8X8_MSG_GPIO_MENU_PREV:
       u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
       break;
   case U8X8_MSG_GPIO_MENU_HOME:
       u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
       break;
   default:
       u8x8_SetGPIOResult(u8x8, 1); // default return value
       break;
   }
   return 1;
}

// u8g2 接口函数
// U8G2_R0 - 显示旋转角度(R0=0度,R1=90度,R2=180度,R3=270度)
// u8x8_byte_hw_i2c - I2C 字节传输回调函数,负责底层 I2C 通信
// u8x8_gpio_and_delay - GPIO 和延时回调函数,负责复位引脚控制和延时操作

void u8g2Init(u8g2_t *u8g2)
{
   u8g2_Setup_ssd1315_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay);
   u8g2_InitDisplay(u8g2);
   u8g2_SetPowerSave(u8g2, 0);
   u8g2_ClearBuffer(u8g2);
}


main.c


/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "board.h"
#include "mxc_device.h"
#include "nvic_table.h"

#include "oled.h"

int main(void)
{
   u8g2_t u8g2;
   u8g2Init(&u8g2);
   u8g2_SendBuffer(&u8g2);
   
   // 基础图形
   u8g2_DrawBox(&u8g2, 2, 2, 20, 10);
   u8g2_DrawRFrame(&u8g2, 25, 0, 30, 16, 0);
   u8g2_DrawRBox(&u8g2, 60, 0, 30, 32, 0);

   // 画线
   u8g2_DrawLine(&u8g2, 0, 20, 50, 40);

   // 圆
   u8g2_DrawCircle(&u8g2, 110, 30, 10, U8G2_DRAW_ALL);
   u8g2_DrawDisc(&u8g2, 100, 45, 8, U8G2_DRAW_ALL);

   // 文字
   u8g2_SetFont(&u8g2, u8g2_font_unifont_t_chinese3);
   u8g2_DrawUTF8(&u8g2, 4, 60, "u8g2使用");

   u8g2_SendBuffer(&u8g2);

   while (1)
   {
       MXC_Delay(10000);
   }
}


编译代码

使用CTRL + SHIFT + B 选择 Build 编译项目;

或使用终端 make -j16 PROJECT=GPIO,编译成 .elf 程序二进制文件;


四、程序烧录

1、用数据线连接开发板至电脑上;

2、程序烧录

使用CTRL + SHIFT + B 选择 flash & run 烧录并运行程序;


五、演示效果

SSD1316:双色 OLED(上面黄色 / 下面蓝色)

image-20250928094423662

image-20250928094423662.png












关键词: MAX78000FTHR    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]