STM32 - 为啥代码没有像它应该的那样修改寄存器?

Posted

技术标签:

【中文标题】STM32 - 为啥代码没有像它应该的那样修改寄存器?【英文标题】:STM32 - why the code does not modify the registers like it is supposed to?STM32 - 为什么代码没有像它应该的那样修改寄存器? 【发布时间】:2020-01-09 15:45:09 【问题描述】:

我正在使用带有 HAL 库的 STM32F072C8T6 微控制器。我编写了一个程序,通过微控制器的 DAC 引脚发送模拟电压,但它不起作用。我运行了调试器,当我单步执行代码时,我可以看到没有任何 DAC 寄存器发生变化。有谁知道我是否遗漏了代码中的某些内容?

我从其他人那里接手了这个项目。他从 CubeMX 生成项目配置。但是,我没有项目 .ioc 文件(CubeMX 文件),所以我必须手动添加 DAC 函数,而不是使用 CubeMX。我所做的是我取消了 stm32f0xx_hal_conf.h 中的 #define HAL_DAC_MODULE_ENABLED 的注释,并添加了 stm32f0xx_hal_dac.cstm32f0xx_hal_dac_ex.c 进入 Drivers 文件夹。

这是 main.c 中 DAC 的代码:

DAC_HandleTypeDef hdac;
int main(void)
  HAL_Init();
  SystemClock_Config();
  DAC_ChannelConfTypeDef sConfig = 0;
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  
    Error_Handler();
  
  sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  
    Error_Handler();
  
  HAL_DAC_Start( &hdac, DAC_CHANNEL_1);
  HAL_DAC_SetValue( &hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);
  while(1)
  

DAC 输出应为 1/2*3.3V = 1.65V。但是实际电压为 0V,所有 DAC 寄存器保持为 0x00。我还尝试使用 CubeMX 创建一个新项目,DAC 与这个新项目完美配合,因此硬件不是问题。

【问题讨论】:

您确定正确链接了 DAC 功能吗?如果您的调试器支持单步执行代码,您确定执行一直通过循环吗?您能否正确地进入 HAL DAC 功能,还是调试器会感到困惑?当出现故障时Error_Handler() 的预期行为是什么?您看到这种行为了吗? 我以前没有使用过这些 MC 或 CubeMX,但是 MC 构建系统可能对它们如何构建和链接代码非常挑剔。我会怀疑你的手工工作只是为了让它编译。另外,请考虑在Electrical Engineering Stack Exchange 上打开嵌入式问题。这是这里的主题,但他们在那里做了很多低级编程。如果您移动此问题,请确保在 SO 上删除此问题,以免它在 SE 网络内的多个站点上重复。 @skrrgwasme:我可以正确地进入 HAL DAC 功能。我什至尝试直接在主文件中修改 DAC 寄存器,但它没有改变。 @cuckoo 你在哪个 IDE 上工作?,我认为HAL_DAC_SetValue( &hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048); 专注于它的论点是错误的,用 CubeMX 软件制作一个项目并使用 DAC 模块,然后看看如何正确启动和更改 DAC 值。 openstm32.org/forumthread2014 【参考方案1】:

为 RCC 中的 DAC 启用时钟。您的微控制器参考手册的复位和时钟控制一章中记录了应该设置哪个寄存器的确切位。

只要一个外设的时钟没有使能,它的所有寄存器都读为0,这个外设就不能使用了。

【讨论】:

我使用过的每一个基于 ARM 的微控制器都包含时钟切换逻辑,它会禁用各种模块的时钟信号,直到它们被明确启用,从而最大限度地减少未使用模块的功耗.在某些微控制器中,尝试访问已断电模块的寄存器可能会触发硬故障中断(其默认处理程序是分支到自身指令),而在控制器中,写入将被忽略,而读取则为零。我经常想知道,如果有一个控制器会导致访问插入等待状态,而... ...运行时钟足够长的时间来执行访问。如果例如系统时钟以 16MHz 运行,外围设备将以 4,000x/秒的速度被访问,它不需要时钟,除非在被访问时,每次访问都会打开时钟电源四个周期,每个外围设备时钟运行 16,000 个周期第二个将占用持续打开它的一小部分功率。但是,我从未见过外围设备这样做。 @supercat 外设必须有时钟才能完成它们的工作,而不仅仅是访问它们的寄存器。 GPIO 端口可以工作,在访问数据寄存器时“及时”对引脚进行采样,但它不再触发中断(每个 GPIO 引脚都可以配置为检测边沿并在 STM32 上触发中断)。在将数据移入和移出的通信端口上根本没有意义。 大多数外围设备在任何给定时间都知道它们有需要做的事情,或者如果输入处于特定状态,它们就会有需要做的事情。如果每个外设都向时钟分配模块提供一个同步和异步信号,表明它是否有任何有趣的事情要做,那么时钟模块可以将异步信号传递给一个双同步器,该双同步器是无条件激活的(但是,它只是位于时钟模块,不会消耗太多功率),并且只提供模块中的其余寄存器...... ...如果他们有什么有趣的事情要做。因此,UART 的发送端可以确保 UART 在发送最后一位数据之前一直保持时钟,而接收端可以确保如果输入状态与预期不同或正在处理验证一个起始位或接收一个字节,但是当这些事情都没有发生时,系统中只有两个与 UART 相关的寄存器(时钟模块中的同步器)需要时钟,这应该比时钟整体便宜得多UART。

以上是关于STM32 - 为啥代码没有像它应该的那样修改寄存器?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在STM32上不能通过SPI读取寄存器?

STM32串口波特率怎么设置?使用库直接设置吗?像51那样寄存器的设置?

STM32 - 修改 SYSCFG_UR2 寄存器

stm32修改PWM频率的同时,占空比不变

stm32f3发现usart没有发送

我应该在STM32中使用啥RTC备份寄存器?