STM32精确延时(非中断,非ST库函数)

发布者:温馨阳光最新更新时间:2018-04-23 来源: eefocus关键字:STM32  精确延时  非中断  非ST库函数 手机看文章 扫描二维码
随时随地手机看文章

     前天学了下stm的systick,发现还满好用的,可以用来精确定时.以前在用CVAVR的时候发现里面的delay.h非常好用.于是,利用stm32的SysTick做了个精确的延时头函数.


     SysTick的配置在void delay_init(u8 SYSCLK);里面输入的参数SYSCLK是你配置的系统时钟,比如72M,我就调用delay_init(72);然后就完成了对SysTick的初始化设置.在后面调用delay_ms(u32 Nms);delay_us(u32 Nus);就可以得到很准确的延时.


注意:


1,delay_us(u32 Nus);在Nus值很小的时候,误差比较大,我仿真的时候delay_us(1);实际上得到的是延时了1.5us左右.理论上Nus的值越大,越准确.


2,delay_ms(u32 Nms);的参数不能太大!更具你系统时钟来确定.72M的时候Nms的最大值是1864.在其他晶振(<72M)条件下,该值会变大.计算方法:Nms<=0xffffff*8/SYSCLK.


    在包括了这个头函数之后可以得到很准确的延时,也不会产生中断,其他中断可以打断delay_us,delay_ms的执行.


#ifndef __DELAY_H

#define __DELAY_H       

//使用SysTick的普通计数模式对延迟进行管理

//包括delay_us,delay_ms  

//正点原子@SCUT

//2008/12/13  

static u8  fac_us=0;//us延时倍乘数

static u16 fac_ms=0;//ms延时倍乘数

//初始化延迟函数

void delay_init(u8 SYSCLK)

{

SysTick->CTRL&=0xfffffffb;//选择内部时钟 HCLK/8

fac_us=SYSCLK/8;      

fac_ms=(u16)fac_us*1000;

}            

//延时Nms

//注意Nms的范围

//Nms<=0xffffff*8/SYSCLK

//对72M条件下,Nms<=1864 

void delay_ms(u16 nms)

{    

SysTick->LOAD=(u32)nms*fac_ms; //时间加载  

SysTick->CTRL|=0x01;               //开始倒数    

while(!(SysTick->CTRL&(1<<16)));   //等待时间到达 

SysTick->CTRL&=0XFFFFFFFE;         //关闭计数器

SysTick->VAL=0X00000000;           //清空计数器     

}   

//延时us           

void delay_us(u32 Nus)

SysTick->LOAD=Nus*fac_us;       //时间加载      

SysTick->CTRL|=0x01;            //开始倒数    

while(!(SysTick->CTRL&(1<<16)));//等待时间到达 

SysTick->CTRL=0X00000000;       //关闭计数器

SysTick->VAL=0X00000000;        //清空计数器     

}  

#endif


另外的一种方法 :


/*---------------------------------

延时模块函数

说明:只需在工程中加入delay.c和delay.h

文件,即可用 Delayms(__IO uint32_t nTime);

Delayus(__IO uint32_t nTime)

-----------------------------------*/

#ifndef __DELAY_H

#define __DELAY_H

#include "stm32f10x.h"

/*--------------------------------- 

描 述:参数1即为1ms,1000即为1s;只有几

us的误差;

-----------------------------------*/

extern void Delayms(__IO uint32_t nTime);


/*---------------------------------

描 述:参数1即为1us,1000即为1ms;只有几

us的误差;

-----------------------------------*/

extern void Delayus(__IO uint32_t nTime);

/*---------------------------------

函数名:延时调整形式的delaynus函数, 

描 述:参数1即为1us,1000即为1ms;

-----------------------------------*/

extern void delay_nus(unsigned long n);

/*---------------------------------

函数名:延时调整形式的delaynms函数, 

描 述:参数1即为1ms,1000即为1s;

-----------------------------------*/

extern void delay_nms(unsigned long n);

#endif


C 函数


/*---------------------------------

延时模块函数

说明:只需在工程中加入delay.c和delay.h

文件,即可用 Delayms(__IO uint32_t nTime);

Delayus(__IO uint32_t nTime)

-----------------------------------*/

#include"delay.h"

static __IO uint32_t TimingDelay;

/* Private function prototypes -----------------------------------------------*/

/*---------------------------------

函数名:ms延时函数 

描 述:参数1即为1ms,1000即为1s;只有几

us的误差;

-----------------------------------*/

void Delayms(__IO uint32_t nTime) 

while(SysTick_Config(SystemCoreClock/1000)); 

TimingDelay = nTime;

while(TimingDelay != 0);

SysTick->CTRL=0x00; //关闭计数器 

SysTick->VAL =0X00; //清空计数器 

}

/*---------------------------------

函数名:us延时函数 

描 述:参数1即为1us,1000即为1ms;只有几

us的误差;

-----------------------------------*/

void Delayus(__IO uint32_t nTime)

while(SysTick_Config(SystemCoreClock/1000000)); 

TimingDelay = nTime;

while(TimingDelay != 0);

SysTick->CTRL=0x00; //关闭计数器 

SysTick->VAL =0X00; //清空计数器 

}

/*---------------------------------

函数名:延时辅助函数 

描 述: 

-----------------------------------*/

void TimingDelay_Decrement(void)

{

if (TimingDelay != 0x00)

TimingDelay--;

}

}

/*---------------------------------

函数名:systick的中断函数 

描 述:参数1即为1us,1000即为1ms;只有几

us的误差;

-----------------------------------*/

void SysTick_Handler(void)

{

TimingDelay_Decrement();

}

/*---------------------------------

函数名:延时调整形式的delaynus函数, 

描 述:参数1即为1us,1000即为1ms;

-----------------------------------*/

void delay_nus(unsigned long n)

{

unsigned long j;

while(n--)

{

j=12;

while(j--);

}

}

/*---------------------------------

函数名:延时调整形式的delaynms函数, 

描 述:参数1即为1ms,1000即为1s;

-----------------------------------*/

void delay_nms(unsigned long n)

{

while(n--)

delay_nus(1030);

}


关键字:STM32  精确延时  非中断  非ST库函数 引用地址:STM32精确延时(非中断,非ST库函数)

上一篇:STM32F4(用SysTick实现Delay函数)
下一篇:STM32F429 Discovery FMC驱动原子4.3寸LCD

推荐阅读最新更新时间:2024-03-16 16:00

stm32串口字节丢失怎么办?
“STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据0x01 0x02 0x03 0x04..接收端收到的数据为:0x02 0x03 0x04,第一个数据丢失。换成发送别的数值的数据,如0x06 0x0ff,则接收到0x0ff,0x06丢失。错误依旧。 故障排除过程:1、刚开始怀疑是接收端的错误,我是使用电脑串口,运行串口辅助调试工具接收,换成其他软件后,发现故障依旧,而且电脑软件一直是开启状态,不像和电脑软件有关。2、使用单步调试,单步运行各个发送指令,都正常。能收到0x01
[单片机]
<font color='red'>stm32</font>串口字节丢失怎么办?
STM32中I2C总线上数据的读、写。
/** * @brief 从I2C1总线上的某一器件的某一起始地址中读取一定字节的数据到数组中 * @param driver_Addr:I2C器件地址 * @param start_Addr:起始字节地址 * @param number_Bytes:要读取的字节数量(小于一页) * @param read_Buffer:存放读取数据的数组指针 * @retval 是否读取成功 */ u8 I2C1_Read_NBytes(u8 driver_Addr, u8 start_Addr, u8 number_Bytes, u8 *read_Buffer) { uint8_t read_Num; u8 I2C_Tim
[单片机]
什么是时钟树架构
2.1 时钟树结构图 STM32属于Cortex-M3内核的单片机,时钟结构比之前的51单片机较复杂的多,根据数据手册,STM32F103的时钟结构如下图所示。 根据上图可以看到,STM32F103系列单片机具有4个时钟源,内部的8MHz时钟发生器,外部的晶体振荡器接口,最高支持16MHz,外部的32.768kHz晶体振荡器接口和内部的40kHz时钟发生器,其中32.768kHz和40kHz主要用于内部RTC时钟脉冲,8MHz的晶振通过PLL时钟倍乘器,将系统总线时钟提高为72MHz。 STM32F103系列内部具有2条外设时钟总线,APB1和APB2,其中APB2的时钟最高可达72MHz,APB1的时钟最高可达36MHz
[单片机]
什么是时钟树架构
STM32的多个ADC模块如何同时采样转换详细应用实例说明
在STM32家族里,多数系列芯片内含2到3个ADC模块,有的甚至更多,比方G4系列可以有5个ADC模块。其中,通道数因不同的系列或型号多少不等,几个到几十个的都有。有时,我们可能需要多个ADC模块同时工作,比方3个ADC模块同时采样转换。这时如果芯片内含有3个ADC模块,并支持同时采样转换就很方便。比方STM32F4系列、STM32F7等其它系列都含有3个ADC模块,并支持同时AD采样转换。 这里就3个ADC模块同时进行采样转换应用,做个简单实现示例,以供有需要的用户参考。此时3个ADC模块会建立主从关系。以STM32F4芯片为例。内部大致框架如下: 采样转换时按如下图示操作,每次对分别属于3个ADC模块的3个通道进行AD
[单片机]
<font color='red'>STM32</font>的多个ADC模块如何同时采样转换详细应用实例说明
stm32学习笔记--串口波特率
这几天的学习有什么问题呢?开始看前几个例程的时候貌似还找到些感觉,学了些东西,比如串口需要配置的波特率是如何计算的,如何通过位段位带别名区的设计实现对I/O口单个位的寻址操作,端口模式如何设置,spi与iic之间各自的优势和劣势,上个周稀里糊涂看了那么多,现在一想就剩下这些了,然后是这个周,这个周的感觉是更加的不扎实,很多东西都是走马观花,看了就忘,比如中断控制,直到看了第二遍才形成框架,看门狗DMA游戏手柄红外通信的各个实验,好吧,这些东西我仅仅知道是怎么回事,对他们的了解甚至不如上个周的模块,至少还有个框架,到了这里,只剩下 哦,这个,我知道 就没了,对!就没了。所以接下来要去改程序,不管改什么程序,当然最好是直接拿三轴加速度
[单片机]
STM32的启动堆栈初始化
有几个问题,众多博文中抄来抄去,内容一样,却没有解释清楚 上电初始化堆栈,在进入_main后又说初始化堆栈,有什么不同 堆栈的地址是怎么得出来的 关于这两个问题,先借用一下要标准的启动流程 一般而言,系统上电后第一个执行的是由汇编所编写的启动文件,其主要工作为一下五部分: (1)、初始化堆栈指针SP=_initial_sp (2)、初始化PC指针,令其=Reset_Handler (3)、初始化中断向量表 (4)、配置系统时钟 (5)、调用C库函数_main初始化用户堆栈,从而最终调用main函数进入C的世界 STM32的中断向量表规定每一行必须是SP地址,第二行是复位中断入口地址,上电后,C
[单片机]
STM32学习日志——输入捕获实验
今天学习的是通用定时器的第三个功能——输入捕获,它的作用是检测到TIMx_CHx的边沿跳变(上升沿或下降沿),即可将当前定时器的存放在捕获/比较寄存器中。 输入捕获滤波器可以通过TIMx_CCMR1的ICF位去控制N个跳变捕获一次,以此达到滤波的作用。TIMx_CCER的CC1P位捕获输出极性,是捕获上升沿或者下降沿。TIMx_CCMR1的CC1S位控制输入还是输出,以及输入脚的选择。TIMx_CCMR1的ICPS位控制输入的分频。TIMx_CCER的CC1E位控制捕获使能。 本次要用输入捕获功能来测量信号的脉冲宽度,用按键作输入,即测量按下的时间。首先配置输入捕获,在第一次上升沿处触发中断,将定时器清零,将STA清零并将bi
[单片机]
RC522读写程序代码分享
#include stm32f10x.h #include stm32f10x_spi.h #include stm32f10x_gpio.h #include stm32f10x_rcc.h #include delay.h #include mfrc522.h #include stdio.h #define SPI_CE_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4) #define SPI_CE_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4) void SPI1_Init(void) { RCC_AP
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved