STM32 —— 定时器 点灯 与 串口通信

STM32 —— 定时器实战 点灯 与 串口通信

实验目的

通过定时器 Timer 方式实现时间的精准控制,相当于给 CPU 上了一个闹钟,CPU 平时处理其它任务,当定时时间到了以后,处理定时相关的任务。请设置一个 5 秒的定时器,每隔5秒从串口发送 “hello windows!” ;同时设置一个 2 秒的定时器,让 LED 等周期性地闪烁

实验原理

前面我们的程序都是通过 HAL_Delay 延时函数进行实现的,这种方式一直占用 CPU ,却没有做什么有意义的事情,我们此次实验通过使用 TIM 计时器,相当于一个时钟,能够定时执行相对应的任务,并且不影响我们在其他时间执行其他任务,这样,我们的 CPU 就能够被充分的利用,就不会产生无用功

关于 TIM 计时器的内容,请看我的另一篇博客:STM32 —— 定时器

HAL 库方法

CubeMX 项目配置

RCC 配置

SYS 配置

USART1 配置

TIM2 配置

这里我们配置使用内部时钟,将分频系数设置为 71 ,虽然我们设置的是 71 ,但是在系统处理的时候,会默认加上一,所以这里实际上进行的是 72 分频,由于我们在一般习惯设置 72MHz 的时钟,所以这里我们分频后得到的就是 1MHz 的时钟,我们设置计数次数为
1000,通过计算得知时间间隔为 0.001s ,也就是每隔 0.001s 定时器就会产生一次中断,这里的计数模式我们使用默认的向上计数模式即可,使能自动重载

NVIC 配置

将定时器 TIM2 配置为默认全局中断,然后还需要自动生成中断优先级相关代码段

引脚配置

代码设计

首先我们需要启动定时器,代码如下:

HAL_TIM_Base_Start_IT(&htim2);

然后我们需要重写定时器回调函数,这样就能够触发计时器,回调函数如下:

HAL_TIM_PeriodElapsedCallback(htim);

重写回调函数如下:

#define COUNTOF(a) (sizeof(a)/sizeof(*(a)))
uint8_t str[] = "Hello ppqppl!\r\n";
	
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	
	uint8_t time = 0;	// 设置时间变量
	
	if(htim->Instance == TIM2){	// 判断使用的时钟是 TIM2 通用时钟
		time++;
		if(time%2000 == 0){
				HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);	// 反转串口输出
		}
		if(time%5000 == 0){
				HAL_UART_Transmit(&huart1,str,COUNTOF(str),0xFFFF);	// 输出
				if(time%10000 == 0 && time != 0){
					time = 0;
				}
		}
	}
}

标准库方法

若有需要,后续会更新标准库写法

寄存器方法

若有需要,后续会更新寄存器写法

运行测试

虚拟串口测试

首先我们用 proteus 搭建仿真电路,电路如下:

仿真测试结果如下:

注意:由于 proteus 仿真运行更多要考虑我们对波形的检测,所以会将时间放慢,这里我在仿真编译时,将代码中设置的时间缩小到了十分之一,确保我们看到结果不会等待太长时间

接线示例




运行结果

image

这里由于博客限制图片上传大小的原因,将定时器设置时间压缩到要求时间的一半

波形检测

波形如下:


错误解决方法

由于函数名称过长,在写函数名称的时候一定要仔细查看,不要写错,否则就会产生本来函数内容没有问题,但是由于名称错误又看不到运行结果的情况

还有些启动程序没有反应,可能是没有启动定时器,注意要在主函数进行循环之前打开定时器,否则将会是一个无效程序

参考文档

  1. STM32CUBEMX_定时器控制LED闪烁
posted @ 2022-11-02 17:49  ppqppl  阅读(195)  评论(0编辑  收藏  举报