本文参考了以下文档
备赛电赛学习stm32篇(七):tim输入捕获
https://blog.csdn.net/m0_61022809/article/details/128570211
芯片类型为stm32f103zet6
管脚使用描述:
输出:使用pe9重定义为tim1_ch1
输入:使用pd12复用为tim4_ch1
pwm配置代码:
tim1_pwm_init(2000-1, 72-1);
void tim1_pwm_init(u16 arr, u16 psc)
{
gpio_inittypedef gpio_initstructure;
tim_timebaseinittypedef tim_timebasestructure;
tim_ocinittypedef tim_ocinitstructure;
rcc_apb2periphclockcmd(rcc_apb2periph_tim1, enable); //使能定时器1时钟
rcc_apb2periphclockcmd(rcc_apb2periph_afio, enable); //复用时钟使能
rcc_apb2periphclockcmd(rcc_apb2periph_gpioe, enable); //使能gpio外设时钟
gpio_pinremapconfig(gpio_fullremap_tim1, enable);
//设置pe引脚为复用输出功能,输出pwm脉冲波形
gpio_initstructure.gpio_pin = gpio_pin_9; //|gpio_pin_11|gpio_pin_13|gpio_pin_14; //tim1_ch1-4
gpio_initstructure.gpio_mode = gpio_mode_af_pp; //推挽输出
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
gpio_init(gpioe, &gpio_initstructure); //初始化gpioe
//初始化tim1
tim_timebasestructure.tim_period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
tim_timebasestructure.tim_prescaler = psc; //设置用来作为timx时钟频率除数的预分频值
tim_timebasestructure.tim_clockdivision = 0; //设置时钟分割:tdts = tck_tim
tim_timebasestructure.tim_countermode = tim_countermode_up; //tim向上计数模式
tim_timebasestructure.tim_repetitioncounter = 0;
tim_timebaseinit(tim1, &tim_timebasestructure); //根据tim_timebaseinitstruct中指定的参数初始化timx的时间基数单位
//初始化tim1 channel1-4 pwm模式.
//因为只使用了ch1,所以尝试只初始化ch1
tim_ocinitstructure.tim_ocmode = tim_ocmode_pwm1; //选择定时器模式:tim脉冲宽度调制模式1,计数值<自动重装载值时,输出高电平
tim_ocinitstructure.tim_outputstate = tim_outputstate_enable; //比较输出使能
tim_ocinitstructure.tim_ocpolarity = tim_ocpolarity_high; //输出极性:tim输出比较极性高
tim_oc1init(tim1, &tim_ocinitstructure); //根据t指定的参数初始化外设tim1 oc1
//tim_oc2init(tim1, &tim_ocinitstructure); //根据t指定的参数初始化外设tim1 oc2
//tim_oc3init(tim1, &tim_ocinitstructure); //根据t指定的参数初始化外设tim1 oc3
//tim_oc4init(tim1, &tim_ocinitstructure); //根据t指定的参数初始化外设tim1 oc4
tim_oc1preloadconfig(tim1, tim_ocpreload_enable); //使能tim1在ccr1上的预装载寄存器
//tim_oc2preloadconfig(tim1, tim_ocpreload_enable); //使能tim1在ccr2上的预装载寄存器
//tim_oc3preloadconfig(tim1, tim_ocpreload_enable); //使能tim1在ccr3上的预装载寄存器
//tim_oc4preloadconfig(tim1, tim_ocpreload_enable); //使能tim1在ccr4上的预装载寄存器
tim_cmd(tim1, enable); //使能tim1
tim_ctrlpwmoutputs(tim1, enable); //moe 主输出使能,高级定时器需要添加
//printf("%s end\r\n", __function__);
}
捕获代码:
void tim4_cap_init(u16 arr, u16 psc)
{
//1. 使能时钟
rcc_apb2periphclockcmd(rcc_apb2periph_gpiod|rcc_apb2periph_afio, enable);
//配置gpio口
gpio_inittypedef gpio_initstructure;
gpio_initstructure.gpio_pin = gpio_pin_12;
gpio_initstructure.gpio_mode = gpio_mode_in_floating; //浮空输入模式
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
gpio_init(gpiod, &gpio_initstructure);
//gpio_resetbits(gpiod, gpio_pin_12); //1214pm2:先删除
//2.tim4配置
//gpio_afiodeinit(); //刚开始没有这个语句,所以一直没有重映射成功
gpio_pinremapconfig(gpio_remap_tim4, enable); //这个就是重映射功能函数
rcc_apb1periphclockcmd(rcc_apb1periph_tim4, enable);
//配置tim4
tim_timebaseinittypedef tim_timebasestructure;
tim_timebasestructure.tim_clockdivision = tim_ckd_div1;
tim_timebasestructure.tim_countermode = tim_countermode_up;
tim_timebasestructure.tim_period = arr;
tim_timebasestructure.tim_prescaler= psc;
tim_timebaseinit(tim4, &tim_timebasestructure);
//3. 配置tim4 channel输入捕获
tim_icinittypedef tim_icinitstructure;
tim_icinitstructure.tim_channel = tim_channel_1;
tim_icinitstructure.tim_icpolarity = tim_icpolarity_rising; //上升沿捕获
tim_icinitstructure.tim_icprescaler = tim_icpsc_div1; //对输入的pwm信号不分频
tim_icinitstructure.tim_icselection = tim_icselection_directti; // ic1直接连接ti1fp1
tim_icinitstructure.tim_icfilter = 0x00;
//tim_icinit(tim4, &tim_icinitstructure);
tim_pwmiconfig(tim4, &tim_icinitstructure);
#if 0 //实测不需要这个
//配置ch2
tim_icinitstructure.tim_channel = tim_channel_2;
tim_icinitstructure.tim_icpolarity = tim_icpolarity_falling; //下降沿触发;
tim_icinitstructure.tim_icselection = tim_icselection_indirectti; //ic2间接连接ti1fp2
tim_icinitstructure.tim_icprescaler = tim_icpsc_div1; //对输入的pwm信号不分频
tim_icinitstructure.tim_icfilter = 0x0;
tim_pwmiconfig(tim4, &tim_icinitstructure);
#endif
//选择输入捕获的触发信号;
tim_selectinputtrigger(tim4, tim_ts_ti1fp1);
// 选择从模式
// pwm输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器cnt被复位清零;
tim_selectslavemode(tim4, tim_slavemode_reset);
tim_selectmasterslavemode(tim4, tim_masterslavemode_enable);
//配置中断分组
//https://blog.csdn.net/qq_42475191/article/details/120535222
//这个函数的作用是对中断的优先级进行分组,这个函数在系统中只能被调用一次,一旦分组确定就{banned}最佳好不要更改。
nvic_prioritygroupconfig(nvic_prioritygroup_2); //设置nvic中断分组2:2位抢占优先级,2位响应优先级
nvic_inittypedef nvic_initstructure;
nvic_initstructure.nvic_irqchannel = tim4_irqn;
nvic_initstructure.nvic_irqchannelcmd = enable;
nvic_initstructure.nvic_irqchannelpreemptionpriority = 1; //3; //抢占优先级3
nvic_initstructure.nvic_irqchannelsubpriority = 3; //0; //子优先级2
nvic_init(&nvic_initstructure);
// 使能捕获中断,这个中断主要针对的是主捕获通道(ti1fp1)
tim_itconfig(tim4, tim_it_cc1, enable);
// 清除中断标志位
tim_clearitpendingbit(tim4, tim_it_cc1);
//计数器开始计数
tim_cmd(tim4, enable); //使能tim4
#if 0
tim_itconfig(tim4,tim_it_update,enable); //允许溢出中断
tim_itconfig(tim4,tim_it_cc1,enable); //允许捕获中断
tim_itconfig(tim4,tim_it_cc2,enable);
tim_itconfig(tim4,tim_it_cc3,enable);
tim_itconfig(tim4,tim_it_cc4,enable);
#endif
}
void tim4_irqhandler(void)
{
int ret;
ret = tim_getflagstatus(tim4, tim_flag_cc1);
if (ret)
{
tim_clearitpendingbit(tim4, tim_it_cc1);
uint32_t ic1_ccr1, ic2_ccr2;
ic1_ccr1 = tim_getcapture1(tim4); //获取周期值ccr1
ic2_ccr2 = tim_getcapture2(tim4); //获取高电平时间ccr2
if (ic1_ccr1 > 0) {
tim4_pwm.pwm_0 = ((float)ic2_ccr2 / ic1_ccr1) * 100; /* 这里 * 100, 便于计算和显示 */
}
}
}