STM32G070RB Nucleo-64 代码例程

知识库
知识库文档
/firmware/开发板/STM32G070RB Nucleo-64/STM32G070RB Nucleo-64 代码例程.md

文档

STM32G070RB Nucleo-64 代码例程

本文档覆盖 HAL 库例程,重点展示 G0 系列特色:HSI16 无晶振运行、LPUART 低功耗唤醒、双 Bank Flash OTA、Arduino 兼容编程。


一、STM32CubeIDE / HAL 库例程

1.1 64MHz HSI16 无晶振时钟配置

/* main.c - G070 使用 HSI16 + PLL = 64MHz(无需外部晶振!) */
#include "main.h"

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /* 使用 HSI16,不需要 HSE */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;  // HSI16 → PLL
    RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;           // ÷1 = 16MHz
    RCC_OscInitStruct.PLL.PLLN = 8;                       // ×8 = 128MHz
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;           // ÷2 = 64MHz
    RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;           // ÷2 = 64MHz (SYSCLK)
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;    // 64MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;     // 64MHz
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2WS);  // G0: 64MHz=2WS
}

1.2 LED 闪烁(板载 PA5 = Arduino D13)

/* G070 Nucleo LED Blink - 最简单的开始 */
#include "main.h"

static void MX_GPIO_Init(void)
{
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_5;       // LD1 用户LED
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

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

    while (1)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
        HAL_Delay(500);
    }
}

1.3 用户按键 + LED 交互

/* B1 按键 (PC13) 控制 LED (PA5) */
#include "main.h"

static void MX_GPIO_Init(void)
{
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* PA5 - LED 输出 */
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* PC13 - B1 按键输入(按下为低) */
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;  // 内部上拉
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

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

    while (1)
    {
        if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
        {
            HAL_Delay(20);  // 消抖
            if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
            {
                HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
                while (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET); // 等待释放
            }
        }
    }
}

1.4 USART2 虚拟串口通信(通过 ST-LINK VCP)

/* USART2 通过 ST-LINK VCP 与 PC 通信 */
/* PA2(TX), PA3(RX) - 已连接到板载 ST-LINK 虚拟串口 */
#include "main.h"
#include <stdio.h>

UART_HandleTypeDef huart2;

static void MX_USART2_UART_Init(void)
{
    huart2.Instance = USART2;
    huart2.Init.BaudRate = 115200;
    huart2.Init.WordLength = UART_WORDLENGTH_8B;
    huart2.Init.StopBits = UART_STOPBITS_1;
    huart2.Init.Parity = UART_PARITY_NONE;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart2);
}

/* printf 重定向到 USART2 */
int __io_putchar(int ch)
{
    HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 10);
    return ch;
}

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

    uint32_t count = 0;

    printf("STM32G070 Nucleo-64 Ready!\r\n");
    printf("System Clock: %lu Hz\r\n", HAL_RCC_GetSysClockFreq());

    while (1)
    {
        printf("Uptime: %lu seconds\r\n", count++);
        HAL_Delay(1000);
    }
}

1.5 LPUART 低功耗串口

/* LPUART1 - G0 特色:可在 STOP 模式下唤醒 MCU */
/* 典型应用:电池供电的传感器节点,平时休眠,串口收到数据时唤醒 */
#include "main.h"

LPUART_HandleTypeDef hlpuart1;

void LPUART1_Init(void)
{
    hlpuart1.Instance = LPUART1;
    hlpuart1.Init.BaudRate = 9600;          // LPUART 波特率有限
    hlpuart1.Init.WordLength = LPUART_WORDLENGTH_8B;
    hlpuart1.Init.StopBits = LPUART_STOPBITS_1;
    hlpuart1.Init.Parity = LPUART_PARITY_NONE;
    hlpuart1.Init.Mode = LPUART_MODE_TX_RX;
    hlpuart1.Init.HwFlowCtl = LPUART_HWCONTROL_NONE;
    hlpuart1.Init.OneBitSampling = LPUART_ONE_BIT_SAMPLE_DISABLE;
    hlpuart1.Init.ClockPrescaler = LPUART_PRESCALER_DIV1;
    hlpuart1.AdvancedInit.AdvFeatureInit = LPUART_ADVFEATURE_NO_INIT;
    HAL_LPUART_Init(&hlpuart1);

    /* 使能 LPUART 唤醒 STOP 模式 */
    HAL_LPUARTEx_EnableStopMode(&hlpuart1);
    __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);  /* 可选额外唤醒源 */
}

/* 进入 STOP 模式,等待 LPUART 唤醒 */
void Enter_StopMode(void)
{
    printf("Entering STOP mode...\r\n");
    HAL_Delay(10);

    /* 挂起 SysTick 避免唤醒 */
    HAL_SuspendTick();

    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

    /* 唤醒后恢复 */
    SystemClock_Config();  // 重新配置时钟(STOP 后 HSI/PLL 停了)
    HAL_ResumeTick();
    printf("Woken up by LPUART!\r\n");
}

1.6 I2C OLED + Arduino 兼容编程

/* 使用 Arduino 兼容引脚 A4(PB7-SDA), A5(PB6-SCL) 驱动 SSD1306 OLED */
#include "main.h"

I2C_HandleTypeDef hi2c1;

/* I2C1 初始化 - 与 Arduino Shield 引脚兼容 */
static void MX_I2C1_Init(void)
{
    hi2c1.Instance = I2C1;
    hi2c1.Init.Timing = 0x00707CBB;   // 100KHz @ 64MHz (CubeMX 自动计算)
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    HAL_I2C_Init(&hi2c1);
}

/* SSD1306 简单测试 */
void SSD1306_Test(void)
{
    uint8_t init_cmds[] = {
        0x00, 0xAE,        // Display OFF
        0x00, 0xD5, 0x80,  // Clock
        0x00, 0xA8, 0x3F,  // Mux
        0x00, 0xD3, 0x00,  // Offset
        0x00, 0x40,        // Start Line
        0x00, 0x8D, 0x14,  // Charge Pump
        0x00, 0x20, 0x00,  // Horizontal Mode
        0x00, 0xA1,        // Segment Remap
        0x00, 0xC8,        // COM Scan
        0x00, 0xDA, 0x12,  // COM Pins
        0x00, 0x81, 0xCF,  // Contrast
        0x00, 0xD9, 0xF1,  // Pre-charge
        0x00, 0xDB, 0x40,  // VCOMH
        0x00, 0xA4,        // Display All On Resume
        0x00, 0xA6,        // Normal Display
        0x00, 0xAF         // Display ON
    };

    for (int i = 0; i < sizeof(init_cmds); i += 2)
    {
        HAL_I2C_Master_Transmit(&hi2c1, 0x3C << 1,
                                &init_cmds[i + 1], 1, 100);
    }
}

1.7 ADC 读取(PA0 = Arduino A0)

/* ADC 读取模拟量,通过 VCP 输出 */
ADC_HandleTypeDef hadc1;

static void MX_ADC1_Init(void)
{
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;  // 64MHz
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    hadc1.Init.LowPowerAutoWait = DISABLE;
    hadc1.Init.LowPowerAutoPowerOff = DISABLE;
    hadc1.Init.ContinuousConvMode = DISABLE;
    hadc1.Init.NbrOfConversion = 1;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    HAL_ADC_Init(&hadc1);

    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_0;  // PA0
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;  // 长采样提高精度
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

float Read_ADC_Voltage(void)
{
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    uint32_t val = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    return val * 3.3f / 4096.0f;
}

二、Arduino IDE 编程(STM32duino)

Nucleo G070 同样支持 STM32duino,Board 选择 Nucleo-64 G070RB

/* Arduino 风格 - 完全兼容 Shield 生态 */
void setup()
{
    pinMode(PA5, OUTPUT);      // D13 用户 LED
    pinMode(PC13, INPUT_PULLUP); // B1 用户按键
    Serial.begin(115200);      // 通过 ST-LINK VCP
}

void loop()
{
    digitalWrite(PA5, !digitalRead(PA5));  // 翻转 LED
    Serial.println("Nucleo G070 with Arduino!");
    delay(500);
}

三、PlatformIO 配置

; platformio.ini - Nucleo G070RB
[env:nucleo_g070rb]
platform = ststm32
board = nucleo_g070rb
framework = arduino
; framework = stm32cube  ; 使用 HAL 框架
upload_protocol = stlink
monitor_speed = 115200

; 使用内置 ST-LINK,无需额外烧录器

四、STM32CubeProgrammer 拖拽烧录

Nucleo ST-LINK 支持大容量存储烧录:

1. 编译生成 .bin 文件
2. 将 Nucleo 通过 USB 连接到电脑
3. 电脑出现 "NODE_G070RB" 虚拟 U 盘
4. 拖拽 .bin 文件到该 U 盘
5. 自动烧录并复位运行

无需安装任何软件!这是最快最方便的烧录方式。

五、G0 系列特色功能总结

功能 说明
HSI16 ±1% 无需外部晶振即可可靠运行串口通信
LPUART 支持 STOP 模式唤醒,电池供电神器
双 Bank Flash 安全 OTA 固件升级
USB PD 3.0 支持 USB Power Delivery(需外部 PHY)
低功耗 STOP < 2μA, STANDBY < 0.5μA
快速 ADC 0.4μs 转换时间,2.5Msps

信息

路径
/firmware/开发板/STM32G070RB Nucleo-64/STM32G070RB Nucleo-64 代码例程.md
更新时间
2026/5/26