我刚刚开始学习如何使用 ST 的 HAL 对 ARM 微控制器进行编程。所以我有这段代码,它在输出比较模式下使用定时器生成 1khz 和 20khz 信号。一切都很好,我用示波器对其进行了测试,结果符合预期。问题在于 HAL_TIM_PeriodElapsedCallback() 应该在定时器溢出并切换 LED 时调用。LED 的配置是正确的。HAL_TIM_PeriodElapsedCallback() 被 HAL_TIM_IRQHandler(&htim3) 调用;每当定时器 3 的中断被触发时,例如定时器溢出时,都会调用它。HAL_TIM_IRQHandler(&htim3); 当输出比较寄存器与定时器“计数”寄存器匹配时也经常调用它,它调用 HAL_TIM_OC_DelayElapsedCallback()。这一切都有效,所以我知道 timer3 中断配置正确,但我无法弄清楚为什么当定时器溢出时没有调用正确的回调。我猜是输出比较触发的中断以某种方式与溢出中断混淆。我也尝试过使用调试器并遵循代码,但只是跳过了 HAL_TIM_OC_DelayElapsedCallback()。我已经包含了我的 main() 以及处理所有中断的 HAL_Timer 库中的相关代码。请帮我调试一下!PS。Nucleo_BSP_Init(); 只需配置时钟和 GPIO,因此我不会放置此代码,因为我知道 LED 可以工作,并且时钟是使用 CubeMX 配置的,所以应该没问题。我的猜测是输出比较触发的中断以某种方式与溢出中断混淆。我也尝试过使用调试器并遵循代码,但只是跳过了 HAL_TIM_OC_DelayElapsedCallback()。我已经包含了我的 main() 以及处理所有中断的 HAL_Timer 库中的相关代码。请帮我调试一下!PS。Nucleo_BSP_Init(); 只需配置时钟和 GPIO,因此我不会放置此代码,因为我知道 LED 可以工作,并且时钟是使用 CubeMX 配置的,所以应该没问题。我的猜测是输出比较触发的中断以某种方式与溢出中断混淆。我也尝试过使用调试器并遵循代码,但只是跳过了 HAL_TIM_OC_DelayElapsedCallback()。我已经包含了我的 main() 以及处理所有中断的 HAL_Timer 库中的相关代码。请帮我调试一下!PS。Nucleo_BSP_Init(); 只需配置时钟和 GPIO,因此我不会放置此代码,因为我知道 LED 可以工作,并且时钟是使用 CubeMX 配置的,所以应该没问题。请帮我调试一下!PS。Nucleo_BSP_Init(); 只需配置时钟和 GPIO,因此我不会放置此代码,因为我知道 LED 可以工作,并且时钟是使用 CubeMX 配置的,所以应该没问题。请帮我调试一下!PS。Nucleo_BSP_Init(); 只需配置时钟和 GPIO,因此我不会放置此代码,因为我知道 LED 可以工作,并且时钟是使用 CubeMX 配置的,所以应该没问题。
----------------MAIN CODE --------------------
#include "stm32f4xx_hal.h"
#include <nucleo_hal_bsp.h>
#include <string.h>
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;
void MX_TIM3_Init(void);
uint16_t computePulse(TIM_HandleTypeDef *htim, uint32_t chFrequency) {
uint32_t timFrequency= HAL_RCC_GetPCLK1Freq() / (htim->Instance->PSC + 1);
return (uint16_t)(timFrequency / chFrequency);
}
volatile uint16_t CH1_FREQ = 0;
volatile uint16_t CH2_FREQ = 0;
int main(void) {
HAL_Init();
Nucleo_BSP_Init();
MX_TIM3_Init();
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1);
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_2);
while (1);
}
/* TIM3 init function */
void MX_TIM3_Init(void) {
TIM_OC_InitTypeDef sConfigOC;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 2;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_OC_Init(&htim3);
CH1_FREQ = computePulse(&htim3, 1000);
CH2_FREQ = computePulse(&htim3, 20000);
sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
sConfigOC.Pulse = CH1_FREQ;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
sConfigOC.Pulse = CH2_FREQ;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) {
uint32_t pulse;
/* TIMx_CH1 toggling with frequency = 1KHz */
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
pulse = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
/* Set the Capture Compare Register value */
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, (pulse + CH1_FREQ));
}
/* TIM2_CH2 toggling with frequency = 20KHz */
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
pulse = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
/* Set the Capture Compare Register value */
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_2, (pulse + CH2_FREQ));
}
}
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef* htim_base) {
GPIO_InitTypeDef GPIO_InitStruct;
if(htim_base->Instance==TIM3) {
__TIM3_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
}
void TIM3_IRQHandler(void) {
HAL_TIM_IRQHandler(&htim3);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance == TIM3){
// HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
}
IRQ 处理程序代码,每当触发中断时都会被调用。
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
/* Capture compare 1 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET)
{
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
/* Input capture event */
if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
}
/* Capture compare 2 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
/* Input capture event */
if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
/* Capture compare 3 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
/* Input capture event */
if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
/* Capture compare 4 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
/* Input capture event */
if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
/* TIM Update event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
HAL_TIM_PeriodElapsedCallback(htim);
}
}
/* TIM Break input event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
HAL_TIMEx_BreakCallback(htim);
}
}
/* TIM Trigger detection event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
HAL_TIM_TriggerCallback(htim);
}
}
/* TIM commutation event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
HAL_TIMEx_CommutationCallback(htim);
}
}
}