通过定时器Timer方式实现串口发送“hello windows!”及LED等周期性闪烁

一、定时器的相关介绍

1.定时器的含义

定时器是SoC的常见外设
(1)定时器和计数器。计数器是用来计数的(每隔一个固定时间会计一个数);因为计数器的计数时间周期是固定的,因此到了一定时间只要用计数值x计数时间周期,就可以得到一个时间段,这个时间段就是我们定的时间(这就是定时器)。
(2)定时器/计数器作为SoC的外设,主要用来实现定时执行代码的功能。定时器相对于SoC来说,就好象闹钟相对于人来说意义一样。

2.定时器的作用

1)定时器可以让SoC在执行主程序的同时,具有计时功能(通过定时器),到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU会去处理中断并执行定时器中断的ISR。从而去执行预先设定好的事件。
(2)定时器就好象是CPU的一个秘书一样,这个秘书专门管帮CPU来计时,并到时间后提醒CPU要做某件事情。所以CPU有了定时器之后,只需预先把自己xx时间之后必须要做的事情绑定到定时器中断ISR即可,到了时间之后定时器就会以中断的方式提醒CPU来处理这个事情。

3.定时器的原理

(1)定时器计时其实是通过计数来实现的。 定时器内部有一个计数器,这个计数器根据一个时钟(这个时钟源来自于ARM的APB总线 66MHz,然后经过时钟模块内部的分频器来分频得到)来工作。每隔一个时钟周期,计数器就计数一次,定时器的时间就是计数器计数值×时钟周期。

(2)定时器内部有1个寄存器TCNT,计时开始时我们会把一个总的计数值(初值)放入TCNT寄存器中,然后每隔一个时钟周期(假设为1ms)TCNT中的值会自动减1(硬件自动完成,不需要CPU软件去干预),直到TCNT中减为0的时候,TCNT就会触发定时器中断。

(3)定时时间是由2个东西共同决定的:一个是TCNT中的计数值,一个是时钟周期,两者的乘积即为最终定时的时间。

4.与定时器有关的器件

(1)PWM定时器
PWM(pulse wide modulation 脉宽调制)
PWM波形是一个周期性波形,周期为T,在每个周期内波形是完全相同的。每个周期内由一个高电平和一个低电平组成。
PWM波形有2个重要参数:一个是周期T,另一个是占空比 duty(占空比就是一个周期内高电平的时间除以周期时间的商)。
对于一个PWM波形,知道了周期 T和占空比duty,就可以算出这个波形的所有细节。譬如高电平时间为T x duty,低电平时间为T*(1-duty)。
PWM波形有很多用处,譬如通信上用PWM来进行脉宽调制对基波进行载波调制;在发光二极管LED照明领域可以用PWM波形来调制电流进行调光;用来驱动蜂鸣器等设备。
(2)系统定时器
(3)看门狗
其实是一个定时器,只不过定时器时间到了之后不只是中断,还可以复位CPU。
看门狗定时器和普通的定时器并无本质区别。定时器可以设定一个时间,在这个时间完成之前定时器不断计时,时间到的时候定时器会复位CPU(重启系统)。
普通设备重启不是问题,但是有些设备人工重启存在困难。这时候我们希望系统能够自己检验自己是否已经跑飞,并且在意识到自己跑飞的时候,可以很快的(几个ms或者更短)自我重启。这个功能就要靠看门狗定时器来实现。
我们在应用程序中打开看门狗设备,初始化好给它一个时间,然后应用程序使用一个线程来喂狗,这个线程的执行时间安全短于看门狗的复位时间。当系统(或者应用程序)异常后,喂狗线程自然就不工作了,然后到时候看门狗就会复位。
实战中有时候为了绝对的可靠,我们并不会用SoC中自带的看门狗,而是使用专门的外置的看门狗芯片来实现看门狗。
(4)实时时钟RTC(real time clock)
RTC是实时时钟,RTC是实时时钟,它和定时器的差别就好象闹钟(定时器)和钟表(RTC)的差别一样。
RTC是SoC中一个内部外设,RTC有自己独立的晶振提供RTC时钟源(32.768KHz),内部有一些寄存器用来记录时间(年月日时分秒星期)。一般情况下为了在系统关机时时间仍然在走,还会给RTC提供一个电池供电。

5.定时器的功能

(1)基本定时器(TIM6,TIM7)的主要功能:
只有最基本的定时功能,。基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。
(2)通用定时器(TIM2~TIM5)的主要功能:
除了基本的定时器的功能外,还具有测量输入信号的脉冲长度( 输入捕获) 或者产生输出波形( 输出比较和PWM)
(3)高级定时器(TIM1,TIM8)的主要功能:
高级定时器不但具有基本,通用定时器的所有的功能,还具有控制交直流电动机所有的功能,你比如它可以输出6路互补带死区的信号,刹车功能等等。

二、实现LED等周期性闪烁(2s),同时实现串口发送“hello windows!”(5s)

1.STM32CubeMX工程创建

(1)打开STM32CubeMX主界面,点击“ACCESS TO MCU SELECTOR”,创建新项目

(2)在“Commerical Part Number”里面选择自己需要的芯片,点击信息栏中的具体芯片信息选中,再点击“Start Project”

(3)先点击System Core将其展开,再点击RCC,将HSE设置为Crystal/Ceramic Resonator

(4)点击SYS,将Debug设置为Serial Wire

(5)点击GPIO,将C15设置为GPIO_Output

(6)先点击Timers将其展开,再点击TIM2,将“Clock Source”设置为Internal Clock,然后点击“Parameter Settings”,按下图设置相关参数

(7)点击NVIC,勾选TIM2 global interrupt

(8)点击Code generation,勾选生成定时器2中断优先级配置代码和HAL库配置代码

(9)先点击Connectivity将其展开,再点击USART1,将Mode设置为Asynchronous

(10)点击Clock Configuration勾选PLLCLK和HSE,将晶振频率设置为最大值72MHz

(11)点击Project Manager→Project,配置好自己的项目名和项目存放路径,然后将IDE设置为MDK-ARM

(12)点击Code Generate界面,选择生成初始化文件.c/.h,之后再点击GENERATE CODE即可成功创建工程

2.程序编写

(1)在点击GENERATE CODE之后弹出来的界面点击Open Project即可跳转到Keil5进行程序编写


(2)打开main.c文件
◉在main函数中加入如下代码:

HAL_TIM_Base_Start_IT(&htim2);

“htim2”中“h”表示HAL库,“tim2”表示定时器2。所以这行代码的意思就是启动定时器2。

◉在while循环后面添加如下代码:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t time_cnt =0;

	if(htim->Instance == TIM2)
	{
	
			++time_cnt;
		    int flag=0;
		if((time_cnt%400==0))
			{
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
				if(time_cnt>=1000)
				{
			time_cnt =0;
			char data[]="hello windows!\n";
			HAL_UART_Transmit(&huart1, (uint8_t *)data, 15, 0xffff);
				}
            }
		
	}
}

该函数为定时器的中断回调函数,当产生定时中断的时候,会自动调用这个函数。在函数内部定义了一个静态变量:time_cnt。当它≥400的时候,才会执行if里面的代码。也就是说需要发生400次中断,才会让LED的状态翻转。前面已经算过了,一次定时中断的时间是0.005秒,所以400次中断的时间是0.005*400=2秒。也就是说每隔2秒,LED的状态翻转一次。

3.程序编译及hex文件创建

点击Rebuild编译程序,若没有错误即可成功创建hex文件

4.电路连接

USB转TTLSTM32F103C8T6
GNDGND
3v33v3
TXDA10
RXDA9

LED负极接STM32F103C8T6的C15管脚,正极接3.3v管脚。

5.程序烧录

置BOOT0为0,BOOT1为1
(1)打开mcuisp,选择串口为COM5,并选择生成的hex文件

(2)点击读器件信息,若显示一切正常则进行下一步

(3)点击开始编程,若显示一切正常则说明烧录成功

6.串口调试

打开野火串口调试助手,将端口设置为COM5,波特率设置为115200,数据位设置为8,停止位设置为1,校验位设置为None,然后点击打开串口

7.运行结果



由上面两个运行结果可以看到,LED呈2s的等周期性闪烁;并且串口调试助手接收区每隔5s发送一次“hello windows!”,说明实验成功!

三、总结

本次实验通过定时器Timer方式实现时间的精准控制,实现了每隔5秒从串口发送“hello windows!”;同时实现了让LED呈2秒的等周期性闪烁。在实验过程中,我遇到了一些问题,例如对定时器理解不够导致STM32CubMX中某些参数未设置或设置错误,连接电路时未注意管脚导致连线错误,编写程序时添加的代码位置错误等,这些问题都导致达不到预期实验效果,经过一遍遍地检查与调试,最终实现了LED的周期闪烁和串口通信。通过本次实验,我了解了定时器的相关知识及应用,也对串口通信有了进一步的理解,但未来仍需好好学习相关知识,加深理解。

四、参考链接

http://www.mcublog.cn/stm32/2021_01/stm32cubemx-dingshiqi-led/
https://blog.csdn.net/jack123345667/article/details/108100283
https://blog.csdn.net/aricchen77/article/details/112298126

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值