(STM32) 是否可以仅使用Timer1、CH1和CH2捕获两个不同的信号?
(STM32) Is it possible to capture two different signals using Timer1, CH1 and CH2 only?
我目前正在做一个项目,我正在尝试测量连接到 Timer1(通道 1 和通道 2)的两个不同信号的占空比和频率
PE9 ------> TIM1_CH1
PE11 ------> TIM1_CH2
我的计划是每 100 毫秒在 CH1 和 CH2 之间切换一次,调用一个名为 PwmInput_SwitchChannels(BOOL) 的函数,其中包含每个通道的正确配置。在中断函数中,我想捕获值并将它们存储在 pwm_capture 类型的两个元素的数组中。
typedef struct
{
__IO UInt16 uhIC2Value;
__IO UInt16 uhDutyCycle;
__IO UInt32 uwFrequency;
}
pwm_capture;
pwm_capture input_capture[2];
问题是 1 个通道的捕获值与真实值不匹配,这似乎是 PwmInput_SwitchChannels 中的问题。
当我独立测试两个通道时,代码运行良好,中断功能正在发挥作用。
#define PIN18_PWM_A ((BOOL) 0)
#define PIN19_PWM_B ((BOOL) 1)
typedef struct
{
__IO UInt16 uhIC2Value;
__IO UInt16 uhDutyCycle;
__IO UInt32 uwFrequency;
}
pwm_capture;
pwm_capture input_capture[2];
BOOL Tim1_Channels = 0;
UInt16 counter_pwm = 0;
void HalTim_MainFunction(void)
{
if ( FALSE != rb_InitStatus )
{
counter_pwm++;
if(counter_pwm % 100 == 0)
{
Tim1_Channels = ! Tim1_Channels;
PwmInput_SwitchChannels(Tim1_Channels);
}
}
else {
;
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1)
{
switch(Tim1_Channels){
case PIN18_PWM_A:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
/* Get the Input Capture value */
input_capture[0].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
if (input_capture[0].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[0].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)) * 100) / input_capture[0].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[0].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[0].uhIC2Value;
}
else
{
input_capture[0].uhDutyCycle = 0;
input_capture[0].uwFrequency = 0;
}
}
break;
}
case PIN19_PWM_B:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
/* Get the Input Capture value */
input_capture[1].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (input_capture[1].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[1].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)) * 100) / input_capture[1].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[1].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[1].uhIC2Value;
}
else
{
input_capture[1].uhDutyCycle = 0;
input_capture[1].uwFrequency = 0;
}
}
break;
}
default:
Error_Handler();
}
}
}
void PwmInput_SwitchChannels(BOOL aux)
{
TIM_SlaveConfigTypeDef sSlaveConfig_aux = {0};
TIM_MasterConfigTypeDef sMasterConfig_aux = {0};
TIM_IC_InitTypeDef sConfigIC_aux = {0};
/*##-4- Stop the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Stop_IT(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/*##-5- Stop the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Stop_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
switch (aux){
case PIN18_PWM_A:
{
sSlaveConfig_aux.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig_aux.InputTrigger = TIM_TS_TI2FP2;
sSlaveConfig_aux.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig_aux.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig_aux) != HAL_OK)
{
Error_Handler();
}
sMasterConfig_aux.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig_aux.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig_aux) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC_aux.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC_aux.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
break;
}
case PIN19_PWM_B:
{
sSlaveConfig_aux.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig_aux.InputTrigger = TIM_TS_TI1FP1;
sSlaveConfig_aux.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig_aux.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig_aux) != HAL_OK)
{
Error_Handler();
}
sMasterConfig_aux.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig_aux.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig_aux) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC_aux.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC_aux.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
break;
}
default:
Error_Handler();
/*##-4- Start the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/*##-5- Start the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
}
}
我的目的是在不影响结果和性能的情况下,在两个通道之间正确切换(由于硬件限制,仅使用 Tim1_CH1 和 Tim1_CH2)。
一个可能的原因是 Tim1_Channels
未声明 [=11=]。它在主函数中写入,并在中断处理程序中访问。缺少 volatile
限定符,没有什么可以阻止优化器将值保存在寄存器中,并且永远不会将其写回内存。据优化器所知,访问值的中断处理程序永远不会从主程序中调用。
我通过将以下变量声明为 volatile 以及修改中断函数中的代码解决了这个问题
__IO pwm_capture input_capture[2] = {{0}, {0}};
__IO BOOL Tim1_Channels = 0;
__IO UInt16 counter_pwm = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1)
{
switch(Tim1_Channels){
case PIN18_PWM_A:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
/* Get the Input Capture value */
input_capture[0].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (input_capture[0].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[0].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)) * 100) / input_capture[0].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[0].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[0].uhIC2Value;
}
else
{
input_capture[0].uhDutyCycle = 0;
input_capture[0].uwFrequency = 0;
}
}
break;
}
case PIN19_PWM_B:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
/* Get the Input Capture value */
input_capture[1].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (input_capture[1].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[1].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)) * 100) / input_capture[1].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[1].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[1].uhIC2Value;
}
else
{
input_capture[1].uhDutyCycle = 0;
input_capture[1].uwFrequency = 0;
}
}
break;
}
default:
Error_Handler();
}
}
}
我目前正在做一个项目,我正在尝试测量连接到 Timer1(通道 1 和通道 2)的两个不同信号的占空比和频率 PE9 ------> TIM1_CH1 PE11 ------> TIM1_CH2
我的计划是每 100 毫秒在 CH1 和 CH2 之间切换一次,调用一个名为 PwmInput_SwitchChannels(BOOL) 的函数,其中包含每个通道的正确配置。在中断函数中,我想捕获值并将它们存储在 pwm_capture 类型的两个元素的数组中。
typedef struct
{
__IO UInt16 uhIC2Value;
__IO UInt16 uhDutyCycle;
__IO UInt32 uwFrequency;
}
pwm_capture;
pwm_capture input_capture[2];
问题是 1 个通道的捕获值与真实值不匹配,这似乎是 PwmInput_SwitchChannels 中的问题。 当我独立测试两个通道时,代码运行良好,中断功能正在发挥作用。
#define PIN18_PWM_A ((BOOL) 0)
#define PIN19_PWM_B ((BOOL) 1)
typedef struct
{
__IO UInt16 uhIC2Value;
__IO UInt16 uhDutyCycle;
__IO UInt32 uwFrequency;
}
pwm_capture;
pwm_capture input_capture[2];
BOOL Tim1_Channels = 0;
UInt16 counter_pwm = 0;
void HalTim_MainFunction(void)
{
if ( FALSE != rb_InitStatus )
{
counter_pwm++;
if(counter_pwm % 100 == 0)
{
Tim1_Channels = ! Tim1_Channels;
PwmInput_SwitchChannels(Tim1_Channels);
}
}
else {
;
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1)
{
switch(Tim1_Channels){
case PIN18_PWM_A:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
/* Get the Input Capture value */
input_capture[0].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
if (input_capture[0].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[0].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)) * 100) / input_capture[0].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[0].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[0].uhIC2Value;
}
else
{
input_capture[0].uhDutyCycle = 0;
input_capture[0].uwFrequency = 0;
}
}
break;
}
case PIN19_PWM_B:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
/* Get the Input Capture value */
input_capture[1].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (input_capture[1].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[1].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)) * 100) / input_capture[1].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[1].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[1].uhIC2Value;
}
else
{
input_capture[1].uhDutyCycle = 0;
input_capture[1].uwFrequency = 0;
}
}
break;
}
default:
Error_Handler();
}
}
}
void PwmInput_SwitchChannels(BOOL aux)
{
TIM_SlaveConfigTypeDef sSlaveConfig_aux = {0};
TIM_MasterConfigTypeDef sMasterConfig_aux = {0};
TIM_IC_InitTypeDef sConfigIC_aux = {0};
/*##-4- Stop the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Stop_IT(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/*##-5- Stop the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Stop_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
switch (aux){
case PIN18_PWM_A:
{
sSlaveConfig_aux.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig_aux.InputTrigger = TIM_TS_TI2FP2;
sSlaveConfig_aux.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig_aux.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig_aux) != HAL_OK)
{
Error_Handler();
}
sMasterConfig_aux.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig_aux.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig_aux) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC_aux.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC_aux.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
break;
}
case PIN19_PWM_B:
{
sSlaveConfig_aux.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig_aux.InputTrigger = TIM_TS_TI1FP1;
sSlaveConfig_aux.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig_aux.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig_aux) != HAL_OK)
{
Error_Handler();
}
sMasterConfig_aux.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig_aux.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig_aux) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC_aux.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC_aux.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sConfigIC_aux.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC_aux.ICSelection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC_aux, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
break;
}
default:
Error_Handler();
/*##-4- Start the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/*##-5- Start the Input Capture in interrupt mode ##########################*/
if (HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
}
}
我的目的是在不影响结果和性能的情况下,在两个通道之间正确切换(由于硬件限制,仅使用 Tim1_CH1 和 Tim1_CH2)。
一个可能的原因是 Tim1_Channels
未声明 [=11=]。它在主函数中写入,并在中断处理程序中访问。缺少 volatile
限定符,没有什么可以阻止优化器将值保存在寄存器中,并且永远不会将其写回内存。据优化器所知,访问值的中断处理程序永远不会从主程序中调用。
我通过将以下变量声明为 volatile 以及修改中断函数中的代码解决了这个问题
__IO pwm_capture input_capture[2] = {{0}, {0}};
__IO BOOL Tim1_Channels = 0;
__IO UInt16 counter_pwm = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1)
{
switch(Tim1_Channels){
case PIN18_PWM_A:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
/* Get the Input Capture value */
input_capture[0].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (input_capture[0].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[0].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)) * 100) / input_capture[0].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[0].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[0].uhIC2Value;
}
else
{
input_capture[0].uhDutyCycle = 0;
input_capture[0].uwFrequency = 0;
}
}
break;
}
case PIN19_PWM_B:
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
/* Get the Input Capture value */
input_capture[1].uhIC2Value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (input_capture[1].uhIC2Value != 0)
{
/* Duty cycle computation */
input_capture[1].uhDutyCycle = ((HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)) * 100) / input_capture[1].uhIC2Value;
/* uwFrequency computation
TIM1 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
input_capture[1].uwFrequency = (HAL_RCC_GetHCLKFreq()) / input_capture[1].uhIC2Value;
}
else
{
input_capture[1].uhDutyCycle = 0;
input_capture[1].uwFrequency = 0;
}
}
break;
}
default:
Error_Handler();
}
}
}