目录
一、知识点
1、ic(input capture)输入捕获
2、通用定时器结构
(1)输出比较的执行逻辑
(2)四个输入捕获和输出比较通道
(3)输入捕获的执行流程和输出比较的区别
(4)输入捕获的作用
(5)输入捕获通道
(6)pwmi模式:同时测量频率和占空比
(7)主从触发模式:实现硬件全自动测量
3、测频法和测周法测量频率
(1)测频法和测周法的原理
测频率法:定义一个t,如1s,在1s的时间内,有多少个周期,就是多少hz
测周法:周期的倒数就是频率,测出一个周期的时间,再取倒数,就是频率(测量时间的方法:定时器计次,使用一个已知频率fc的计次时钟,来驱动计数器,从一个上升沿开始计,计数器从0开始,一直计到下一个上升沿,停止,计一个数的时间是1/fc,计n个数,时间就是n/fc,n/fc就是周期,再取一个倒数,就得到公式fx=fc/n)
中界频率:测频率法的n=测周法的n,两者误差相等。
(2)测频法和测周法的选择
此时,当待测信号小于中界频率时,用测周法,当大于中界频率时,用测频法
(3)测频法和测周法的比较
测频法适合高频信号(因为若n很小,误差会很大),若闸门时间选为1s,那么每隔1s才能出结果,结果比较慢
测周法适合测量低频信号(周期比较长,计次就会比较多,有助于减少误差),测一个周期就能出现结果,而一般待测信号频率都比较大,故结果更新较快
(4)测频法和测周法的实现
a、测频法的思路:之前的对射式红外传感器计次计次,每来一个上升沿计次1,再用有一个定时器,每隔1s中断,再中断中,每隔1s取一次计次值,同时清0计次,为下一次做准备,这样每次读取的计次值就是频率
定时器外部时钟也同理,每隔1s取一次计次,就能实现
b、测周法:测量两个上升沿的时间(见本次代码)
4、主从触发模式
5、结构
(1)捕获输出基本结构
(2)pwmi基本结构
占空比:ccr2/ccr1
二、输入捕获模式测频率
1、原理图
2、改变pwm频率
tim_timebaseinitstructure.tim_period = 100 - 1; //arr
tim_timebaseinitstructure.tim_prescaler = 720 - 1; //psc
tim_ocinitstructure.tim_pulse = 0; //ccr
这代码中,因为arr=100,所以ccr的值为占空比(该电平在周期的比例)
3、单独修改psc的函数
void pwm_setprescaler(uint16_t prescaler)
{
//第三个参数指定定时器预分屏器的重装模式
//第一个 tim_pscreloadmode_update,预分频器在更新事件重装//等待周期结束
// 第二个tim_pscreloadmode_immediate预分频器立即重装//可能一个周期没结束就切换
tim_prescalerconfig(tim2, prescaler, tim_pscreloadmode_immediate);
}
4、设置1000hz,占空比为50%
pwm_setprescaler(720 - 1); //freq = 72m / (psc + 1) / 100 //1000hz
pwm_setcompare1(50); //duty = ccr / 100 //占空比为50%
5、工作步骤
6、ccr
7、 代码
(1)ic.c
#include "stm32f10x.h" // device header
void ic_init(void)
{
//tim3
rcc_apb1periphclockcmd(rcc_apb1periph_tim3, enable);
rcc_apb2periphclockcmd(rcc_apb2periph_gpioa, enable);
gpio_inittypedef gpio_initstructure;
gpio_initstructure.gpio_mode = gpio_mode_ipu;//上拉模式
gpio_initstructure.gpio_pin = gpio_pin_6;//pa6
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
gpio_init(gpioa, &gpio_initstructure);
tim_internalclockconfig(tim3);//tim3
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这个值决定了测周法的标准频率fc=1m
tim_timebaseinitstructure.tim_repetitioncounter = 0;
tim_timebaseinit(tim3, &tim_timebaseinitstructure);//tim3
//第四步:配置输入捕获单元
tim_icinittypedef tim_icinitstructure;
tim_icinitstructure.tim_channel = tim_channel_1;//选择通道1
tim_icinitstructure.tim_icfilter = 0xf;//数越大,滤波效果越好,滤波器计次不会改变信号原有的频率,一般滤波器的采样频率会远高于信号频率
tim_icinitstructure.tim_icpolarity = tim_icpolarity_rising;//上升沿触发
tim_icinitstructure.tim_icprescaler = tim_icpsc_div1;//分频器对信号本身进行计次,会改变频率。此处不分频
tim_icinitstructure.tim_icselection = tim_icselection_directti;//直连通道
tim_icinit(tim3, &tim_icinitstructure);
//第五步:选择重模式的触发源
tim_selectinputtrigger(tim3, tim_ts_ti1fp1);
//选择触发之后执行的操作
tim_selectslavemode(tim3, tim_slavemode_reset);
//使能
tim_cmd(tim3, enable);
}
uint32_t ic_getfreq(void)
{
//fc除n(fc,标准频率=72m/预分频系数)
return 1000000 / (tim_getcapture1(tim3) + 1);
}
(2)mian.c
#include "stm32f10x.h" // device header
#include "delay.h"
#include "oled.h"
#include "pwm.h"
#include "ic.h"
int main(void)
{
oled_init();
pwm_init();
ic_init();
oled_showstring(1, 1, "freq:00000hz");
pwm_setprescaler(720 - 1); //freq = 72m / (psc + 1) / 100 //1000hz
pwm_setcompare1(50); //duty = ccr / 100 //占空比为50%
while (1)
{
oled_shownum(1, 6, ic_getfreq(), 5);
}
}
三、pwmi模式频率占空比
1、ic.c中不一样的地方
//该函数会自动把剩下的一个通道初始化成相反的配置,第一个是通道1,直连、上升沿
//第二个是通道2,交叉、下降沿
tim_pwmiconfig(tim3, &tim_icinitstructure);
uint32_t ic_getduty(void)
{
return (tim_getcapture2(tim3) + 1) * 100 / (tim_getcapture1(tim3) + 1);
}
2、ic.c
#include "stm32f10x.h" // device header
void ic_init(void)
{
rcc_apb1periphclockcmd(rcc_apb1periph_tim3, enable);
rcc_apb2periphclockcmd(rcc_apb2periph_gpioa, enable);
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);
tim_internalclockconfig(tim3);
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);
tim_icinittypedef tim_icinitstructure;
tim_icinitstructure.tim_channel = tim_channel_1;
tim_icinitstructure.tim_icfilter = 0xf;
tim_icinitstructure.tim_icpolarity = tim_icpolarity_rising;
tim_icinitstructure.tim_icprescaler = tim_icpsc_div1;
tim_icinitstructure.tim_icselection = tim_icselection_directti;
//该函数会自动把剩下的一个通道初始化成相反的配置,第一个是通道1,直连、上升沿
//第二个是通道2,交叉、下降沿
tim_pwmiconfig(tim3, &tim_icinitstructure);
tim_selectinputtrigger(tim3, tim_ts_ti1fp1);
tim_selectslavemode(tim3, tim_slavemode_reset);
tim_cmd(tim3, enable);
}
uint32_t ic_getfreq(void)
{
return 1000000 / (tim_getcapture1(tim3) + 1);
}
uint32_t ic_getduty(void)
{
return (tim_getcapture2(tim3) + 1) * 100 / (tim_getcapture1(tim3) + 1);
}
3、main.c
#include "stm32f10x.h" // device header
#include "delay.h"
#include "oled.h"
#include "pwm.h"
#include "ic.h"
int main(void)
{
oled_init();
pwm_init();
ic_init();
oled_showstring(1, 1, "freq:00000hz");
oled_showstring(2, 1, "duty:00%");
pwm_setprescaler(720 - 1); //freq = 72m / (psc + 1) / 100
pwm_setcompare1(50); //duty = ccr / 100
while (1)
{
oled_shownum(1, 6, ic_getfreq(), 5);
oled_shownum(2, 6, ic_getduty(), 2);
}
}
四、知识点
测频率的性能
发表评论