stm32f103输入捕获

简介

输入捕获功能同样只有高级/通用定时器才具有. 

输入捕获英文名字为Input Capture. 是定时器外设另一个大的功能, 与输出比较OC共用CCR寄存器, 因此一个定时器只可以使用一种功能, CCR(Capture Compare Register捕获比较寄存器).

信号输入引脚出现指定电平跳变时, 当前CNT的值将被锁存到CCR中, 可用于测量PWM波形的频率, 占空比, 脉冲间隔, 电平持续时间等参数. 这里我们将使用PWMI模式, 捕获上一节产生的PWM波, 来测量频率占空比.

注意这里只能测量方波, 如果是正弦波需要经过电压比价器转化为方波再测.

如果电压过高, 需要隔离放大器或者电压互感器, 否则将会烧毁.

测量频率原理

 测量频率有两种方法:

1. 测频法.(适用于高频信号, 使用的技术是: 外部时钟源定时器计数)

使用一个定时器正常计时Ts, 以另一个定时器待测量的信号为时钟源, 产生一次电平跳变记次+1, 总共计次N, 待测频率为Fx = N / T;

2. 测周法(适用于低频信号, 使用的技术是: 输入捕获)

使用一个定时器设置为输入捕获功能, 设置该定时器的时基单元固定好标准频率fc, 将自动重装值设定为最大值, 防止CNT溢出. 每次经过一个上升沿, CCR捕获CNT的值为N, 并且将CNT清零, 此时为一个待测信号的周期走了N个标准频率fc, 所以待测频率为fx = 1 / T = 1 / (1/fc * N) = fc / N;

总结: 测频法是一段时间内的平均值, 时间慢, 值平滑. 测周法, 是一个周期出结果, 时间与一个周期长度相关, 更新快.

可能出现的误差

1. 正负一误差: 如最后测了半个, 算一个还是算0个, 就会出现正负一误差.

2. 单片机的时钟源是晶振, 晶振可能产生误差.

3. 外界信号的干扰产生误差.

如何减小误差, 测频法增加测量的时间, 测周法减小标准频率fc. 增加滤波功能.

测量占空比

 使用PWMI模式配置交叉通道, 让CCR2捕获下降沿, CCR1捕获上升沿, 使用从模式将CNT清零. 这样CCR1捕获的是一个周期N个fc, CCR2捕获的是一个周期高电平的N2个fc, 占空比 = CCR2 / CCR1 * 100 %.

输入捕获电路

 输入信号源CH1会经过数据选择器到达TI1, 经过滤波器和边沿检测器可以输出TI1FP1信号, 经过预分频器可以触发输入捕获中断, 触发事件CCR将会捕获CNT的值, 中断可以将CNT清零, 等待下次的捕获, 但过于浪费软件资源, 让CPU持续工作在中断的状态下, 所以有从模式可以硬件将CNT清零. 但是只有通道1和2有, 如果是通道3或者4只能使用中断手动清零, 所以不要使用3/4通道.

 

IC模式和PWMI模式

 IC模式下只能初始化一条通道, 两次初始化也可以实现PWMI模式, 就是要麻烦一些.

PWMI模式下可以初始化两条通道, 一条通道为监测上升沿/直连, 会自动配置另一个通道为监测下降沿/交叉连接, 方便快速配置好可以检测频率和占空比两项的操作.

主从触发模式

 主从触发模式实现硬件全自动测量.

首先是触发源的选择为: TI1FP1, 从模式选择Reset.

注意要先捕获后清零, 否则会捕获到0.

代码逻辑

  1.  RCC开启GPIO, TIM时钟
  2. GPIO上拉/浮空输入模式
  3. 时基单元配置
  4. 从模式触发源选择
  5. 从模式选择
  6. 启动定时器

代码参考

void ICInit()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    //选择时基单元的时钟源
    TIM_InternalClockConfig(TIM3);
    
    //配置GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    //配置时基单元, fc = 1Mhz.
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInitStructure.TIM_Period = 65536-1;//ARR自动重装值
    TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//PSC预分频器值
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值(高级定时器才有)
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
    
    //配置PWMI模式
    TIM_ICInitTypeDef TIM_ICInitStruct;
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_1; //通道1
    TIM_ICInitStruct.TIM_ICFilter = 0xf; //最大滤波
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //捕获上升沿
    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不分频
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直连通道
    TIM_PWMIConfig(TIM3, &TIM_ICInitStruct);
    
    //选择输入触发源,和从模式
    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
    
    TIM_Cmd(TIM3, ENABLE);
}


uint16_t getFreq()
{
    return 1000000 / (TIM_GetCapture1(TIM3)+1);
}

uint16_t getDuty()
{
    return (TIM_GetCapture2(TIM3)+1)*100 / (TIM_GetCapture1(TIM3)+1);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值