STM32CubeMX | STM32使用HAL库进行脉冲宽度和周期测量

STM32CubeMX | STM32使用HAL库进行脉冲宽度和周期测量


使用芯片:STM32F103RCT6

思路:定时器设置为1MHZ的计数频率,定时计数器增加一就是增加1us

① 首先设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;
② 然后切换为下降沿捕获,捕获下降沿记录此刻的时间计数值;
③ 最后设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;**

对于16bit定时器,最大可计数0xFFFF,也就是65535us,那么:高电平持续的时间 = 定时器溢出计数 * 0xFFFF + 当前计数值

对于32bit定时器,最大可计数0xFFFFFFFF,也就是4294.967295s,这个时间足够测量脉冲宽度的了,那么:高电平持续的时间 = 当前计数值

高电平持续的时间 = ② - ①

周期 = ③ - ①


定时器配置

设置定时器2的计数频率为1MHz,输入捕获使用通道一,也就是PA0引脚,将PA0引脚设置为下拉模式,目的是为了在空闲时间保持信号稳定:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


中断分组设置

在这里插入图片描述


代码配置

tim.c中添加如下代码:


__IO uint32_t TIM2_TIMEOUT_COUNT = 0;			///< 定时器2定时溢出计数
uint32_t TIM2_CAPTURE_BUF[3]   = {0, 0, 0};		///< 分别存储上升沿计数、下降沿计数、下个上升沿计数
__IO uint8_t TIM2_CAPTURE_STA = 0xFF;			///< 状态标记

/**
 * 设置TIM2输入捕获极性
 * @param TIM_ICPolarity:
 *        TIM_INPUTCHANNELPOLARITY_RISING  :上升沿捕获
 *        TIM_INPUTCHANNELPOLARITY_FALLING :下降沿捕获
 *        TIM_INPUTCHANNELPOLARITY_BOTHEDGE:上升沿和下降沿都捕获
 */
inline void TIM2_SetCapturePolarity(uint32_t TIM_ICPolarity)
{
    htim2.Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
    htim2.Instance->CCER |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
}

/// 定时器2时间溢出回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == htim2.Instance)
    {
        TIM2_TIMEOUT_COUNT++;										// 溢出次数计数
    }
}

///< 输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == htim2.Instance)
    {
        switch (TIM2_CAPTURE_STA)
        {
        case 1:
        {
            printf("准备捕获下降沿...\r\n");
            TIM2_CAPTURE_BUF[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
            TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_FALLING);					// 设置为下降沿触发
            TIM2_CAPTURE_STA++;
            break;
        }
        case 2:
        {
            printf("准备捕获下个上升沿...\r\n");
            TIM2_CAPTURE_BUF[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
            TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);					// 设置为上升沿触发
            TIM2_CAPTURE_STA++;
            break;
        }
        case 3:
        {
            printf("捕获结束...\r\n");
            printf("# end ----------------------------------------------------\r\n");
            TIM2_CAPTURE_BUF[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
            HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1);									// 停止捕获
            HAL_TIM_Base_Stop_IT(&htim2);												// 停止定时器更新中断
            TIM2_CAPTURE_STA++;
            break;
        }
        default:
            break;
        }
    }
}

///< TIM2轮训状态切换
inline void TIM2_Poll(void)
{
    switch (TIM2_CAPTURE_STA)
    {
    case 0:
    {
        printf("# start ----------------------------------------------------\r\n");
        printf("准备捕获上升沿...\r\n");
        TIM2_TIMEOUT_COUNT = 0;
        __HAL_TIM_SET_COUNTER(&htim2, 0);											// 清除定时器2现有计数
        memset(TIM2_CAPTURE_BUF, 0, sizeof(TIM2_CAPTURE_BUF));						// 清除捕获计数
        TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);					// 设置为上升沿触发
        HAL_TIM_Base_Start_IT(&htim2);												// 启动定时器更新中断
        HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);									// 启动捕获中断
        TIM2_CAPTURE_STA++;
        break;
    }

    case 4:
    {
        uint32_t high  = TIM2_CAPTURE_BUF[1] - TIM2_CAPTURE_BUF[0];
        uint32_t cycle = TIM2_CAPTURE_BUF[2] - TIM2_CAPTURE_BUF[0];
        float frq = 1.0 / (((float)cycle) / 1000000.0);
        TIM2_CAPTURE_STA++;

        printf("\r\n\r\n");
        printf("################################# START #########################################\r\n");
        printf("高电平持续时间:%dms\r\n", high / 1000);
        printf("周期          :%dms\r\n", cycle / 1000);
        printf("频率          :%fHz\r\n", frq);
        printf("################################## END ##########################################\r\n\r\n");
        break;
    }

    default:
        break;
    }
}

main.c:

int main()
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    DEBUG_UART_Init();
    MX_TIM2_Init();
    printf("================================ 系统运行! ================================  \r\n");
    while(1)
    {
        TIM2_Poll();
        DEBUG_UART_RecvHandler();
    }
}

说明:串口一接串口调试助手,勾选发送新行,向单片机发送任意字符以此来启动输入捕获。


ends…

  • 15
    点赞
  • 144
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
STM32CubeMX是由STMicroelectronics开发的一款集成开发环境(IDE),用于快速生成STM32微控制器相关的初始化代码。它提供了用户友好的图形界面,支持中文语言,使得开发人员可以轻松地配置和初始化STM32微控制器的各种外设,例如GPIO、USART、I2C等。STM32CubeMX还能够生成初始化代码模板,并支持导出至主流的IDE平台,如Keil、IAR等。 相对于STM32CubeMXSTM32F1的HAL(Hardware Abstraction Layer)库是一种更底层的API层,用于抽象硬件细节,为开发人员提供更直接、更灵活的访问STM32F1系列微控制器的各种外设。HAL库提供了一系列函数接口,方便用户进行底层硬件编程,例如GPIO的读写操作、USART的发送接收等。 STM32CubeMXSTM32F1的HAL库在开发过程中都有各自的优点。STM32CubeMX提供了一个易于使用的图形化界面,使得微控制器初学者能够更加快速地进行外设配置,生成初始化代码,并支持中文,方便使用中国开发者。而HAL库提供了更灵活、更底层的硬件接口,允许开发者直接调用底层寄存器操作,满足对微控制器性能和资源要求更高的应用场景。 总之,STM32CubeMXSTM32F1的HAL库STM32微控制器开发的两个重要工具。对于初学者来说,可以先通过STM32CubeMX进行外设配置和生成初始化代码,然后使用HAL库进行更高级的编程。而对于有一定经验的开发者来说,可以直接使用HAL库进行底层硬件操作。无论是哪种方式,都能够帮助开发者更加快速、高效地进行STM32F1系列微控制器的开发工作。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觉皇嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值