一.作者小课堂
(一)定时器
STM32定时器种类多,功能强大,这些定时器完全独立、互不干扰,可以同步操作。
1.SysTick定时器
SysTick系统时钟位于Cortex-M3内核,是一个24位的递减计数器,主要用于: 精确延时,在多任务操作系统中为系统提供时间基准(时基); 任务切换,为每个任务分配时间片。
2. WatchDog看门狗
作用:当微控制器受到外部干扰或程序中出现不可预知的逻辑故障导致应用程序脱离正常的执行流程时(俗称程序跑飞),在一定的时间间隔内使系统复位,回到初始状态; 看门狗设计是用来监视MCU程序运行状态的,是确保系统可靠稳定运行的一种有效措施。
3.STM32定时器模块
定时器时钟有四种来源:
● 内部时钟(CK_INT)
● 外部时钟模式1:外部输入脚(TIx) (输入捕获的引脚)
● 外部时钟模式2:外部触发输入(ETR)
● 内部触发输入(ITRx):(定时器级联)使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
产生CK_PSC时钟,然后在从模式控制器内设置好计数模式(向上向下),再经过预分频器产生CK_CNT,若为CNT计数器向下计数,则当其计数到0时,自动重装载寄存器会重新为CNT计数器装载新值重新递减计数,并产生一个更新事件。
时基单元:
● 计数器寄存器(TIMx_CNT)
● 预分频器寄存器 (TIMx_PSC)
● 自动装载寄存器 (TIMx_ARR)
输入捕获:信号通过捕获通道进入,经滤波,经分频,到捕获比较寄存器。
(二)PWM原理
1.PWM
(1)工作原理
在PWM的一个周期内,定时器从0开始向上计数,在0-t1时间段,定时器计数器TIMx_CNT值小于TIMx_CCRx值,输出低电平; 在t1-t2时间段,定时器计数器TIMx_CNT值大于TIMx_CCRx值,输出高电平; 当定时器计数器的值TIMx_CNT达到ARR时,定时器溢出,重新从0开始向上计数,如此循环。
(2)PWM的一个周期
定时器从0开始向上计数
当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程
至此一个PWM周期完成
二.实践出真知
(一)实验一
1.实验要求
使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
2.代码
HAL_TIM_Base_Start_IT(&htim2);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static unsigned char ledState = 0;
if (htim == (&htim2))
{
if (ledState == 0)
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
ledState = !ledState;
}
}
3.实验结果
①波形图
②实物演示
(二)实验二
1.实验要求
接上,采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整占空比变化到一个满意效果;使用Keil虚拟示波器,观察 PWM输出波形。
2.代码
/* USER CODE BEGIN 1 */
uint16_t pwmVal=0; //PWM占空比
uint8_t dir=1;
/* USER CODE END 1 */
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
/* USER CODE END 2 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
while (pwmVal< 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
HAL_Delay(200);
}
/* USER CODE END 3 */