STM32H743IIT6 Core Board 代码例程

知识库
知识库文档
/firmware/开发板/STM32H743IIT6 Core Board/STM32H743IIT6 Core Board 代码例程.md

文档

STM32H743IIT6 Core Board 代码例程

H743 的代码复杂度显著高于 F1/F4 系列,本文档重点展示:多域架构初始化、TCM 使用、Cache 一致性处理、LTDC LCD、ETH、16位 ADC、TouchGFX 集成。


一、STM32CubeIDE / HAL 库例程

1.1 480MHz 系统时钟 + MPU + Cache 初始化

/* main.c - H743 480MHz 完整初始化(CubeMX 生成 + 手动优化) */
#include "main.h"

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

    /* HSE 25MHz → PLL1 → 480MHz */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

    /* PLL1: 25 ÷ 5 × 192 ÷ 2 = 480MHz */
    RCC_OscInitStruct.PLL.PLLM = 5;
    RCC_OscInitStruct.PLL.PLLN = 192;
    RCC_OscInitStruct.PLL.PLLP = 2;
    RCC_OscInitStruct.PLL.PLLQ = 10;    // 48MHz for USB
    RCC_OscInitStruct.PLL.PLLR = 2;     // 480MHz for SYSCLK
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    /* 总线分频 */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2
                                | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_D3PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;   // D1 AHB=240MHz
    RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;  // APB3=120MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;  // APB1=120MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;  // APB2=120MHz
    RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;  // APB4=120MHz
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4WS);
}

/* MPU 配置:保护关键区域,DMA 缓冲区设为 non-cacheable */
void MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct = {0};
    HAL_MPU_Disable();

    /* 区域0: 整个 0x20000000-0x2001FFFF (SRAM1-3, D2域)
       设为 Device/StronglyOrdered 避免 DMA Cache 一致性问题 */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER0;
    MPU_InitStruct.BaseAddress = 0x20000000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
    MPU_InitStruct.SubRegionDisable = 0x0;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

/* 完整初始化流程 */
int main(void)
{
    /* 使能 FPU */
    SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));

    HAL_Init();
    SystemClock_Config();

    /* 使能 I-Cache 和 D-Cache */
    SCB_EnableICache();
    SCB_EnableDCache();

    /* MPU 配置(DMA 前必须配置) */
    MPU_Config();

    /* 验证系统时钟 */
    uint32_t sysclk = HAL_RCC_GetSysClockFreq();
    // sysclk 应为 480,000,000

    while (1)
    {
        // 应用逻辑
    }
}

1.2 TCM 内存使用(关键代码零等待执行)

/* 将时间关键的函数和数据放入 TCM */

/* DTCM:数据,零等待读写 */
__attribute__((section(".dtcm"))) volatile float fftBuffer[4096];
__attribute__((section(".dtcm"))) volatile int criticalCounter;

/* ITCM:代码,零等待执行 */
__attribute__((section(".itcm"))) void CriticalISR(void)
{
    // 高频中断处理,放在 ITCM 中零等待执行
    criticalCounter++;
}

/* 链接脚本需要添加对应 section(CubeMX 通常已配置):
   .dtcm (NOLOAD): { *(.dtcm) } > DTCM
   .itcm : { *(.itcm) } > ITCM
*/

1.3 DMA + Cache 一致性处理

/* H7 使用 DMA 必须处理 Cache 一致性 */
#include "main.h"

#define DMA_BUFFER_SIZE 1024

/* DMA 缓冲区放在 D2 域普通 SRAM(Non-Cacheable by MPU) */
/* 或手动维护 Cache 一致性 */
__attribute__((section(".dma_buffer"))) uint8_t dmaRxBuf[DMA_BUFFER_SIZE];
__attribute__((section(".dma_buffer"))) uint8_t dmaTxBuf[DMA_BUFFER_SIZE];

void UART_DMA_Example(UART_HandleTypeDef *huart)
{
    /* 发送:先 Clean DCache,将 Cache 数据写回内存 */
    memset(dmaTxBuf, 0xAA, DMA_BUFFER_SIZE);
    SCB_CleanDCache_by_Addr((uint32_t *)dmaTxBuf, DMA_BUFFER_SIZE);

    HAL_UART_Transmit_DMA(huart, dmaTxBuf, DMA_BUFFER_SIZE);

    /* 接收前:Invalidate DCache,确保读到的是内存最新数据 */
    HAL_UART_Receive_DMA(huart, dmaRxBuf, DMA_BUFFER_SIZE);
    HAL_Delay(100);  // 等待接收完成
    SCB_InvalidateDCache_by_Addr((uint32_t *)dmaRxBuf, DMA_BUFFER_SIZE);

    /* 现在可以安全读取 dmaRxBuf */
}

1.4 16位 ADC 高精度采集

/* H743 ADC 16位模式,配合 DMA */
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

#define ADC_SAMPLES 256
__attribute__((section(".dma_buffer"))) uint16_t adcData[ADC_SAMPLES];

static void MX_ADC1_Init(void)
{
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;   // ADC时钟 = 120MHz/2 = 60MHz
    hadc1.Init.Resolution = ADC_RESOLUTION_16B;          // 16位模式!
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    hadc1.Init.LowPowerAutoWait = DISABLE;
    hadc1.Init.ContinuousConvMode = DISABLE;
    hadc1.Init.NbrOfConversion = 1;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
    hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
    hadc1.Init.OversamplingMode = DISABLE;
    HAL_ADC_Init(&hadc1);

    /* 通道配置 */
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_0;                    // PA0
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;  // 16位需更长采样时间
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
    sConfig.Offset = 0;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

/* 16位精确电压计算 */
float ADC16_ToVoltage(uint16_t adcVal, float vref)
{
    return (float)adcVal * vref / 65535.0f;  // 16位=0~65535
}

1.5 LTDC + DMA2D 图形加速

/* LTDC 驱动 RGB565 LCD + Chrom-ART (DMA2D) 硬件加速 */
#include "main.h"

#define LCD_WIDTH  480
#define LCD_HEIGHT 272

/* 帧缓冲 - 通常放在 SDRAM(通过 FMC 外挂) */
__attribute__((section(".frame_buffer")))
uint16_t framebuf[LCD_WIDTH * LCD_HEIGHT];

/* DMA2D 快速清屏(硬件加速 Fill) */
void LCD_Clear(uint16_t color)
{
    DMA2D->CR = DMA2D_R2M;                    // 寄存器→内存模式
    DMA2D->OPFCCR = DMA2D_OUTPUT_RGB565;      // RGB565 输出
    DMA2D->OOR = 0;                           // 输出偏移
    DMA2D->OMAR = (uint32_t)framebuf;         // 输出地址
    DMA2D->NLR = (LCD_WIDTH << 16) | LCD_HEIGHT; // 宽×高
    DMA2D->OCOLR = color;                     // 填充颜色

    DMA2D->CR |= DMA2D_CR_START;
    while (DMA2D->CR & DMA2D_CR_START);       // 等待完成
}

/* DMA2D 快速位图绘制(硬件加速 Blit) */
void LCD_DrawBitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h,
                    const uint16_t *bitmap)
{
    DMA2D->CR = DMA2D_M2M_PFC;                // 内存→内存 + 像素格式转换
    DMA2D->FGMAR = (uint32_t)bitmap;          // 前景(位图)
    DMA2D->BGMAR = (uint32_t)(framebuf + y * LCD_WIDTH + x); // 背景
    DMA2D->OMAR = (uint32_t)(framebuf + y * LCD_WIDTH + x);  // 输出
    DMA2D->FGOR = 0;
    DMA2D->BGOR = LCD_WIDTH - w;
    DMA2D->OOR = LCD_WIDTH - w;
    DMA2D->FGPFCCR = DMA2D_INPUT_RGB565;
    DMA2D->BGPFCCR = DMA2D_INPUT_RGB565;
    DMA2D->OPFCCR = DMA2D_OUTPUT_RGB565;
    DMA2D->NLR = (w << 16) | h;

    DMA2D->CR |= DMA2D_CR_START;
    while (DMA2D->CR & DMA2D_CR_START);
}

二、TouchGFX 集成(GUI 开发)

/* TouchGFX 是 ST 官方推荐的 GUI 框架,与 CubeMX 深度集成 */

/* CubeMX 配置步骤:
   1. 使能 LTDC、DMA2D、FMC(SDRAM)、CRC
   2. Middleware → TouchGFX → 使能
   3. 配置 LTDC 时序匹配你的 LCD 屏幕
   4. 生成代码,在 CubeIDE 中用 TouchGFX Designer 编辑 UI
*/

/* TouchGFX 自动生成的入口在 TouchGFX/target/generated/ */
/* 用户只需关注 MVP 模式:

   Model:  数据层(传感器数据、通信数据)
   View:   UI 界面设计(TouchGFX Designer 拖拽完成)
   Presenter:  Model ↔ View 的桥梁
*/

// Screen1View.cpp(简化示例)
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
}

void Screen1View::handleTickEvent()
{
    // 每帧调用,更新传感器数据到 UI
    float temp = readTemperature();
    Unicode::snprintfFloat(textTempBuffer, TEXTTEMP_SIZE, "%.1f", temp);
    textTemp.invalidate();
}

三、以太网 (ETH) + LwIP 例程

/* CubeMX 配置:ETH → RMII, LwIP → 使能 */
#include "main.h"
#include "lwip.h"
#include "lwip/tcp.h"

/* TCP Echo 服务器 */
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
    /* 设置回调 */
    tcp_recv(pcb, tcp_echoserver_recv);
    return ERR_OK;
}

static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *pcb,
                                  struct pbuf *p, err_t err)
{
    if (p != NULL) {
        tcp_write(pcb, p->payload, p->len, TCP_WRITE_FLAG_COPY);
        tcp_output(pcb);
        pbuf_free(p);
    } else {
        tcp_close(pcb);  // 客户端断开
    }
    return ERR_OK;
}

void TCP_Server_Init(void)
{
    struct tcp_pcb *pcb = tcp_new();
    tcp_bind(pcb, IP_ADDR_ANY, 5000);  // 监听 5000 端口
    pcb = tcp_listen(pcb);
    tcp_accept(pcb, tcp_echoserver_accept);
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_LWIP_Init();       // CubeMX 生成
    TCP_Server_Init();

    while (1)
    {
        MX_LWIP_Process();  // 每循环调用一次处理网络栈
    }
}

四、PlatformIO 配置

; platformio.ini - H743 Core Board
[env:h743_core]
platform = ststm32
board = genericSTM32H743II
framework = stm32cube      ; 推荐使用 HAL 框架
; framework = arduino       ; 也有 Arduino 支持但不完整
upload_protocol = stlink
debug_tool = stlink
monitor_speed = 115200

build_flags =
    -D CORE_CM7
    -D USE_HAL_DRIVER
    -D STM32H743xx
    -Wl,--print-memory-usage   ; 打印内存使用统计

五、H7 开发排坑指南

常见问题 原因 解决方法
HardFault 启动瞬间 Flash Latency 不足 480MHz 需要 FLASH_LATENCY_4WS,从 Flash 执行还需开启 ART
DMA 数据异常 Cache 不一致 使用 non-cacheable 内存区或手动 Clean/Invalidate
外设不工作 D3 域时钟未使能 检查 __HAL_RCC_xxx_CLK_ENABLE(),H7 多域架构需分别使能
ETH 不通信 MPU 未配置 DMA 描述符区域 ETH DMA 描述符必须 non-cacheable
ADC 读数噪声大 采样时间太短 16位模式至少 387.5 ADC cycles
无法烧录 Flash 双 Bank 保护 先用 CubeProgrammer 全片擦除
PLL 不锁 HSE 起振问题 检查 25MHz 晶振及负载电容

信息

路径
/firmware/开发板/STM32H743IIT6 Core Board/STM32H743IIT6 Core Board 代码例程.md
更新时间
2026/5/26