目录
前言
软件版本: STM32CubeMX:6.61
KEIl:5.61
mcusip
FireTools
硬件: STM32F103C8T6
一.什么是定时器
定时器实际上就是Soc当中的一个内部外设。
1.定时器与计数器
定时器常与计数器扯到一起,计数器也是soc当中的一个内部外设,计数器顾名思义是用来计数的,就和我们的秒表一样,秒表实际上就是一个计数器,每隔一个单位走一个格(就是计一个数),因为计数器的计数时间周期是固定的,因此到了一定时间只要用计数值*计数时间周期,就能得到一个时间段,这个时间段就是我们定的时间(这就是定时器了)。计数器和定时器其实是一回事。
定时器/计数器作为SoC的外设,主要用来实现定时执行代码的功能。定时器相对于SoC来说,就好像闹钟相对于人来说意义一样。单核的CPU是单线程的,只能干一件事情,干完这件事情完去干另一件事情需要定时器来提醒。
2. 定时器有什么用
(1)定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU会去处理中断并执行定时器的ISR。从而去执行预先设定好的事件。
(2)定时器就好像是CPU的一个秘书一样,这个秘书专门管帮CPU来计时,并到时间后提醒CPU要做某件事情。所以CPU有了定时器之后,只需要预先把自己XX时间之后必须要做的事情绑定到定时器中断ISR即可,到了时间之后定时器就会以中断的方式提醒CPU来处理这个事情。
3. 定时器的原理
(1)定时器计时其实是通过计数来实现的。定时器内部有一个计数器,这个计数器根据一个时钟(这个时钟来自于ARM的APB总线,然后经过时钟模块内部的分频器来分频得到)来工作。每隔一个时钟周期,计数器就就计数一次,定时器的时间就是计数器计数值x时钟周期。
(2)定时器内部有1个寄存器TCNT,计时开始时我们会把一个总的计数值(譬如说300)放入TCNT寄存器中,然后每隔一个时钟周期(假设为1ms)TCNT中的值会自动减1(硬件自动完成,不需要CPU软件去干预),知道TCNT中减为0的时候,TCNT就会触发定时器中断。最后的计时时间就是300ms。
(3)定时时间是由2个东西共同决定的:一个是TCNT中的计数值,一个是时钟周期。譬如上例中,定时周期就为300x1ms=300ms。
4.时钟产生器和时基单元
内部时钟(CK_INT)
外部时钟模式 1:外部输入脚(TIx)
外部时钟模式 2:外部触发输入(ETR)
内部触发输入(ITRx):使用A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)。 这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。
时基单元就是定时器框图的第二部分,它包括三个寄存器,分别是:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)和自动装载寄存器(TIMx_ARR)。对这三个寄存器的介绍如下:
计数器寄存器(TIMx_CNT):向上计数、向下计数或者中心对齐计数;
计数器寄存器(TIMx_CNT):可将时钟频率按1到65535之间的任意值进行分频,可在运行时改变其设置值;
自动装载寄存器(TIMx_ARR):如果TIMx_CR1寄存器中的ARPE位为0,ARR寄存器的内容将直接写入影子寄存器;如果ARPE为1,ARR寄存器的那日同将在每次的更新时间UEV发生时,传送到影子寄存器;如果TIM1_CR1中的UDIS位为0,当计数器产生溢出条件时,产生更新事件。
二.用STM32CubeMx创建项目
1. 创建项目
打开项目,选择芯片
2.配置RCC和SYS
在System Core下选择RCC,将HSE改成Crystal/Ceramic Resonator
点击SYS,将Debug改成Serial Wire
3. 配置IO输出口
点击PA2,选择GPIO_Output
4. 配置定时器
选择定时器2和定时器3
在目录Timers下点击TIM2,将Clock Source时钟源选择为Internal Clock
内部时钟,设置分频系数为71,向上计数模式,计数周期为5000。
TIM3同上设置
5. 配置NVIC和USART1
点击NVIC,勾选TIM2和TIM3的中断
然后点击Code generation,勾选TIM2的中断优先级
在目录Connectivity下点击USART1,将Mode改为异步通信Asynchronous
6 .配置时钟
点击Clock,将HCLK改为72
7.项目配置
点击Project Manager,填入项目名称,将IDE改为MDK-ARM
,后面版本改为V5
点击GENERATE CODE
三.用keil实现
1.定时器启动代码
将代码放在主函数main.c下
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
2 .串口通信
代码如下
uint8_t hello[20]="hello windows!\r\n";
3.定时器中断回调函数
代码如下
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_2);
}
}
if(htim->Instance == TIM3)
{
if(++time_cnt3 >= 1000)
{
time_cnt3 =0;
HAL_UART_Transmit(&huart1,hello,20,100000);
}
}
}
4.烧录
5.展示效果
四.总结
通过这次实验我懂得了什么是定时器和如何使用定时器来达成目的,虽然在编写代码的时候多次出现错误,但是在查询资料和多次尝试后终于完成了任务.
五.参考资料
STM32定时器实现5秒周期串口通信,2秒LED灯闪烁