请基于STM32L431的定时器2(TIM2),采用课本上已有构件,编程实现一个嵌入式系统,已知电路板上振动马达 MOTOR的引脚为(PTA NUM18)。要求至少功能:采用两个不同占空比的PWM控制该振动马达,使之振动程度不同;主程序循环执行。(请写出核心代码和代码解析)
时间: 2024-03-11 09:47:04 浏览: 117
以下是基于STM32L431的定时器2(TIM2)控制振动马达的核心代码和代码解析:
```c
#include "stm32l4xx.h"
#define MOTOR_PIN GPIO_PIN_2
#define MOTOR_PORT GPIOA
void TIM2_IRQHandler(void)
{
if(TIM2->SR & TIM_SR_UIF) //检查更新事件是否发生
{
TIM2->SR &= ~TIM_SR_UIF; //清除更新事件标志位
TIM2->CCR1 = 500; //设置PWM1占空比为50%
TIM2->CCR2 = 1000; //设置PWM2占空比为100%
}
}
int main(void)
{
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; //使能GPIOA时钟
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN; //使能TIM2时钟
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = MOTOR_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(MOTOR_PORT, &GPIO_InitStruct); //配置GPIO引脚复用为TIM2_CH1
TIM2->PSC = 399; //预分频器值,时钟频率为80MHz/(399+1)=200kHz
TIM2->ARR = 999; //自动重载寄存器值,计数器计数到999后重新开始
TIM2->CCR1 = 0; //设置PWM1占空比为0%
TIM2->CCR2 = 0; //设置PWM2占空比为0%
TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE; //PWM1模式为PWM模式1,启用预装载
TIM2->CCMR1 |= TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE; //PWM2模式为PWM模式1,启用预装载
TIM2->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E; //启用PWM输出
TIM2->DIER |= TIM_DIER_UIE; //使能更新中断
TIM2->CR1 |= TIM_CR1_CEN; //启动计数器
NVIC_EnableIRQ(TIM2_IRQn); //使能定时器2中断
while (1)
{
//主程序循环执行
}
}
```
代码解析:
1. 定义了`MOTOR_PIN`和`MOTOR_PORT`宏,分别表示振动马达的引脚和所在的GPIO端口。
2. 在`TIM2_IRQHandler()`中实现定时器2的更新中断处理函数,当更新事件发生时,清除更新事件标志位,并设置PWM1和PWM2的占空比分别为50%和100%。
3. 在`main()`函数中,依次进行以下操作:
- 使能GPIOA和TIM2的时钟。
- 配置GPIO引脚为TIM2_CH1复用模式。
- 配置定时器2的预分频器、自动重载寄存器、PWM模式、PWM输出和更新中断。
- 使能定时器2的计数器和定时器2中断。
4. 在主程序中,可以添加其他需要执行的代码,例如读取传感器数据、控制其他外设等。
注意事项:
1. 在配置GPIO引脚为TIM2_CH1复用模式时,需要将引脚的复用选择设置为`GPIO_AF1_TIM2`。
2. 在配置PWM模式时,需要设置预装载使能位,否则占空比设置不会生效。
3. 在启动定时器2计数器前,需要先配置好定时器2的所有参数,否则可能会出现意想不到的错误。
阅读全文