图5 MM32F0140输入捕获框图
计数定时配置时基配置配置定时器工作模式配置 CR1[OPM] 位可以设置定时器工作模式,其中值为 0 表示定时器将循环计时,值为 1 表示计时 1 次后就停止计数器。
配置是否预装载配置 CR1[ARPE] 位可以配置定时器自动预装载寄存器 ARR 的实际更新方式,值为1则用户写入 ARR 寄存器的值会在下一次计数器更新时起效,否则立刻生效。
配置计数模式配置 CR1[DIR] 位和 CR1[CMS] 位可以配置计数器计数模式。如果选择单向计数,CR1[CMS]需配置为 0,此时CR1[DIR] 配置为 0 时,向上计数,配置为 1 时向下计数。如果选择先向上计数再向下计数,则需要配置 CR1[CMS],CR1[DIR] 值保持为 0。
配置预分频值由上述计数器频率计算小结可知,如果需要定时器频率为 cnt_frq, 定时器输入源频率为 clk_frq,定时器的预分频值 psc 应为
−1
计算出的 psc 值写入 PSC 寄存器。
配置自动预装载寄存器 ARR自动预装载寄存器 ARR 的值决定定时器周期计数次数。假如定时器向上计数,则计数器从 0 递增到 ARR 值,即 ARR 寄存器值为 arrv,则实际计数器一个周期内会做arrv+1 次计数,所以ARR 寄存器值应为需要的周期计数值减一。将此值写入 ARR 寄存器。
使能计数器完成上述配置后,将 CR1[CEN] 置为 1 即可启动计数器计数。当不需要计数时,将此位设置为 0。
比较输出配置配置通道输出模式配置 CCMRy[CCxS] 位为 0,可以将通道 x 配置为输出模式。
配置是否预装载匹配值配置 CCMRy[OCxPE] 位可以设置通道 x 的比较输出匹配值生效方式,为 0 则一旦写入立刻生效,否则匹配值将在下一次更新事件后生效。
配置比较输出模式配置 CCMRy[OCxM] 字段可以选择不同的比较输出模式,具体字段值和比较输出模式间关系可见表3。
表3 CCMRy[OCxM] 与 比较输出模式间对应关系
CCMRy[OCxM]比较输出模式
0比较情况对参考输出电压无影响。
1匹配时,参考输出电压为高。
2匹配时,参考输出电压为低。
3匹配时,翻转参考输出电压。
4参考输出电压总为低。
5参考输出电压总为高。
6输出PWM波时,匹配时产生下降沿。
7输出PWM波时,匹配时产生上升沿。
配置有效输出电压配置 CCER[CCxP] 位,可以设置通道 x 的有效输出电压。值为0,则参考电压的高电平为有效电平;值为1,则参考电压的低电平为有效电平。
使能通道输出配置 CCER[CCxE] 位为1,使能通道输出功能;配置为 0,则关闭通道输出功能。
输入捕获配置配置通道输入模式配置 CCMRy[CCxS] 位为1,可将通道 x 配置为输入模式。
配置输入信号边沿选择配置 CCER[CCxP] 和 CCER[CCxNP] 位,可以配置输入信号的有效边沿选择,具体对应关系如表4。
表4 输入模式下,CCER[CCxP]和CCER[CCxNP] 对于输入边沿影响
CCER[CCxP]CCER[CCxNP]有效边沿
00上升沿有效
10下降沿有效
11双边沿有效
配置采样和滤波配置 CCMRy[ICxF] 字段,设置通道 x 的输入捕获滤波器。
配置预分频器配置 CCMRy[IC1PSC] 字段,设置通道 x 输入信号的预分频值。
使能通道输入配置 CCER[CCxE] 位为 1,使能通道输入捕获功能;配置为 0,则关闭通道输入捕获功能。
样例 pokt-f0140 开发板 定时器实现TIM2通道1输出pwm波在 SDK 中已有支持的 pokt-f0140 开发板上,在 tim_32b_0 样例工程中,通过 tim_32b_output_compare_pwm 可以使用定时器 TIM2 的通道 1 输出 pwm 波。
时钟初始化TIM2 在 APB2 总线上,需要使能时钟。TIM2 的通道 1 复用 PA0 引脚,需要使能 GPIOA 时钟。
/* Enable TIM. */
RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_TIM2, true);
RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_TIM2);
/* Enable GPIOA for TIM2_CH1. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOA, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOA);
初始化输出引脚GPIO_Init_Type gpio_init;
gpio_init.Pins = GPIO_PIN_0;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_2);/* 根据data sheet, 配置复用模式2。 */
定时器时基配置TIM_32B_Init_Type tim_init;
tim_init.ClockFreqHz = BOARD_TIM_32B_FREQ;/* 因为 TIM_32B 在APB2总线上,所以BOARD_TIM_32B_FREQ的值实际为APB2总线时钟频率。*/
tim_init.StepFreqHz = APP_TIM_UPDATE_PERIOD; /* 定时器周期时长为定时器周期长度Period加1后除定时器频率StepFreqHz。*/
tim_init.Period = APP_TIM_UPDATE_PERIOD - 1u; /* 所以可得值为1,也即定时器周期时长为1s。 */
tim_init.EnablePreloadPeriod = false; /* 不采用预装载,修改ARR寄存器将立即生效。 */
tim_init.PeriodMode = TIM_32B_PeriodMode_Continuous;/* 循环计时。 */
tim_init.CountMode = TIM_32B_CountMode_Increase; /* 递增计数。 */
TIM_32B_Init(BOARD_TIM_32B_PORT, &tim_init);
配置输出通道TIM_32B_OutputCompareConf_Type tim_outcomp_conf;
tim_outcomp_conf.ChannelValue = 0u;/* Compare value initialize with 0. */
tim_outcomp_conf.EnableFastOutput = false; /* Disable fast output. */
tim_outcomp_conf.EnablePreLoadChannelValue = false; /* Disable preload, put data immediately. */
tim_outcomp_conf.RefOutMode = TIM_32B_OutputCompareRefOut_FallingEdgeOnMatch;/*Generate a falling edge when matched.*/
tim_outcomp_conf.ClearRefOutOnExtTrigger = false; /* Ext signal won't clear output. */
tim_outcomp_conf.PinPolarity = TIM_32B_PinPolarity_Rising;/* High polarity is valid. */
TIM_32B_EnableOutputCompare(BOARD_TIM_32B_PORT, BOARD_TIM_32B_CHANNEL, &tim_outcomp_conf);
使能计数器TIM_32B_Start(BOARD_TIM_32B_PORT);
main 函数main 函数将轮询键入,并按设定的占空比数组循环输出不同的 PWM 波。
int main(void)
{
BOARD_Init();
printf("
tim_32b_output_compare_pwm.
");
/* Setup the timer. */
app_tim_32b_init();
printf("press any key to change the pwm ...
");
while (1)
{
for (uint32_t i = 0; i < APP_TIM_32B_PWM_NUM; i++)
{
getchar();
TIM_32B_PutChannelValue(BOARD_TIM_32B_PORT, BOARD_TIM_32B_CHANNEL, app_tim_32_pwm_val
);/* Change duty cycle. */
printf("PWM value: %u
", (unsigned)app_tim_32_pwm_val);
}
}
}
实验结果将 TIM2 通道1 所在引脚用杜邦线与小灯泡引脚相连,可以实现呼吸灯的效果。因为每次键入,都会改变 pwm 波的占空比,所以小灯泡的亮度在不断改变:
0