用TIM2来做延时,延时基准时间1ms,最大可延时65535ms。
系统基础频率是8MHz*4=32MHz。
先配置定时器:
TIM_TimeBaseInitTypeDef timInitStruct;
timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 定时器基准频率32MHz
timInitStruct.TIM_Prescaler = 32000; // 计数频率为1KHz
timInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
timInitStruct.TIM_RepetitionCounter = 0;
timInitStruct.TIM_Period = 0; // 这个值实际上就是TIMX->ARR,延时开始时重新设定即可
TIM_TimeBaseInit(TIM2, &timInitStruct);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 计数溢出时触发中断
TIM_Cmd(TIM2, DISABLE);
把定时器的计数频率定为1KHz,这样每1ms计数一次,可以做1ms为基准的延时。
定义延时函数:
u8 _delayTimeOut;
void delay1ms(u16 delayTime)
{
_delayTimeOut = 0;
TIM2->ARR = delayTime;
TIM_Cmd(TIM2, ENABLE);
while(!_delayTimeOut)
{
}
TIM_Cmd(TIM2, DISABLE);
}
定义计数溢出时的中断函数:
extern u8 _delayTimeOut;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
_delayTimeOut = 1;
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
}
}
原来的一个思路是配置定时器每1ms就中断一次(TIMX->ARR值固定),在延时前将全局的延时计数器清零(该值在中断中不断累加),然后比较计数器值与欲延时的值,超过了就停止,就像这样:
void delay1ms(u16 delayTime)
{
_delayTimer = 0; // 延时计数器
TIM_Cmd(TIM2, ENABLE);
while(_delayTimer < delayTime)
{}
TIM_Cmd(TIM2, DISABLE);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
_delayTimer++;
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
}
}
关键字:STM32 定时器 精确延时 SysTick
引用地址:
STM32用定时器精确延时的方法(非SysTick)
推荐阅读最新更新时间:2024-03-16 15:15
STM32之点亮LED灯程序
原理图: 程序: #include stm32f10x.h GPIO_InitTypeDef GPIO_InitStructure; #define LED1_ON GPIO_SetBits(GPIOB, GPIO_Pin_5); //#define LED1_ON GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_SET); #define LED1_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_5); //#define LED1_OFF GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_RESET) ; #def
[单片机]
STM32F03定时器基础知识基本简介
一、思维导图 三、定时器基本简介 (一)定时器分类 STM32F103微控制器的定时器分为 系统定时器(SysTick) 、 “看门狗”定时器(WatchDog) 、 基本定时器 、 通用定时器 、高级定时器和 实时时钟(RTC) 等。 系统定时器(SysTick) :是一个集成在Cortex-M3内核当中的定时器,Cortex-M3内核附带SysTick的主要目的是 给实时操作系统(RTOS)提供时间基准(时钟节拍 ),SysTick是不允许被用户直接使用的。 “看门狗”定时器(WatchDog) :“看门狗”定时器连接到STM32微控制器芯片的复位电路, 在定时器溢出时会触发复位操作 。 实时时钟RTC :是一个带独
[单片机]
STM32开发笔记97: C++语言命名规范
单片机型号:STM32F091RCT6 在此文章中记录C++语言的命名规范。 1、文件名均采用小写英文字母方式实现,多个英文单词之间用“_ 予以分割; 2、宏定义均采用大写英文字母方式实现,多个英文单词之间用“_ 予以分割; 3、自定义数据类型均小写英文字母方式实现,多个英文单词之间用“_ 予以分割; 4、类名首字母用C表示,后续采用匈牙利命名法,首字母大写,如遇英文缩写单词,则按照英文命名规范进行拼写,例如LED为缩写单词,但是英文规范可以写作led或Led,则类名用CLed表示,而HAL是硬件映射层的缩写,英文用全大写表示,使用时,则使用CHAL命名; 5、用类声明的类对象,去除首字母C即可,例如CLe
[单片机]
STM32 xPSR影响的条件指令
最近在学ARM Cortex-M3,找了本号称很经典的书“An Definitive Guide to The ARM Cortex-M3”在看。这个系列学习笔记其实就是在学习这本书的过程中做的读书笔记。 无条件跳转指令 跳转指令分为无条件跳转和有条件跳转两大类。无条件跳转类指令非常简单,常见的就四种形式。 B Label ;跳转到Label处对应的地址, 无条件跳转指令 BX reg ;跳转到由寄存器reg给出的地址, 无条件跳转指令 BL Label ;跳转到Label对应的地址,并且把跳转前的下条指令地址保存到LR BLX reg ;跳转到由寄存器reg给出的地址,并根据REG的LSB切换处理器状态,还要把转移前的下条
[单片机]
STM32--基本定时器的应用
实验目的:使用基本定时器TIM6控制LED的亮灭。 void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); } void TIM6_Init(void) { TIM_TimeBaseIn
[单片机]
stm32中程序内存的理解和一些问题的解决
一个小的项目,在测试时间和产品量稍微大一些之后,出现了一些莫名其妙的非逻辑错误的Bug(最头疼的是不能每次都能复制出来)。经过修改后,最近一个月的测试都没有出现。本人在这里得到了原子哥和其他朋友的很多帮助,也把自己的一些经验分享给各位,也欢迎大家指正。 1. 程序偶尔会出现一些Bug,经过output串口信息发现一些堆栈的临时变量被莫名其妙的修改。 stm32103rbt6的内存是20K,算比较小了,看到程序出错的那个函数申请了很多零时变量,也需要访问很多全局变量。猜想是内存被其他操作更改所致。 解决ram被使用过多的一个方法是尽量少用全局变量,能用const就用一定用const变量,因为这样会放在flash,而不是ram. 我的
[单片机]
stm32 Ctext-M3内核最简单的多任务RTOS
RTOS 实时操作系统,我做的是一个多任务的操作系统,可以同时运行多个任务,我这里设置的最大任务数是32个, 估计跑30多个任务的嵌入式设备很少吧,32个任务够用了。 OS我把它叫做HesOS,主要功能如下,比较简单。 1--实现多任务调度 2--实现任务调度锁 3--实现临界区保护 4--实现读取cpu使用率(这个功能比较重要的) 5--实现us延时(用于模拟如IIC总线模拟) 对于一般的嵌入式应用有这些功能,差不多够用了。 移植HesOS也非常简单,不会像其它的OS一样比较庞大,修改的地方也比较多,使用起来也复杂。 HesOS不管是移植和使用都是非常简单的,类似于PC的线程使用。 主
[单片机]
STM32控制步进电机程序
步进电机(也称脉冲电机)(将电脉冲转换为相应的角位移或线位移的电磁机械装置,具有快速启动,停能力,在电机的负荷不超过它能提供的动态转矩时,可以通过输入脉冲来控制它在一瞬间的启动或者停止。在非超载的情况下,步距角和转速只和输入的脉冲频率有关,和环境温度,气压,振动无关,也不受电网电压的波动和负载变化的影响,因此,控制较为精准)即给电机一个脉冲信号,电机则转过一个步距角 步进电机是一种感应电机,它的工作原理:利用电子电路,将直流电变成分时供电的,多相时序控制电流,用这种电流为步进电机供电,步进电机才能正常工作,驱动器就是为步进电机分时供电的,多相时序控制器,就是说:必须用由双环形脉冲信号功率驱动电路等组成的控制系统方可使用。 步距角:
[单片机]