目录
实验目的:利用定时器3实现LED0呼吸灯和LED1的定时闪烁
实验平台:正点原子精英板
一、简介
1.定时器简介
参考:STM32 hal库使用笔记(二)中断—定时器中断_乱码小伙的博客-CSDN博客
2.PWM简介
PWM(Pulse Width Modulation)脉冲宽度调制 在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域。
3.输出比较
OC(Output Compare)输出比较 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形 每个高级定时器和通用定时器都拥有4个输出比较通道。
二、HAL库配置
1.时钟树配置
参考:STM32 hal库使用笔记(一)GPIO的使用—流水灯_乱码小伙的博客-CSDN博客
2.CubeMX配置定时器3
查阅使用手册可知,PB5具有定时器3通道2的重映射功能,按下图配置:时钟源选择内部时钟源,通道2选择输出PWM。
GPIO设置:LED1的配置不再赘述。
由于还需要定时中断实现LED1的闪烁,打开NVIC对应的中断接口:
参数设置:pwm输出频率为2KHZ按照下图配置PSC和ARR;重装载使能;PWM mode1模式;Pulse:250,占空比约50%;极性选择:Low,由于LED0是低电平点亮,所以电平要低电平有效,这样配合CCR比较器就可以实现呼吸灯。
频率计算公式:
配置完成后,生成代码即可。
三、代码编写
利用CubeMX进行配置后,HAL库已经完成了关于配置HAL_TIM_PWM_Init(),HAL_TIM_PWM_MspInit(),HAL_TIM_PWM_ConfigChannel()的工作,实现了定时器的配置,时钟配置,PWM初始化和模式选择等工作。用户只需要,开启PWM和定时中断,并编写回调函数,在主函数里按照需求调节占空比。
初始化:
void MX_TIM3_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 71;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 499;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 250;
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim3);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//用户添加,开启PWM输出
HAL_TIM_Base_Start_IT(&htim3);//用户添加,开启中断
}
回调函数:由于配置完的周期是0.0005秒,所以按照以下编写实现0.5秒闪烁
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM3)
{
k++;
if(k>=1000){k=0;HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);}
}
}
主函数:ledrpwmval的最大值不能超过500,否则也无效,其大小决定呼吸灯亮灭速度。
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t ledrpwmval = 0;
uint8_t dir = 1;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_Delay(10);
if (dir)ledrpwmval=ledrpwmval+5; /* dir==1 ledrpwmval递增 */
else ledrpwmval=ledrpwmval-5; /* dir==0 ledrpwmval递减 */
if (ledrpwmval > 500)dir = 0; /* ledrpwmval到达500后,方向为递减 */
if (ledrpwmval == 0)dir = 1; /* ledrpwmval递减到0后,方向改为递增 */
/* 修改比较值控制占空比 */
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2, ledrpwmval);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
四、实验效果
PWM呼吸灯和定时中断闪烁
欢迎大家交流和指正!!!