提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、STM32定时器的结构?
-
- [1. 51定时器的结构](#1. 51定时器的结构)
- [2. stm32定时器的结构](#2. stm32定时器的结构)
-
- [2.1 通用定时器](#2.1 通用定时器)
- 二、使用步骤
-
- 1.开启时钟
- 2.初始化定时器
- 3.中断配置(分组、优先级)
-
- [3.1 配置中断源](#3.1 配置中断源)
- 3.2配置中断优先级
- [3.3 开启定时器](#3.3 开启定时器)
- [3.4 中断服务函数](#3.4 中断服务函数)
- [3.5判断中断源, 清除中断源](#3.5判断中断源, 清除中断源)
- 三、参考初始化函数
-
- 3.1写成外设初始化函数,方便main函数调用
- 3.2中断函数
- [3.3 中断服务函数加入时分秒](#3.3 中断服务函数加入时分秒)
- 四、测试验证
-
- 4.1时钟使能查看
- [4.2 更新中断状态位](#4.2 更新中断状态位)
- [4.3 其他状态和配置](#4.3 其他状态和配置)
- 五、拓展
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
定时器有什么用?精准延时,PWM,做一个时钟:年月日,时分秒。时钟最基本的就是1s怎么来?
提示:以下是本篇文章正文内容,下面案例可供参考
一、STM32定时器的结构?
1. 51定时器的结构
1.1如何实现定时1s的功能?
- 选定时功能
- 装初值
- 配置定时器中断
- 中断里面计数,计数多少次根据定时的需要
2. stm32定时器的结构
2.1 通用定时器
部分芯片时没有基本定时器的
有基本定时器的型号
- 时钟来源RCC
- 控制器,应该是要使能
- 分频器
- 装计数初值
- 中断
二、使用步骤
1.开启时钟
代码如下(示例):
c
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
2.初始化定时器
代码如下(示例):
c
//TIM_TimeBaseInitStruct.TIM_ClockDivision=
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=50000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler= 72-1;
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct);
3.中断配置(分组、优先级)
3.1 配置中断源
timer6只有溢出中断
c
TIM_ITConfig( TIM6, TIM_IT_Update, ENABLE);
3.2配置中断优先级
c
NVIC_InitStruct.NVIC_IRQChannel=TIM6_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0; //0-3
NVIC_InitStruct.NVIC_IRQChannelSubPriority= 1; //0-3
NVIC_Init(&NVIC_InitStruct);
3.3 开启定时器
出了GPIO今后每个外设都要单独开启
c
TIM_Cmd( TIM6, ENABLE); //使能
3.4 中断服务函数
在启动文件找到中断向量表,然后完成中断服务函数
c
void TIM6_IRQHandler()
{
if(TIM_GetITStatus( TIM6, TIM_IT_Update))
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
num++;
if(num==20)
{
num=0;
//led取反
}
}
}
3.5判断中断源, 清除中断源
三、参考初始化函数
3.1写成外设初始化函数,方便main函数调用
c
void timer6()
{
/*
1.开启APB1时钟 72MHz
2.配置定时器6 TimeInit() 72预分配,0-65535 1000000us/50000us =CNT=20 定时时间/中断溢出时间=计数值
3.中断配置 分组,优先级 。开启中断源
4.中断服务函数 计数值, 1us ,计数20次后让一个LED取反
*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
//TIM_TimeBaseInitStruct.TIM_ClockDivision=
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=50000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler= 72-1;
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct);
//开启中断:
TIM_ITConfig( TIM6, TIM_IT_Update, ENABLE);
TIM_Cmd( TIM6, ENABLE); //使能
NVIC_InitStruct.NVIC_IRQChannel=TIM6_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0; //0-3
NVIC_InitStruct.NVIC_IRQChannelSubPriority= 1; //0-3
NVIC_Init(&NVIC_InitStruct);
}
3.2中断函数
c
void TIM6_IRQHandler()
{
if(TIM_GetITStatus( TIM6, TIM_IT_Update))
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
num++;
if(num==20)
{
num=0;
//led取反
}
}
}
3.3 中断服务函数加入时分秒
c
void TIM6_IRQHandler()
{
if(TIM_GetITStatus( TIM6, TIM_IT_Update))
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
num++;
if(num==20)
{
num=0;
//led取反
GPIOA->ODR^=0x0100;
// 异或,相同为0,不同为1
//拿0 去异或,原来是0,还是0;原来是1,还是1。既可以保持不变
//拿1 去异或,原来是0,变成1;原来是0,变成1。起到取反的作用
second++;
one_second_flag=1;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
}
}
}
四、测试验证
在中断服务函数设定断点
4.1时钟使能查看
4.2 更新中断状态位
4.3 其他状态和配置
五、拓展
串口: 时钟
- 通过串口获取时分秒
- 通过串口修改时间
总结
深入浅出,从51单片机定时结构到stm32定时结构引导讲解了,STM32如何实现定时1s的原理,并工程实现