一、通用定时器从模式:复位模式
使用TIM1的CH1输出PWM脉冲
使用TIM4的CH1作为触发输入通道。
PWM的上升沿触发TIM4的复位模式,复位TIM4计数器并触发中断.
定时器1配置,用来产生PWM脉冲
TIM_HandleTypeDef htimx; //基本定时器句柄
void ADVANCED_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig; //定时器时钟配置
TIM_MasterConfigTypeDef sMasterConfig; //定时器主从模式配置
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;//刹车和死区时间配置
TIM_OC_InitTypeDef sConfigOC; //输出比较配置
ADVANCED_TIM_RCC_CLK_ENABLE();
htimx.Instance = TIM1;
htimx.Init.Prescaler = ADVANCED_TIM_PRESCALER; //预分频设置
htimx.Init.CounterMode = TIM_COUNTERMODE_UP; //计数方式,向上或者向下
htimx.Init.Period = ADVANCED_TIM_PERIOD; //定时器周期
htimx.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; //时钟分频,基本定时器没有
htimx.Init.RepetitionCounter = ADVANCED_TIM_REPETITIONCOUNTER; //重复计数器
HAL_TIM_Base_Init(&htimx); //初始化
//定时器时钟配置
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htimx, &sClockSourceConfig); //初始化
HAL_TIM_PWM_Init(&htimx);
//定时器主从模式配置
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; //从模式,设置是否使用定时器的被动触发。
HAL_TIMEx_MasterConfigSynchronization(&htimx, &sMasterConfig);
//刹车和死区时间配置
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;//设置运行模式下非工作状态选项
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;//设置在空载下非工作状态选项
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; //锁电平参数
sBreakDeadTimeConfig.DeadTime = 100; //死区时间设置
sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; //使能或失能TIMx刹车输入
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;//TIMx刹车输入管脚极性
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;//使能和失能自动输出功能
HAL_TIMEx_ConfigBreakDeadTime(&htimx, &sBreakDeadTimeConfig);
//输出比较配置
sConfigOC.OCMode = TIM_OCMODE_PWM1; //输出比较模式
sConfigOC.Pulse = 100; //设置电平跳变值
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; //输出比较级性
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;//互补输出比较级性
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; //输出比较快速使能和失能
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; //选择空闲状态下非工作状态
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;//设置空闲状态下非工作状态
HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_MspPostInit(&htimx); }
// 定时器4配置为从模式–复位模式
void GENERAL_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig; //定时器时钟配置
TIM_SlaveConfigTypeDef sSlaveConfig; //从模式配置
/* 基本定时器外设时钟使能 */
htimx_GeneralTIM.Instance = TIM4;
htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;
htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;
htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;
htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_IC_Init(&htimx_GeneralTIM);
/* 定时器时钟源选择 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);
/* 从模式:复位模式 TI1 输入上出现上升沿时,递增计数器清零*/
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; // 从模式:外部触发复位
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; // 输入触发:选择 TI1 作为输入源
sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;// 触发极性:上升沿
sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;// 触发预分频:无
sSlaveConfig.TriggerFilter = 0x0; // 滤波:本例中不需要任何滤波
HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
/* 外设中断配置 */
HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}
二、通用定时器从模式:门控模式
使用TIM2的CH1作为触发输入通道,当相应的引脚为低电平时,触发从模式:门控模式,TIM2计数器开始工作;如果引脚悬空,TIM2不工作。
void GENERAL_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;
/* 基本定时器外设时钟使能 */
GENERAL_TIM_RCC_CLK_ENABLE();
/* 定时器基本功能初始化 */
htimx_GeneralTIM.Instance = TIM2;
htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;
htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;
htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;
htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_IC_Init(&htimx_GeneralTIM);
/* 定时器时钟源选择 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);
/* 从模式:复位模式 TI1 输入上出现下降沿时,从定时器使能 */
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED; // 从模式:门控模式
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; // 输入触发:选择 TI1 作为输入源
sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING; // 门控极性:低电平
sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1; // 触发预分频:无
sSlaveConfig.TriggerFilter = 0x0; // 滤波:本例中不需要任何滤波
HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
/* 外设中断配置 */
HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}
三、通用定时器从模式:触发模式
TIM4的CH2通道作为触发输入通道,开机之后并不启动定时器,将相应输入通道的端口与GND短接,给通道一个上升沿,即可触发使能TIM4。
void GENERAL_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;
/* 基本定时器外设时钟使能 */
GENERAL_TIM_RCC_CLK_ENABLE();
htimx_GeneralTIM.Instance = TIM4;
htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;
htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;
htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;
htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_IC_Init(&htimx_GeneralTIM);
/* 定时器时钟源选择 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);
/* 从模式:复位模式 TI2 输入上出现下降沿时,使能从计数器*/
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER; // 从模式:触发模式
sSlaveConfig.InputTrigger = TIM_TS_TI2FP2; // 输入触发:选择 TI2 作为输入源
sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING; // 触发极性:下降沿触发
sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1; // 触发预分频:无
sSlaveConfig.TriggerFilter = 0x0; // 滤波:本例中不需要任何滤波
HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
/* 外设中断配置 */
HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}
主函数中只使能中断,而不启动。
/* 通用定时器初始化 */
GENERAL_TIMx_Init();
/* 使能中断,但不启动TIM */
__HAL_TIM_ENABLE_IT(&htimx_GeneralTIM,TIM_IT_UPDATE); // 使能更新中断
四、定时器从模式:外部时钟2模式_从模式_触发模式
示例试验:通过短接GND给TIM4的CH1一个下降沿,使能TIM4,然后按下按键1,没按一次,LED灯闪烁一次。
说明:使用TIM4的CH1作为触发输入通道,对应的引脚是PD12,开机是没有使能定时器,给CH1一个下降沿
触发使能TIM4,这个时候,TIM4的时钟有ETR引脚提供,对应引脚是PE0,也就是KEY1,所以按下KEY1,计
数器开始递增,LED闪烁.
void GENERAL_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;
/* 基本定时器外设时钟使能 */
GENERAL_TIM_RCC_CLK_ENABLE();
htimx_GeneralTIM.Instance = TIM4;
htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER; //预分频为0
htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP; //加计数
htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD; //定时器周期:0XFFFF
htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_IC_Init(&htimx_GeneralTIM);
/* 定时器时钟源选择:外部时钟模式2 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;// 获取外部时钟,这里使用按键来模拟,定时器本身就是一个计数器,理解这一点
sClockSourceConfig.ClockFilter = 0x0;
sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_FALLING;
sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);
/* 从模式:复位模式 TI1 输入上出现上升沿时,触发从定时器*/
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER; // 从模式:触发模式
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; // 输入触发:选择 TI1 作为输入源
sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING; // 触发极性:上升沿触发
sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1; // 触发预分频:无
sSlaveConfig.TriggerFilter = 0x0; // 滤波:本例中不需要任何滤波
HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
/* 外设中断配置 */
HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}
在主函数中,只要计数器中的数值变化后,就翻转LED。
while (1)
{
/* 循环读取TIMx的计数器,只有变化,就翻转LED电平 */
Counter = __HAL_TIM_GET_COUNTER(&htimx_GeneralTIM);
if( last_Counter != Counter)
{
LED1_TOGGLE;
LED2_TOGGLE;
LED3_TOGGLE;
last_Counter = Counter ;
}
}
上述四种从模式的配置方式基本相同,仅是在于触发条件不同而已。理解了一个其他的都没问题