STM32延时不同写法

本文介绍了STM32延时的三种方法:普通延时函数、定时器计数和Systick定时器。普通延时简单但不精准,定时器计数提高精度但占用CPU资源,Systick定时器则能实现精准延时并优化资源利用。通过Systick_Config()配置中断时间,并结合时间与频率公式计算延迟。延时函数需用到全局volatile变量,中断处理需注意固件库的systick中断函数处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于STM32系列的延时函数有着不同的写法,本章将给大家带来最简单的延时到最精准延时函数的各种写法及原理。
在STM32系列中要学会用好systick定时器,这很重要

一.普通延时函数

原理
用C中累加或者累减的方法,到一定条件后就退出。
好处
好写,用for循环或者while循环,不用去理解各种有关底层硬件的寄存器。
坏处
延时不精准,误差大,让CPU持续空跑,大大浪费CPU资源。

void delay(uint16 i)
{
	#if 0
	while(i--)
	{}
	#endif
	for(int j=0;j<i;j++)
	{}
}

二.定时器计数

在32中,使用定时器的地方很多,所以对于32中各种稀缺的外设资源极其珍贵,用好各种外设对于小白来说是关键的一步。
原理
采用C中累加原理,选定某一定时器,通过计数器来产生中断。
好处
可达到精准延时,但会使CPU在定时器中持续累加或累减,占用CPU资源。

这里随便举的一个例子

void TIM4_Init(u16 ar,u16 rs)
{
	TIM_TimeBaseInitTypeDef TIM_InitStrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能定时器时钟
	
	TIM_InitStrue.TIM_Period=ar;//自动装载值
	TIM_InitStrue.TIM_Prescaler=rs;//预分频系数的设置
	TIM_InitStrue.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_InitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseInit(TIM4,&TIM_InitStrue);//初始化定时器,对定时器进行配置
	
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//开启定时器中断
	
	NVIC_InitStrue.NVIC_IRQChannel=TIM4_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStrue.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStrue);//初始化中断,设置中断的优先级

	TIM_Cmd(TIM4,ENABLE);//使能定时器
}

void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET)
	{
		LED1=!LED1;
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中断标志位
	}
}	

三、Systick定时器

关于滴答定时器,我的理解为可以替代所有的定时器中有关涉及到时间的问题配置,可以让定时器更好的配合其他功能使用,而定时器中的计数器寄存器可以用于PID之类,更好的控制精度。

在此处介绍两种有关Systcik定时器的使用方法

(1).同样运用CPU持续在滴答定时器进行计数

void delay_us(u32 i)
 8 {
   
   
 
<think>首先,用户的问题是:“我想在STM32微控制器上实现流水灯效果的编程方法 请问如何使用STM32编写流水灯程序”。这涉及STM32微控制器编程,特别是流水灯效果的实现。 从系统级指令中,我需要: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 回答结构要清晰,帮助用户逐步解决问题,保证真实可靠。 参考提供的引用: - 引用[1]: STM32F103流水灯实现教程。提到项目简单,为学习其他功能打基础,可调整LED数量和闪烁模式。 - 引用[2]: 利用STM32实现流水灯程序。使用STM32F103C8芯片,在Keil中创建新工程。 - 引用[3]: STM32控制流水灯。包含头文件代码,定义GPIO端口和引脚,初始化函数等。 这些引用是关于STM32流水灯实现的,所以我应该基于这些信息构建回答。 关键步骤: 1. **硬件准备**:需要STM32开发板(如STM32F103系列)、LED灯、电阻、连接线等。 2. **软件开发环境**:使用Keil MDK-ARMSTM32CubeIDE进行编程。 3. **编程步骤**: - 配置GPIO引脚为输出模式。 - 初始化时钟。 - 编写控制LED的代码,实现流水灯效果(如顺序点亮和熄灭)。 - 使用定时器或延时函数来控制切换速度。 4. **代码示例**:基于引用[3],提供简化代码。 结构化回答: - 介绍流水灯概念。 - 逐步指导如何实现。 - 提供代码片段。 - 解释关键部分。 - 生成相关问题。 使用中文回答。 添加引用:在引用的段落末尾添加[^1]、[^2]、[^3]。例如,提到教程时添加[^1]。 确保回答真实可靠:基于标准STM32编程实践。 最终回答结构: 1. 引言:解释流水灯效果。 2. 硬件准备。 3. 软件设置。 4. 编程步骤。 5. 代码示例。 6. 测试和调试。 7. 相关问题。 生成相关问题:在最后添加“相关问题”部分。</think>### 如何使用STM32编写流水灯程序 流水灯效果是一种常见的嵌入式系统项目,其中多个LED灯按顺序依次点亮和熄灭,形成“流动”的视觉效果。在STM32微控制器上实现此功能,需要结合硬件配置和软件编程。下面我将以STM32F103系列为例(如STM32F103C8T6),逐步指导您完成流水灯程序的编写。整个过程基于Keil MDK-ARM开发环境(也可使用STM32CubeIDE),并参考了相关教程和代码示例[^1][^2][^3]。请确保您已准备好以下硬件: - STM32开发板(如STM32F103C8T6最小系统板)。 - 多个LED灯(通常3-8个)及限流电阻(约220-470Ω)。 - 连接线,用于将LED阳极连接到STM32的GPIO引脚,阴极接地。 - USB转串口模块(用于烧录程序)。 #### 步骤1: 硬件连接 首先,将LED灯连接到STM32的GPIO引脚。例如,使用GPIOC端口(如引用[3]所示): - LED1连接到PC4。 - LED2连接到PC5。 - LED3连接到PC6。 - ...以此类推(最多支持8个LED)。 确保每个LED串联一个限流电阻(约220Ω),以防止电流过大损坏引脚。接地端连接到开发板的GND。这种配置简单易用,适用于初学者项目[^1]。 #### 步骤2: 软件环境设置 1. **安装开发工具**: - 下载并安装Keil MDK-ARM(免费版可用)或STM32CubeIDE。 - 安装STM32F1系列的支持包(如STM32CubeMX用于配置)。 - 参考引用[2],在Keil中创建新工程:选择芯片型号“STM32F103C8”,并配置为“STMicroelectronics”。 2. **工程初始化**: - 使用STM32CubeMX生成初始化代码(可选但推荐): - 打开CubeMX,选择您的芯片型号。 - 配置GPIO引脚为输出模式(如PC4-PC7设置为推挽输出,无上拉下拉)。 - 启用时钟(System Core > GPIO,确保GPIO端口时钟已使能)。 - 生成代码并导入Keil工程。 #### 步骤3: 编程实现流水灯效果 流水灯的核心是顺序控制LED的状态(点亮/熄灭),通常通过延时函数或定时器中断实现。以下是基于引用[3]的简化代码示例。我们将使用一个基本延时循环(简单但高效),适合初学者。 ##### 关键代码文件 创建以下文件(或添加到现有工程): 1. **main.c**:主程序入口。 2. **bsp_led.h** 和 **bsp_led.c**:LED控制函数(参考引用[3])。 **bsp_led.h(头文件)**: ```c #ifndef __LED_H #define __LED_H #include "stm32f1xx.h" // 包含STM32库头文件 // 定义LED引脚(以GPIOC为例) #define LED_GPIO_PORT GPIOC #define LED1_PIN GPIO_PIN_4 #define LED2_PIN GPIO_PIN_5 #define LED3_PIN GPIO_PIN_6 #define LED4_PIN GPIO_PIN_7 // 添加更多引脚定义(如需要) // 函数声明 void LED_Init(void); // LED初始化 void LED_Toggle(uint8_t led_index); // 切换指定LED状态 void Delay_ms(uint32_t ms); // 简单延时函数 #endif /* __LED_H */ ``` **bsp_led.c(源文件)**: ```c #include "bsp_led.h" #include "stm32f1xx_hal.h" // HAL库头文件 // LED初始化函数 void LED_Init(void) { // 启用GPIOC时钟 __HAL_RCC_GPIOC_CLK_ENABLE(); // 配置GPIO引脚为输出模式 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = LED1_PIN | LED2_PIN | LED3_PIN | LED4_PIN; // 添加所有使用的引脚 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速输出 HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct); // 初始状态:所有LED熄灭 HAL_GPIO_WritePin(LED_GPIO_PORT, LED1_PIN | LED2_PIN | LED3_PIN | LED4_PIN, GPIO_PIN_RESET); } // 简单延时函数(基于系统时钟循环) void Delay_ms(uint32_t ms) { for(uint32_t i = 0; i < ms * 1000; i++); // 调整循环次数以适应您的时钟频率(如72MHz) } // 切换LED状态函数 void LED_Toggle(uint8_t led_index) { switch(led_index) { case 0: HAL_GPIO_TogglePin(LED_GPIO_PORT, LED1_PIN); break; case 1: HAL_GPIO_TogglePin(LED_GPIO_PORT, LED2_PIN); break; case 2: HAL_GPIO_TogglePin(LED_GPIO_PORT, LED3_PIN); break; case 3: HAL_GPIO_TogglePin(LED_GPIO_PORT, LED4_PIN); break; // 添加更多case(如需要) default: break; } } ``` **main.c(主程序)**: ```c #include "stm32f1xx_hal.h" #include "bsp_led.h" int main(void) { // 初始化HAL库和系统时钟 HAL_Init(); SystemClock_Config(); // 此函数需在工程中实现(通常由CubeMX生成) // 初始化LED LED_Init(); // 主循环:实现流水灯效果 while (1) { for (uint8_t i = 0; i < 4; i++) { // 假设有4个LED LED_Toggle(i); // 点亮当前LED Delay_ms(500); // 延时500ms(控制流水速度) LED_Toggle(i); // 熄灭当前LED(或使用HAL_GPIO_WritePin直接设置) } } } ``` #### 步骤4: 编译、烧录和测试 1. **编译工程**:在Keil中点击“Build”编译代码,确保无错误。 2. **烧录程序**:使用ST-Link或USB转串口工具将程序烧录到STM32开发板。 3. **测试效果**:上电后,LED灯应依次点亮和熄灭,形成流水效果。如果效果不理想: - 检查硬件连接是否正确(如引脚是否对应)。 - 调整延时时间(如`Delay_ms(200)`缩短为更快流动)。 - 使用示波器或逻辑分析仪调试GPIO信号。 #### 优化建议 - **使用定时器中断**:为避免阻塞主循环,参考引用[3],启用TIM3定时器中断(在`HAL_TIM_PeriodElapsedCallback`中切换LED)。这更高效且节省CPU资源。 - **扩展功能**:如引用[1]所述,可添加按键控制流动方向或速度,满足不同需求。 - **能耗考虑**:在低功耗应用中,使用睡眠模式优化能耗。 这个项目虽然简单,但为学习STM32的GPIO控制、时钟配置和中断处理打下了基础[^1]。实际应用中,您可以根据板载资源调整LED数量和模式[^3]。 ### 相关问题 1. 如何用STM32定时器中断优化流水灯程序,以减少CPU占用? 2. 在STM32上实现流水灯时,如何处理多个GPIO端口的配置? 3. 流水灯效果在嵌入式系统中有哪些实际应用场景?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值