STM32硬件调试过程遇中到Delay_ms()函数卡死的问题

AI助手已提取文章相关产品:
程序在LCD初始化过程中卡死,通过硬件调试发现卡在Delay_ms()函数,转到定义发现其为Delay_us的宏定义函数:
#define Delay_ms(x) Delay_us(1000*x)//单位ms
即延迟x单位ms,转到Delay_us()函数定义:
void Delay_us(__IO u32 nTime)
{ 
    TimingDelay = nTime;    
    while(TimingDelay != 0);
}
可以发现若参数TimingDelay不为零则此处为while死循环,通过研究发现TimingDelay参数需要在系统滴答定时器中断中递减,即:
/**@filename stm32f10x_it.c 
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
    TimingDelay_Decrement();
}
函数TimingDelay_Decrement()定义如下:
/*-------------------------------------------------------------------------------
程序名称:TimingDelay_Decrement
程序描述:数字递减直到0  
输入参数:无
返回参数:无
备    注:需要在中断函数SysTick_Handler()中调用
---------------------------------------------------------------------------------*/
void TimingDelay_Decrement(void)
{
    if (TimingDelay != 0x00)
    { 
    TimingDelay--;
    }
}
程序卡死的原因就是中断函数SysTick_Handler(void)中没有对TimingDelay进行递减(没有调用函数TimingDelay_Decrement())从而跳不出死循环
另外值得注意的是SysTick使用前必须初始化,以使能中断:
void SysTick_Init(void)
{
     // SystemFrequency / 1000       1ms中断一次
     // SystemFrequency / 100000     10us中断一次
     // SystemFrequency / 1000000    1us中断一次

    if (SysTick_Config(SystemCoreClock / 1000000))    // 1us ST3.5.0库版本
    { 
        /* Capture error */ 
        while (1);
    }
}
若不使能中断会导致无法进入定时器中断函数,也会卡死在while循环中。

您可能感兴趣的与本文相关内容

<think>首先,用户的问题是关于“Delay函数在编程中的使用及实现方法”。根据系统级指令,我需要: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 参考提供的引用: - 引用[1]: 讨论delay()函数在Arduino中的阻塞行为。 - 引用[2]: 进一步解释delay()在Arduino中的阻塞问题。 - 引用[3]: 描述sleep()函数在Linux中的使用,包括单位(秒、毫秒、微秒)。 - 引用[4]: 提到在51单片机C编程中,delay函数通常在.c和.h文件中实现。 - 引用[5]: 展示了一个51单片机的代码示例,使用delay()函数。 用户意图是寻找与Delay函数相关的技术信息,可能用于编程中的延时操作。所以,我需要覆盖Delay函数的常见使用场景、实现方法、优缺点,以及替代方案。 结构回答: 1. **介绍Delay函数**:解释什么是Delay函数,它在编程中的作用。 2. **使用场景**:描述在哪些情况下使用Delay函数,如嵌入式系统、微控制器等。 3. **实现方法**:讨论如何实现Delay函数,包括基于循环的延时、系统调用如sleep()等。 4. **优缺点**:分析Delay函数的优点和缺点,特别是阻塞行为。 5. **替代方案**:建议非阻塞的延时方法,如使用定时器中断或异步编程。 6. **代码示例**:提供简单的代码示例来说明实现。 7. **生成相关问题**:在末尾添加相关问题。 确保使用中文回答。 添加引用标识:在引用引用内容时,在末尾添加[^1]、[^2]等。 例如,如果提到delay()的阻塞行为,引用[1]和[^2]。 现在,大纲回答: - **开头**:直接回答问题,概述Delay函数。 - **主体**: - 解释Delay函数的基本概念和作用。 - 使用场景:在Arduino、51单片机、Linux系统等。 - 实现方法:包括软件延时(循环)和硬件/系统延时(sleep、usleep)。 - 优缺点:优点简单易用;缺点阻塞执行。 - 替代方案:如使用millis()在Arduino,或定时器中断。 - 代码示例:提供简单的C或Python示例。 - **结尾**:总结建议,生成相关问题。 生成相关问题:基于内容,创建3-5个相关问题,如: 1. 如何在非阻塞方式下实现延时? 2. Delay函数在实时系统中的适用性? 3. 不同编程语言中Delay函数的实现差异? 确保回答真实可靠:基于标准编程知识,参考提供的引用。 最后,添加引用标识:在相关句子末尾。</think>### Delay函数在编程中的使用及实现方法 在编程中,Delay函数(或延时函数)是一种常用工具,用于在代码执行过程中引入人为的暂停时间。这种函数广泛应用于嵌入式系统、微控制器编程(如Arduino或51单片机)、操作系统脚本以及实时任务处理中。其主要目的是控制程序流程,例如等待硬件响应、实现动画效果或协调多任务执行。然而,Delay函数的实现方式和行为因编程环境和需求而异,使用时需注意其潜在的阻塞问题。下面我将逐步介绍Delay函数的使用场景、实现方法、优缺点及替代方案,帮助您全面理解。 #### 1. **Delay函数的基本概念和作用** - **作用**:Delay函数的核心是暂停程序执行一段指定时间。参数通常以毫秒(ms)或微秒(μs)为单位,例如`delay(1000)`表示暂停1秒。在简单应用中,这可以避免CPU过载或确保时序正确,如LED闪烁或传感器数据读取。 - **数学表示**:如果延时时间为$t$毫秒,函数行为可抽象为: $$ \text{delay}(t) : \text{暂停执行} \quad \text{for} \quad t \text{ ms} $$ 其中$t$是正实数,代表延时长度。在嵌入式系统中,这常与时钟频率相关,例如基于循环计数实现延时。 #### 2. **使用场景** - **嵌入式系统**:在Arduino或51单片机中,Delay函数用于控制硬件操作。例如,引用[5]中的代码展示了如何用`delay()`实现LED移位效果:通过`delay(1000)`暂停1秒,使LED灯循环亮起[^5]。类似地,在机器人控制中,Delay可用于舵机转动或电机调速。 - **操作系统级编程**:在Linux或Windows中,类似函数如`sleep()`或`usleep()`用于进程暂停。引用[3]指出,`sleep(unsigned int seconds)`会让进程休眠指定秒数,而`usleep()`提供微秒级精度,适用于脚本或后台任务[^3]。 - **通用编程**:在Python或C语言中,Delay可用于模拟耗时操作,如游戏开发或测试脚本。例如,Python的`time.sleep(1)`等价于延时1秒。 - **注意事项**:Delay函数在实时系统或多任务环境中需谨慎使用,因为其阻塞行为可能导致响应延迟。引用[1]和[2]强调,在Arduino中,`delay()`会完全暂停其他代码执行,影响并发性能[^1][^2]。 #### 3. **实现方法** Delay函数的实现依赖编程语言和硬件平台,主要分为软件延时和系统调用两类。核心原理是利用CPU时钟或系统计时器。 - **软件延时(基于循环)**: - 在资源受限的嵌入式系统(如51单片机),Delay常通过空循环实现。这需要精确计算循环次数来匹配时钟频率。 - **示例代码(C语言,51单片机)**: 引用[5]展示了简单实现,其中`delay(uint z)`函数通过嵌套循环延时`z`毫秒[^5]。假设时钟频率为12MHz,一个机器周期为1μs,则延时1ms需约1000次循环。 ```c void delay(unsigned int z) { unsigned int i, j; for (i = 0; i < z; i++) { for (j = 0; j < 120; j++); // 调整循环次数以匹配时钟 } } ``` - **数学基础**:延时时间$t$(ms)与循环次数$n$的关系为: $$ t = n \times \text{循环周期} $$ 其中循环周期取决于CPU指令速度。例如,如果每条指令耗时$1 \mu s$,则$n = 1000$对应1ms延时。 - **优点**:简单、不依赖外部库,适用于裸机编程。 - **缺点**:精度低,且在高负载系统中可能被中断打断。 - **系统调用(基于OS或硬件)**: - 在操作系统环境中,如Linux或Windows,Delay通过系统函数实现,这些函数利用硬件定时器。 - `sleep()`:以秒为单位,如`sleep(1)`暂停1秒(引用[3])。 - `usleep()`:以微秒为单位,提供更高精度。 - 在Arduino中,`delay()`是内置函数,直接调用微控制器的计时器。 - **示例代码(Arduino)**: ```cpp void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); // LED开 delay(1000); // 暂停1秒 digitalWrite(LED_BUILTIN, LOW); // LED关 delay(1000); // 暂停1秒 } ``` - 这里,`delay(1000)`阻塞执行,直到时间结束[^1][^2]。 - **优点**:精度高,易于使用,且在多线程系统中可减少CPU占用。 - **缺点**:在单线程环境(如Arduino)中会阻塞整个程序。 #### 4. **优缺点分析** - **优点**: - **简单易用**:一行代码即可实现延时,适合快速原型开发。 - **低开销**:在简单项目中,无需额外硬件或复杂配置。 - **缺点**: - **阻塞行为**:这是主要问题Delay函数会暂停所有代码执行,导致系统无响应。引用[1]和[2]解释,在Arduino中,这会使传感器读取或通信中断,影响实时性[^1][^2]。 - **精度问题**:软件延时受CPU速度和中断影响,可能不准确;系统调用如`sleep()`在低优先级任务中可能被延迟。 - **资源浪费**:循环延时占用CPU周期,而阻塞延时可能造成任务调度效率低下。 #### 5. **替代方案及优化建议** 为避免阻塞问题,推荐使用非阻塞延时方法: - **定时器中断**:在嵌入式系统中,配置硬件定时器触发中断。例如,在Arduino中,用`millis()`函数检查时间差: ```cpp unsigned long previousTime = 0; const long interval = 1000; // 1秒 void loop() { unsigned long currentTime = millis(); if (currentTime - previousTime >= interval) { previousTime = currentTime; // 执行任务(如切换LED) } // 其他代码可同时运行 } ``` 这允许多任务并发,无阻塞[^2]。 - **异步编程**:在Python或JavaScript中,使用`asyncio.sleep()`(Python)或`setTimeout()`(JS),结合事件循环实现非阻塞延时。 - **系统级替代**:在Linux中,`nanosleep()`提供纳秒级精度,或使用信号处理(如`alarm()`)实现超时控制[^3]。 - **最佳实践**:在.h文件中声明Delay函数,在.c文件中实现,以提升代码模块性(引用[4])[^4]。对于高精度需求,考虑实时操作系统(RTOS)。 #### 总结 Delay函数是编程中基础的延时工具,适用于简单时序控制,但其阻塞特性在复杂系统中成为瓶颈。实现时,优先选择非阻塞方法(如定时器或异步调用)以提高效率。在嵌入式项目中,参考硬件文档调整延时精度;在OS级编程,利用`sleep()`或`usleep()`优化资源使用[^3][^5]。如果您有具体平台(如Arduino或Linux),我可以提供更针对性的示例。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值