你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32H5 评测】ADC 电压表

[复制链接]
无垠的广袤 发布时间:2026-10-23 17:06

【STM32H5 评测】ADC 电压表

本文介绍了 NUCLEO-H5E5ZJ 开发板驱动 OLED 显示 ADC 电压和 MCU 温度的项目设计,包括硬件连接、环境搭建、工程创建、参数配置、ADC 打印、OLED显示等流程。

cover_adc_oled.jpg

项目介绍

NUCLEO-C562RE 开发板驱动 OLED 显示。

  • 准备工作:硬件连接、环境搭建;
  • 工程测试:工程创建、工程配置、工程代码、编译上传、效果演示。

硬件连接

根据原理图,选择 PF5 和 PG6 作为 I2C4 的通信引脚。

sch_i2c4.jpg

接线方式如下

STM32H5E5ZJT6 OLED
PF5 (SCL) SCL
PG6 (SDA) SDA
GND GND
3V3 VCC

实物图

connect_oled_st.jpg

工程配置

  • 打开 STM32CubeMX 软件,从开发板新建工程;

  • 进入 Pinout & Configuration 标签页,展开 Connectivity ,使能 I2C4,标准速率 100kHz,7 位地址 0x3c ;

    mx_i2c4_parameter.jpg

  • SCL 和 SDA 引脚默认配置,均设置为上拉输出模式;

  • 进入 Pinout & Configuration 标签页,展开 Analog ,点击 ADC3,模式页面下勾选 Temperature Sensor Channel ,参数配置调整采样时间为最大,即 640.5 个周期,以确保读数精度;

    mx_adc3_rank_cycles.jpg

  • 进入 ADC1 模式配置,根据原理图可知板载 A0 引脚对应 PA6,因此使能 IN3,参数配置将采样时间调整至最大;

    adc_sch_pa6_a0.jpg

  • 保存配置,生成 CMake工程;

ADC

使用 VS Code 打开 CubeMX 生成的工程文件夹;

点击左侧工具栏的运行调试按钮,生成 lanch.json 调试器配置文件;

点击下方工具栏的 生成 按钮,编译工程,确认无报错;

adc_code_page.jpg

配置右侧 AI 助手侧边栏,使用 GitHub Copilot 便于代码生成。

代码

VS Code 加载工程,打开 ./Core/Src/main.c 文件,添加如下代码

#include "main.h"
/* USER CODE BEGIN PD */
#define ADC_VREF_MV       3300U
#define ADC_MAX_VALUE     4095U
#define ADC_POLL_TIMEOUT  100U
/* USER CODE END PD */

/* Private variables ------------*/
COM_InitTypeDef BspCOMInit;
ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc3;

I2C_HandleTypeDef hi2c4;

/* Private function prototypes -------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_ICACHE_Init(void);
static void MX_ADC1_Init(void);
static void MX_ADC3_Init(void);
static void MX_I2C4_Init(void);

int main(void)
{
  MPU_Config();
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_ADC1_Init();
  MX_ADC3_Init();
  MX_I2C4_Init();
  /* USER CODE BEGIN 2 */
  if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE END 2 */

  /* Initialize leds */
  BSP_LED_Init(LED_GREEN);
  BSP_LED_Init(LED_RED);
  BSP_LED_Init(LED_BLUE);

  /* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/
  BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);

  /* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */
  BspCOMInit.BaudRate   = 115200;
  BspCOMInit.WordLength = COM_WORDLENGTH_8B;
  BspCOMInit.StopBits   = COM_STOPBITS_1;
  BspCOMInit.Parity     = COM_PARITY_NONE;
  BspCOMInit.HwFlowCtl  = COM_HWCONTROL_NONE;
  if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)
  {
    Error_Handler();
  }

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    uint32_t adcValue;
    uint32_t temperatureAdcValue;
    uint32_t voltageMv;
    int32_t temperatureC;

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
      Error_Handler();
    }
    if (HAL_ADC_PollForConversion(&hadc1, ADC_POLL_TIMEOUT) != HAL_OK)
    {
      Error_Handler();
    }
    adcValue = HAL_ADC_GetValue(&hadc1);
    if (HAL_ADC_Stop(&hadc1) != HAL_OK)
    {
      Error_Handler();
    }

    if (HAL_ADC_Start(&hadc3) != HAL_OK)
    {
      Error_Handler();
    }
    if (HAL_ADC_PollForConversion(&hadc3, ADC_POLL_TIMEOUT) != HAL_OK)
    {
      Error_Handler();
    }
    temperatureAdcValue = HAL_ADC_GetValue(&hadc3);
    if (HAL_ADC_Stop(&hadc3) != HAL_OK)
    {
      Error_Handler();
    }

    voltageMv = (adcValue * ADC_VREF_MV) / ADC_MAX_VALUE;
    temperatureC = __LL_ADC_CALC_TEMPERATURE(ADC_VREF_MV, temperatureAdcValue,
                                             LL_ADC_RESOLUTION_12B);

    printf("{\"adc_voltage_v\": %lu.%03lu, \"mcu_temperature_c\": %ld}\r\n",
           (unsigned long)(voltageMv / 1000U),
           (unsigned long)(voltageMv % 1000U),
           (long)temperatureC);
    HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

保存代码。

编译调试

  • 点击下方工具栏的 生成 按钮,编译工程;
  • 点击左侧工具栏的 调试运行 按钮,点击上方的运行按钮,上传调试固件;
  • 待进入调试状态,点击悬浮工具栏的启动按钮,开始运行程序;

adc_debug.jpg

效果

  • 打开 网页串口数据绘图工具 ,设置串口参数并连接;
  • 原始数据显示窗口打印 JSON 格式的 ADC 电压和温度数据;
  • 点击 开始采集 按钮,曲线显示 ADC 电压和 MCU 温度动态演化曲线;

adc_uart_curve.jpg

OLED

包括 OLED 驱动的头文件和源文件,字库和图片文件等。

ssd1306.h

新建 OLED 驱动头文件 ./Core/Inc/ssd1306.h ,添加如下代码

#ifndef __SSD1306_H
#define __SSD1306_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

void WriteCmd(void);
void SSD1306_WR_CMD(uint8_t cmd);
void SSD1306_WR_DATA(uint8_t data);
void SSD1306_Init(void);
void SSD1306_Clear(void);
void SSD1306_On(void);
void SSD1306_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn);
void SSD1306_ShowString(uint8_t x,uint8_t y,const char *chr,uint8_t Char_Size, uint8_t Color_Turn);
#ifdef __cplusplus
}
#endif

#endif /* __SSD1306_H */

保存代码。

ssd1306.c

新建 OLED 驱动源文件 ./Core/Src/ssd1306.c ,添加如下代码

#include "ssd1306.h"
#include "main.h"
#include "mx_i2c2.h"
#include "oledfont.h"

void WriteCmd(void)
{
    uint8_t i = 0;
    for(i=0; i<27; i++)
    {
        HAL_I2C_Mem_Write(&hi2c4, 0x78, 0x00,
                                I2C_MEMADD_SIZE_8BIT, CMD_Data + i, 1, 100);
    }
}

/**
 * @function: void SSD1306_WR_CMD(uint8_t cmd)
 * @description: 向设备写控制命令
 * @param {uint8_t} cmd 芯片手册规定的命令
 * @return {*}
 */
void SSD1306_WR_CMD(uint8_t cmd)
{
    HAL_I2C_Mem_Write(&hi2c4, 0x78, 0x00,
                            I2C_MEMADD_SIZE_8BIT, &cmd, 1, 100);
}

具体函数定义详见:【功率监测与控制系统DIY活动过程贴】OLED显示 .

oledfont.h

新建 OLED 驱动的字体头文件 ./Core/Inc/oledfont.h ,添加如下代码

#ifndef __OLEDFONT_H
#define __OLEDFONT_H

#include <stdint.h>

//8*6 ASCII字符集点阵  static const uint8_t Font6x8[][6] = {};
const unsigned char F6x8[][6] =  
{  
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp  
// …… ……
 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines  
};

//16*8 ASCII字符集点阵  static const uint8_t Font8x16[][16]={};
const unsigned char Font8x16[]=  
{
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//sp /0  
// …… …… 
 0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00,0x01,0x00,0x00,0x01,0x01,0x00,0x00  // ~ /94
};

const unsigned char Hzk[][32]=
{
{0x40,0x40,0x42,0xCC,0x00,0x04,0xF4,0x94,0x94,0xFF,0x94,0x94,0xF4,0x04,0x00,0x00},
{0x00,0x40,0x20,0x1F,0x20,0x48,0x44,0x42,0x41,0x5F,0x41,0x42,0x44,0x48,0x40,0x00},/*"速",1*/
/* (16 X 16 , 宋体 )*/
};
#endif

使用 PCtoLCD 软件取模,详见:【功率监测与控制系统DIY活动过程贴】OLED显示 .

pc2lcd_hz_config.jpg

字符在线取模:在线文字取模工具 .

bmp.h

新建 OLED 驱动的图片头文件 ./Core/Inc/bmp.h ,添加如下代码

#ifndef BMP_H_
#define BMP_H_

const unsigned char BMP1[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// …… ……
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

#endif /* BMP_H_ */

保存代码。

主函数

修改主函数 ./Core/Src/main.c 文件,关键代码如下

#include "main.h"
#include "ssd1306.h"
#include "bmp.h"

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c4;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_ICACHE_Init(void);
static void MX_I2C4_Init(void);

int main(void)
{
  MPU_Config();
  HAL_Init();
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_ADC1_Init();
  MX_ADC3_Init();
  MX_I2C4_Init();

  SSD1306_Init();

  SSD1306_Clear();
  SSD1306_ShowString(25, 0, "OLED TEST", 16, 1);
  SSD1306_ShowString(0, 3, "6x8 Font~", 12, 0);
  SSD1306_ShowString(0, 4, "8x16 Font~", 16, 0);
  SSD1306_ShowNum(0, 6, 1234567890, 10, 16, 0);
  HAL_Delay(1000);
  /* 图片显示 */
  SSD1306_DrawBMP(0, 0, 128, 8, BMP1, 0);
  HAL_Delay(1000);
  /* 显示汉字 */
  SSD1306_Clear();
  /* 1st row */
  SSD1306_ShowString(0,0," A D C ",16,1);
  SSD1306_ShowCHinese(56,0,7,1); // 电
  SSD1306_ShowString(71,0," ",16,1);
  SSD1306_ShowCHinese(79,0,8,1); // 压
  SSD1306_ShowString(94,0," ",16,1);
  SSD1306_ShowCHinese(102,0,9,1); // 表
  SSD1306_ShowString(117,0," ",16,1);

  /* 2nd row */
  SSD1306_ShowCHinese(0,2,0,0); // 电
  SSD1306_ShowCHinese(15,2,1,0); // 压
  SSD1306_ShowChar(30,2,':',16,0); // : 
  /* 3rd row */
  SSD1306_ShowCHinese(0,4,3,0); // 温
  SSD1306_ShowCHinese(15,4,4,0); // 度
  SSD1306_ShowChar(30,4,':',16,0); // : 
  /* 4th row */
  SSD1306_ShowCHinese(0,6,5,0); // 速
  SSD1306_ShowCHinese(15,6,6,0); // 率
  SSD1306_ShowChar(30,6,':',16,0); // : 

  HAL_Delay(1000);
  while (1){}
}

保存代码。

打开项目的 CMakeLists.txt 文件,将新增的驱动文件 Core/Src/ssd1306.c 添加至编译路径;

# Add sources to executable
target_sources(${CMAKE_PROJECT_NAME} PRIVATE 
# Add user sources here
    Core/Src/ssd1306.c 
) 

保存文件。

效果

  • 编译固件,运行工程;
  • OLED 显示文字、数字、图片等;

oled_show.jpg

ADC 电压表

将 ADC 电压和 MCU 温度数据显示在 OLED 屏幕上。

流程图

flowchart_adc_oled.jpg

代码

在前面代码的基础上,打开 ./Core/Src/main.c 文件,添加如下代码

#include "main.h"
#include "ssd1306.h"
#include "bmp.h"

int main(void)
{
  MX_ADC1_Init();
  MX_ADC3_Init();
  MX_I2C4_Init();
  SSD1306_Init();

  while (1)
  {
    uint32_t adcValue; // ADC value for voltage sensor
    uint32_t temperatureAdcValue; // ADC value for temperature sensor
    uint32_t voltageMv; // mV
    int32_t temperatureC; // Celsius
    int32_t speed; // HZ

    voltageMv = (adcValue * ADC_VREF_MV) / ADC_MAX_VALUE;
    temperatureC = __LL_ADC_CALC_TEMPERATURE(ADC_VREF_MV, temperatureAdcValue,
                                             LL_ADC_RESOLUTION_12B);
    speed = 5;

    printf("{\"adc_voltage_v\": %lu.%03lu, \"mcu_temperature_c\": %ld}\r\n",
           (unsigned long)(voltageMv / 1000U),
           (unsigned long)(voltageMv % 1000U),
           (long)temperatureC);

    SSD1306_ClearLinePart(2, 40, 99);
    SSD1306_ClearLinePart(3, 40, 99);
    SSD1306_ShowDecimal(40, 2, (float)voltageMv / 1000.0f, 1, 3, 16, 0);

    SSD1306_ClearLinePart(4, 40, 99);
    SSD1306_ClearLinePart(5, 40, 99);
    SSD1306_ShowNum(40,4,temperatureC,2,16,0);
    SSD1306_ClearLinePart(6, 40, 99);
    SSD1306_ClearLinePart(7, 40, 99);
    SSD1306_ShowNum(40,6,speed,3,16,0);

    HAL_Delay(1000/speed);
  }
}

保存代码。

效果

  • 点击左侧工具栏的 调试运行 按钮,点击上方的运行按钮,上传调试固件;
  • 待进入调试状态,点击悬浮工具栏的启动按钮,开始运行程序;
  • OLED 显示 A0 引脚的 ADC 电压(0-3.3V)以及 MCU 温度;

adc_oled.jpg

动态演示

adc_oled.gif

总结

本文介绍了 NUCLEO-H5E5ZJ 开发板驱动 OLED 显示 ADC 电压和 MCU 温度的项目设计,包括硬件连接、环境搭建、工程创建、参数配置、ADC 打印、OLED显示等流程,为相关产品的快速开发和应用设计提供了参考。

赞 收藏 评论0 发布时间:2026-10-23 17:06

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版