打印
[STM32F1]

STM32系统滴答定时器实现

[复制链接]
231|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
alvpeg|  楼主 | 2024-9-27 09:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

Delay_us函数使用STM32系统滴答定时器实现

#include "systick.h"/* SystemFrequency / 1000    1ms中断一次 * SystemFrequency / 100000     10us中断一次 * SystemFrequency / 1000000 1us中断一次 */#define SYSTICKPERIOD                    0.000001#define SYSTICKFREQUENCY            (1/SYSTICKPERIOD)/**  * @brief  读取SysTick的状态位COUNTFLAG  * @param  无  * @retval The new state of USART_FLAG (SET or RESET).  */static FlagStatus SysTick_GetFlagStatus(void) {    if(SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk)     {        return SET;    }    else    {        return RESET;    }}/**  * @brief  配置系统滴答定时器 SysTick  * @param  无  * @retval 1 = failed, 0 = successful  */uint32_t SysTick_Init(void){       /* 设置定时周期为1us  */    if (SysTick_Config(SystemCoreClock / SYSTICKFREQUENCY))     {         /* Capture error */         return (1);    }    /* 关闭滴答定时器且禁止中断  */    SysTick->CTRL &= ~ (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);                                                      return (0);}/**  * @brief   us延时程序,10us为一个单位  * @param    *        @ARG nTime: Delay_us( 10 ) 则实现的延时为 10 * 1us = 10us  * @retval  无  */void Delay_us(__IO uint32_t nTime){         /* 清零计数器并使能滴答定时器 */      SysTick->VAL   = 0;      SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;         for( ; nTime > 0 ; nTime--)    {     /* 等待一个延时单位的结束 */     while(SysTick_GetFlagStatus() != SET);    }    /* 关闭滴答定时器 */    SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;}
View Code

检验Delay_us执行时间中用到的GPIO(gpio.h、gpio.c)的配置


#ifndef __GPIO_H#define    __GPIO_H#include "stm32f10x.h"#define     LOW          0#define     HIGH         1/* 带参宏,可以像内联函数一样使用 */#define TX(a)                if (a)    \                                            GPIO_SetBits(GPIOB,GPIO_Pin_0);\                                        else        \                                            GPIO_ResetBits(GPIOB,GPIO_Pin_0)void GPIO_Config(void);#endif
View Code



#include "gpio.h"    /**  * @brief  初始化GPIO  * @param  无  * @retval 无  */void GPIO_Config(void){                /*定义一个GPIO_InitTypeDef类型的结构体*/        GPIO_InitTypeDef GPIO_InitStructure;        /*开启LED的外设时钟*/        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);                                                                    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         GPIO_Init(GPIOB, &GPIO_InitStructure);    }
View Code

在main函数中检验Delay_us的执行时间
#include "systick.h"#include "gpio.h"/**  * @brief  主函数  * @param  无    * @retval 无  */int main(void){        GPIO_Config();    /* 配置SysTick定时周期为1us */    SysTick_Init();    for(;;)    {        TX(HIGH);         Delay_us(1);        TX(LOW);        Delay_us(100);    }     }
示波器的观察结果


  可见Delay_us(100),执行了大概102us,而Delay_us(1)执行了2.2us。
更改一下main函数的延时参数
int main(void){        /* LED 端口初始化 */    GPIO_Config();    /* 配置SysTick定时周期为1us */    SysTick_Init();    for(;;)    {        TX(HIGH);         Delay_us(10);        TX(LOW);        Delay_us(100);    }     }
示波器的观察结果


  可见Delay_us(100),执行了大概101us,而Delay_us(10)执行了11.4us。
结论:此延时函数基本上还是可靠的。

使用特权

评论回复
沙发
泡椒风爪| | 2024-9-27 16:41 | 只看该作者
Delay_us 函数的延时效果基本上是可靠的,可能是会存在一些小的误差。

使用特权

评论回复
板凳
键盘手没手| | 2024-9-27 16:48 | 只看该作者
可以考虑在关键区域添加中断禁用

使用特权

评论回复
地板
而服务器人| | 2024-9-30 03:10 | 只看该作者
延迟时间问题,长时间延迟情况下处理SysTick计数器溢出问题需要注意一下。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

1505

帖子

0

粉丝