STM32H7 FMC同步模式NOR Flash时序参数逐位计算与示波器验证实战
1. 同步模式时序原理
STM32H7的FMC(Flexible Memory Controller)支持同步模式访问NOR Flash,此时FMC输出时钟FMC_CLK,数据在时钟边沿采样。关键参数:
- CLKDIV:FMC_CLK分频系数,FMC_CLK = HCLK / (CLKDIV + 1)。
- DATAST:数据建立时间,以FMC_CLK周期为单位,表示读/写数据有效到下一个时钟边沿的延迟。
- ADDHLD:地址保持时间,以HCLK周期为单位,表示地址有效到数据相位开始的延迟。
同步读时序:地址在ADDHLD后有效,经过DATAST个FMC_CLK周期后数据被采样。写时序类似,但数据由FMC驱动。
2. 逐位计算步骤
假设HCLK = 200MHz,NOR Flash要求:
- tCLK ≥ 10ns(FMC_CLK周期)
- 读数据建立时间tDS ≥ 15ns
- 地址保持时间tAH ≥ 5ns
2.1 计算CLKDIV
FMC_CLK周期 = (CLKDIV + 1) * HCLK周期。HCLK周期 = 5ns。要求FMC_CLK周期 ≥ 10ns,则CLKDIV + 1 ≥ 2,取CLKDIV = 1(FMC_CLK = 100MHz,周期10ns)。
2.2 计算DATAST
DATAST需满足:DATAST * FMC_CLK周期 ≥ tDS。tDS = 15ns,FMC_CLK周期 = 10ns,则DATAST ≥ 1.5,取整为2。
2.3 计算ADDHLD
ADDHLD以HCLK周期为单位:ADDHLD * HCLK周期 ≥ tAH。tAH = 5ns,HCLK周期 = 5ns,则ADDHLD ≥ 1,取1。
3. 完整配置代码
#include "stm32h7xx_hal.h"
FMC_NORSRAM_TimingTypeDef Timing = {0};
FMC_NORSRAM_InitTypeDef Init = {0};
void FMC_Init(void) {
// 使能FMC时钟和GPIO时钟
__HAL_RCC_FMC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
// 配置GPIO为复用推挽,高速
GPIO_InitTypeDef GPIO_Init = {0};
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_Init.Alternate = GPIO_AF12_FMC;
// 地址线A0-A25, 数据线D0-D15, 控制线等(根据实际连接)
// 此处省略具体引脚配置,需参考原理图
// FMC NOR/SRAM 初始化
Init.NSBank = FMC_NORSRAM_BANK1;
Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
Init.MemoryType = FMC_MEMORY_TYPE_NOR;
Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE; // 同步模式使能
Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
HAL_FMC_NORSRAM_Init(&hfmc, &Init);
// 时序配置
Timing.ClockDivision = 1; // CLKDIV = 1
Timing.DataLatency = 2; // DATAST = 2
Timing.AddressSetupTime = 1; // ADDHLD = 1
Timing.AddressHoldTime = 0; // 同步模式忽略
Timing.DataSetupTime = 2; // 同DATAST
Timing.BusTurnAroundDuration = 0;
HAL_FMC_NORSRAM_Timing_Init(&hfmc, &Timing, FMC_NORSRAM_BANK1);
// 使能FMC控制器
__HAL_FMC_NORSRAM_ENABLE(&hfmc, FMC_NORSRAM_BANK1);
}
4. 示波器验证方法
- 测量FMC_CLK频率:探头接FMC_CLK引脚,确认周期为10ns(100MHz)。
- 测量读时序:触发FMC_CLK上升沿,观察地址线、数据线。地址应在ADDHLD后稳定,数据在DATAST个时钟后有效。
- 测量写时序:类似,检查数据在时钟边沿前稳定。
- 调整参数:若数据建立不足,增大DATAST;若地址保持不足,增大ADDHLD。
5. 注意事项
- CLKDIV必须保证FMC_CLK不超过Flash最大频率。
- DATAST和ADDHLD需留有余量,考虑PCB走线延迟。
- 同步模式下,连续时钟模式可提高吞吐量。
- 使用HAL库时,注意Timing结构体成员对应关系。
- 验证时使用高带宽示波器(≥500MHz)和低电容探头。
通过逐位计算和示波器验证,可确保FMC与NOR Flash稳定通信,发挥STM32H7高性能优势。