STM32使用定时器进行串口通信和点灯

STM32使用定时器进行串口通信和点灯

一. 定时器介绍

1.功能简介

STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和 TIME7 等基本定时器。
三种定时器功能如下:
在这里插入图片描述
STM32 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT) 构成。STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波 形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形 周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相 共享的任何资源。 STM3 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能包括:
在这里插入图片描述
在这里插入图片描述

2. 计数器模式

  1. 向上计数模式
    在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。

  2. 向下计数模式
    在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。

  3. 中央对齐计数模式
    在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。

3. 时基单元

可编程通用定时器的主要部分是一个16位计数器和与其相关的自动装载寄存器。这个计数器可
以向上计数、向下计数或者向上向下双向计数。此计数器时钟由预分频器分频得到。 计数器、自动装载寄存器和预分频器寄存器可以由软件读写,在计数器运行时仍可以读写。
时基单元包含:
在这里插入图片描述
定时器频率=时钟频率/(PSC+1)(ARR+1)
在这里插入图片描述

4. 定时器时钟源

定时器的时钟来源有 4 个:
在这里插入图片描述
这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。这里的 CK_INT
时钟是从 APB1 倍频的来的,除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx 的时钟
是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于 APB1
的时钟。

二. 工程建立

1.题目要求

之前博客中的延时功能都是通过循环delay/Hal_delay函数等实现,本次作业通过定时器Timer方式实现时间的精准控制,相当于给CPU上了一个闹钟,CPU平时处理其它任务,当定时时间到了以后,处理定时相关的任务。请设置一个5秒的定时器,每隔5秒从串口发送“hello windows!”;同时设置一个2秒的定时器,让LED等周期性地闪烁。

2.工程建立

(1)创建新项目

在STMCubeMX主界面,创建新项目,点击ACCEE TO MCU SELECTOR
在这里插入图片描述

(2)芯片选择

在part name里选择自己的芯片(一般选择直接搜索所需芯片),本文采用STM32F103C8T6点击信息栏中的具体芯片信息选中,点击start project
在这里插入图片描述

(3)配置RCC

点System Cor,选择RCC,在右侧弹出的菜单栏中选Crystal/Ceramic Resonator
在这里插入图片描述

(4)配置SYS

选择调试接口,点System Cor,选择SYS。,在右侧弹出的菜单栏中选Serial Wire。
在这里插入图片描述

(5)配置IO口输出

选择PA1作为LED灯的输出,将其选为GPIO-OUT,使用这一个灯,做演示用。
在这里插入图片描述

(6)配置定时器2和定时器3

这里我们使用定时器2和定时器3来实现定时的功能。如图所示,依次点击位置1,选中定时器2;位置2,配置定时器2的时钟源为内部时钟;位置3,分频系数为71,向上计数模式,计数周期为5000,使能自动重载模式。
在这里插入图片描述
在这里插入图片描述
注意;分频系数那里虽然写的是71,但系统处理的时候会自动加上1,所以实际进行的是72分频。由于时钟我们一般会配置为72MHZ,所以72分频后得到1MHZ的时钟。1MHZ的时钟,计数5000次,得到时间5000/1000000=0.005秒。也就是每隔0.005秒定时器2会产生一次定时中断。

(7)配置中断

如下图所示,开启定时器2和定时器3的中断。
在这里插入图片描述
如下图所示,生成定时器2和定时器3中断优先级配置代码。
在这里插入图片描述

(8)配置USART

选择Connectivity,点开USART1,Mode选择异步通信Asynchronous
(波特率为115200,1位停止位,无校验位(这里不需要改,默认就是这样))
在这里插入图片描述

(9)时钟配置

如图所示更改配置
在这里插入图片描述

(10)配置项目设置

在这里插入图片描述

(11)生成项目

在这里插入图片描述

三. 代码编写

1.启动定时器

	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_Base_Start_IT(&htim3);

2.串口通信

在main.c中定义STM32需要给上位机发送的消息

	uint8_t hello[20]="hello windows!\r\n";

进行串口通信
将其放入后续的定时器中断回调函数

  HAL_UART_Transmit(&huart1,hello,20,100000);

3.定时器中断回调函数

该函数为定时器的中断回调函数,当产生定时中断的时候,会自动调用这个函数。在函数内部定义了定时器的一个静态变量:time_cnt与定时器3 的time_cnt3。
例如time_cnt,当它大于等于100的时候,才会执行if里面的代码。也就是说需要发生400次中断,才会让LED的状态翻转。前面已经算过了,一次定时中断的时间是0.005秒,所以400次中断的时间是0.005400=2秒。也就是说每隔2秒,LED的状态翻转一次。
例如time_cnt3,当它大于等于1000的时候,才会执行if里面的代码。也就是说需要发生1000次中断,才会让串口发一次消息。0.0051000=5秒,符合题目要求。

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);
		}
			
	}
}

四. 结果演示

定时器

定时器

五. 总结

通过次实验,理解和掌握了定时器的原理,在之前的实验中,都是通过软件延时的方式进行延时,但是软件延时存在很不好的缺点,那就是不准确且浪费CPU资源,通过定时器的方式解决了这种缺点。

参考博客
https://blog.youkuaiyun.com/sjsnsnsnsi/article/details/134232474
https://blog.youkuaiyun.com/weixin_64559251/article/details/127561710

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值