You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用STM32 FMC HAL驱动并行DAC时触发HardFault问题求助

STM32F767 与 DAC8412 通信触发 HardFault 的解决方法

问题核心原因

  1. 总线宽度不匹配:你配置FMC为16位数据宽度,但代码中用uint32_t(32位)类型直接访问外设地址,STM32的FMC不支持跨宽度的非对齐访问,连续写入4个32位数据后触发总线错误,进入HardFault。
  2. 数据格式不符合DAC要求:DAC8412需要12位数据+2位地址的14位组合,你直接写入32位正弦值,未按规范打包地址位与数据位。
  3. 地址未按需切换(可选):代码中address固定为0x60000000,若需切换DAC的4个输出通道,未做对应调整。

具体修正步骤

1. 调整数据类型匹配FMC宽度

将缓冲区和外设访问类型改为uint16_t,适配16位FMC配置:

#define SRAM_BANK_ADDR      ((uint32_t)0x60000000)
#define RESOLUTION_T        ((uint32_t)0x1000)
#define RESOLUTION_Y        ((uint32_t)0x1000)
// 改用16位缓冲区存储DAC需要的打包数据
uint16_t aTxBuffer[RESOLUTION_T];

2. 修正正弦数据打包逻辑

填充缓冲区时,把12位正弦数据与2位DAC地址位打包成16位值:

static void Fill_Buffer(uint16_t *pBuffer, uint32_t res_T, uint32_t res_Y)
{
  uint32_t tmpIndex = 0;
  double sinVal;
  uint16_t dacData;
  // 选择目标通道:通道0(00)→0x0000,通道1(01)→0x4000,通道2(10)→0x8000,通道3(11)→0xC000
  const uint16_t CHANNEL_MASK = 0x0000; 

  for (tmpIndex = 0; tmpIndex < res_T; tmpIndex++ )
  {
    // 计算12位范围的正弦值(0~4095)
    sinVal = round((sin(M_TWOPI*tmpIndex/res_T)+1)*res_Y/2);
    // 打包:高2位为通道地址,低12位为数据
    dacData = CHANNEL_MASK | ((uint16_t)sinVal & 0x0FFF);
    pBuffer[tmpIndex] = dacData;
  }
}

3. 修正外设写入逻辑

用16位指针访问FMC地址,确保总线访问宽度匹配:

uint32_t address = SRAM_BANK_ADDR;
for (uint32_t i = 0; i < RESOLUTION_T; i++ )
{
  // 16位对齐访问,避免总线错误
  *(__IO uint16_t*) address = aTxBuffer[i];
  // 若需切换通道,可在此修改address或调整CHANNEL_MASK重新打包数据
}

4. 验证FMC配置细节

  • 确认FMC的Data Width设置为16-bit,Memory Type为SRAM
  • 检查FMC时序参数(地址建立时间、数据保持时间)是否符合DAC8412的规格书要求
  • 确认DAC的2位地址线与FMC对应地址线连接正确

调试建议

若仍触发HardFault,可通过CubeIDE调试查看SCB->HFSR寄存器的值,定位具体错误类型(比如总线错误、存储管理错误);也可先尝试单次写入16位数据,验证通信链路正常后再进行连续写入。

内容的提问来源于stack exchange,提问作者bibo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 09:05:39