使用STM32 FMC HAL驱动并行DAC时触发HardFault问题求助
STM32F767 与 DAC8412 通信触发 HardFault 的解决方法
问题核心原因
- 总线宽度不匹配:你配置FMC为16位数据宽度,但代码中用
uint32_t(32位)类型直接访问外设地址,STM32的FMC不支持跨宽度的非对齐访问,连续写入4个32位数据后触发总线错误,进入HardFault。 - 数据格式不符合DAC要求:DAC8412需要12位数据+2位地址的14位组合,你直接写入32位正弦值,未按规范打包地址位与数据位。
- 地址未按需切换(可选):代码中
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
相关产品推荐
相关产品推荐

