定时器&PWM应用编程

实验目的

1 深入了解STM32定时器的工作原理,掌握脉宽调制(PWM)的生成方法。
2 掌握使用STM32F103的Tim2~Tim5中的一个定时器的某一个通道与LED相连,并利用定时器计数方式控制LED周期性地亮-灭。
3 学习如何在STM32F103上使用定时器的PWM模式,以呼吸灯的方式使LED渐亮渐灭,并通过Keil虚拟示波器观察PWM输出波形。
4 利用另一个定时器通道编程采集上述PWM输出信号,并获取其周期和脉宽,并将数据通过串口输出显示。
5 学习HC-SR04超声波测距模块的工作原理,并使用STM32F103完成一个超声波测距方案(选做)。

实验任务

一. 使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。

二. 接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

三. 再接上,采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。

四. 学习 HC-SR04超声波测距模块工作原理,使用 stm32F103 完成一个超声波测距方案(第9周之前选做)。

https://zhuanlan.zhihu.com/p/546833349

基于STM32和HC-SR04模块实现超声波测距功能(标准库)

实验内容

深入了解STM32定时器原理,掌握脉宽调制pwm生成方法。

一. 使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
1定时器
1)定时器概念
  能够对内部时钟信号或外部输入信号进行计数,数值达到设定要求时,向CPU发起中断请求,完成外部程序的运行。
  本质就是进行计数,选择内部时钟脉冲,作为计数器时,技术信号的来源选择非周期脉冲信号。
STM32中定时器可分为高级定时器、通用定时器、基本定时器三类,他们都是由一个可编程的16位预分频器(TIMX_PSC)驱动的16位。

2串口通信与点灯
1)创建新项目
在这里插入图片描述
2)选择芯片
在这里插入图片描述
3)配置RCC
在这里插入图片描述
4)配置SYS
在这里插入图片描述
5)配置IO口输出
在这里插入图片描述
6)配置定时器2和定时器3
在这里插入图片描述
分频系数那里虽然写的是71,但系统处理的时候会自动加上1,所以实际进行的是72分频。由于时钟我们一般会配置为72MHZ,所以72分频后得到1MHZ的时钟。1MHZ的时钟,计数5000次,得到时间5000/1000000=0.005秒。也就是每隔0.005秒定时器2会产生一次定时中断。
7)配置中断
开启定时器2和定时器3的中断。
在这里插入图片描述
生成定时器2和定时器3中断优先级配置代码
在这里插入图片描述
8)配置USART
在这里插入图片描述
波特率为115200,1位停止位,无校验位
9)时钟配置
在这里插入图片描述
10)配置项目
在这里插入图片描述

11)生成项目
在这里插入图片描述
12)代码
启动定时器
在这里插入图片描述

定时器中断回调函数

二. 接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t time_cnt =0;
	static uint32_t time_cnt3 =0;
	if(htim->Instance == TIM2)
	{
		if(++time_cnt >= 400)
		{
			time_cnt =0;
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);
		}
	}
	if(htim->Instance == TIM3)
	{
		if(++time_cnt3 >= 1000)
		{
			time_cnt3 =0;
    HAL_UART_Transmit(&huart1,hello,20,100000);
		}
			
	}
}

13)烧录,实验结果
引脚:A1–LED灯
在这里插入图片描述
在这里插入图片描述
接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

uint16_t duty_num3 = 10;
uint16_t duty_num4 = 10;

`HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
``HAL_Delay(50);
		duty_num3 = duty_num3 + 10;
			duty_num4 = duty_num4 + 10;
		if(duty_num3 > 500)
		{
			duty_num3 = 0;
		}
		__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_num3);
			if(duty_num4 > 500)
		{
			duty_num4 = 0;
		}
		__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_1,duty_num4);

在这里插入图片描述
10)编译烧录,实验结果
引脚
A6–LED
PB6 – PC13
在这里插入图片描述
11)PWM输出波形
在这里插入图片描述
在这里插入图片描述
采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。
在这里插入图片描述
代码如下

#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
 
uint8_t i = 0;
 
float Duty = 0;
float Frequency = 0;
uint16_t Cap_val1 = 0;
uint16_t Cap_val2 = 0;
 
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM1_Init();
    MX_TIM3_Init();
    MX_USART1_UART_Init();
    MX_TIM2_Init();
    /* USER CODE BEGIN WHILE */
 
    printf("串口通信测试\r\n");
    HAL_TIM_Base_Start_IT(&htim2); // 使能定时器及其更新中断
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 使能定时器及其PWM输出
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);       // 使能定时器及其输入捕获
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);       // 使能定时器及其输入捕获
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 10); // 设置一个PWM波形进行测量
 
    while (1)
    {
        // 串口发送 频率 占空比
        printf("Cap_val1 is :%d ,  Cap_val2 is : %d \r\n", Cap_val1, Cap_val2);
        printf("Duty is :%0.2f%% Frequency is : %0.2f ms\r\n", Duty, Frequency);
        HAL_Delay(1000);
    }
}
 
 
// 定时TIM2 定时亮灯的中断函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim)
{
    if (tim == &htim2)
    {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    }
}
 
// 定时输入捕获回调函数 计算占空比和频率
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM1)
    {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            Cap_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
        }
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
            Cap_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
            Duty = 100 - (float)Cap_val2 / (float)Cap_val1 * 100;
            Frequency = 0.001 * Cap_val1;
        }
    }
}

运行结果
在这里插入图片描述

实验总结

在实验中,我深入研究和理解了STM32定时器的工作原理。我掌握了控制LED开/关状态的定时器计数方法,并成功实现了LED以2秒的频率周期性开/关。随后,我学习了脉宽调制(PWM)的生成方法,并将LED控制模式切换为PWM模式。通过适当调整周期和占空比,我成功地实现了LED以呼吸灯的形式逐渐打开和关闭。
在观察PWM输出波形的过程中,我使用了Keil虚拟示波器。通过观察波形,我可以直观地了解PWM信号的变化,从而验证我的编程结果。这使我更加熟悉使用示波器进行波形分析的方法。
在这次实验使我更加熟悉了STM32F103单片机的应用和编程,也增强了我的实践能力和解决问题的能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值