文档
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 晶振及负载电容 |