▼点击下方名片,关注公众号,获取更多精彩内容▼
欢迎关注【玩转单片机与嵌入式】公众号,回复关键字获取更多免费视频和资料
回复【加群】,【单片机】、【STM32】、【硬件知识】、【硬件设计】、【经典电路】、【论文】、【毕业设计】、【3D封装库】、【PCB】、【电容】、【TVS】、【阻抗匹配】、【资料】、【终端电阻】、【Keil】、【485】、【CAN】、【振荡器】、[USBCAN]、【PCB】、【智能手环】、【智能家居】、【智能小车】、【555】、【I2C】、【华为】、【中兴】,等……
当涉及到单片机编程时,延时是一项常见但关键的任务。在许多应用中,我们需要控制程序暂停一段时间,以实现精确的时间控制或协调不同设备之间的操作。本文将以STM32为例,介绍关于单片机的延时原理以及常用的延时函数方法。
延时的原理
单片机的延时是通过控制处理器执行一系列指令来实现的。每条指令需要一定的时间来执行,而延时就是利用这些指令的执行时间来达到暂停程序执行的目的。延时的精确性和稳定性受到处理器的时钟频率、编译器优化等因素的影响。
延时方法
1. 软件延时
软件延时是最常见的延时方法之一,适用于大多数STM32单片机。基本思路是通过循环执行空操作或简单指令来消耗时间,从而实现延时。
#include "stm32f4xx.h"
void softwareDelay(uint32_t delay_ms) {
uint32_t i, j;
for(i = 0; i < delay_ms; i++) {
for(j = 0; j < 1000; j++) {
__NOP(); // 空操作,消耗时间
}
}
}
#include "stm32f4xx.h"
void timerDelay(uint32_t delay_ms) {
// 配置定时器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_InitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1; // 1us计数一次
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_Period = delay_ms * 1000; // 延时的微秒数
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_InitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_InitStruct);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
// 等待定时器计数完成
while (TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) == RESET) {
}
// 清除标志位
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
}
volatile uint32_t millisecond = 0;
void SysTick_Handler(void) {
millisecond++; // SysTick中断每毫秒触发一次
}
void nonBlockingDelay(uint32_t delay_ms) {
uint32_t start = millisecond;
while (millisecond - start < delay_ms) {
// 等待延时结束,期间可以处理其他任务
}
}
在上述代码中,我们使用了STM32的SysTick定时器,每毫秒触发一次中断。通过记录开始时间和当前时间的差值,可以实现非阻塞的延时效果。
延时函数的设计
为了方便使用延时,我们可以封装一个延时函数,根据不同的延时方法选择合适的实现。
#include "stm32f4xx.h"
void delay(uint32_t delay_ms) {
// 根据选择的延时方法调用对应的函数
// 如:softwareDelay(delay_ms);
// 或:timerDelay(delay_ms);
// 或:nonBlockingDelay(delay_ms);
}
#include "stm32f4xx.h"
volatile uint32_t millisecond = 0;
void SysTick_Handler(void) {
millisecond++; // SysTick中断每毫秒触发一次
}
void nonBlockingDelay(uint32_t delay_ms) {
uint32_t start = millisecond;
while (millisecond - start < delay_ms) {
// 等待延时结束,期间可以处理其他任务
}
}
int main(void) {
// 初始化SysTick定时器
SystemCoreClockUpdate();
SysTick_Config(SystemCoreClock / 1000); // 配置成每毫秒触发一次中断
// 初始化其他硬件和外设
while (1) {
// 执行主要任务
// 进行非阻塞延时
nonBlockingDelay(1000); // 延时1秒
}
}
总结
END
扫描上方二维码加群,回复【加群】或扫码加我好友,限时免费进入技术交流群。
推荐阅读
【专辑】器件选型
【专辑】单片机
【专辑】经验分享
【专辑】STM32
【专辑】硬件设计
【专辑】软件设计
【专辑】开源项目
【专辑】职业发展
感谢大家阅读,如果喜欢
请点赞和“在看”吧,或者分享到朋友圈。
点击跳转到原文,限时优惠加入我们的知识星球(加好友获取免费券)