日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

歷史上的今天

今天是:2025年07月20日(星期日)

2018年07月20日 | 使用SysTick的普通計數(shù)模式對延遲進(jìn)行管理

發(fā)布者:星塵之淚 來源: eefocus關(guān)鍵字:SysTick  普通計數(shù)模式  延遲 手機(jī)看文章 掃描二維碼
隨時隨地手機(jī)看文章

/*************delay.h*************************/


#ifndef __DELAY_H

#define __DELAY_H   

#include  

////////////////////////////////////////////////////////////////////////////////// 


//ALIENTEK STM32開發(fā)板

//使用SysTick的普通計數(shù)模式對延遲進(jìn)行管理

//包括delay_us,delay_ms

//正點(diǎn)原子@ALIENTEK

//技術(shù)論壇:www.openedv.com

//修改日期:2012/9/2

//版本:V1.5

//版權(quán)所有,盜版必究。

//Copyright(C) 廣州市星翼電子科技有限公司 2009-2019

//All rights reserved

//********************************************************************************

//V1.2修改說明

//修正了中斷中調(diào)用出現(xiàn)死循環(huán)的錯誤

//防止延時不準(zhǔn)確,采用do while結(jié)構(gòu)!



//V1.3修改說明

//增加了對UCOSII延時的支持.

//如果使用ucosII,delay_init會自動設(shè)置SYSTICK的值,使之與ucos的TICKS_PER_SEC對應(yīng).

//delay_ms和delay_us也進(jìn)行了針對ucos的改造.

//delay_us可以在ucos下使用,而且準(zhǔn)確度很高,更重要的是沒有占用額外的定時器.

//delay_ms在ucos下,可以當(dāng)成OSTimeDly來用,在未啟動ucos時,它采用delay_us實(shí)現(xiàn),從而準(zhǔn)確延時

//可以用來初始化外設(shè),在啟動了ucos之后delay_ms根據(jù)延時的長短,選擇OSTimeDly實(shí)現(xiàn)或者delay_us實(shí)現(xiàn).



//V1.4修改說明 20110929

//修改了使用ucos,但是ucos未啟動的時候,delay_ms中中斷無法響應(yīng)的bug.

//V1.5修改說明 20120902

//在delay_us加入ucos上鎖,防止由于ucos打斷delay_us的執(zhí)行,可能導(dǎo)致的延時不準(zhǔn)。

////////////////////////////////////////////////////////////////////////////////// 

void delay_init(u8 SYSCLK);

void delay_ms(u16 nms);

void delay_us(u32 nus);



#endif


/*************delay.c******************/


#include "delay.h"


#include "sys.h"

////////////////////////////////////////////////////////////////////////////////// 

//如果使用ucos,則包括下面的頭文件即可.

#if SYSTEM_SUPPORT_UCOS

#include "includes.h" //ucos 使用 

#endif

////////////////////////////////////////////////////////////////////////////////// 

//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途

//ALIENTEK STM32開發(fā)板

//使用SysTick的普通計數(shù)模式對延遲進(jìn)行管理

//包括delay_us,delay_ms

//正點(diǎn)原子@ALIENTEK

//技術(shù)論壇:www.openedv.com

//修改日期:2012/9/2

//版本:V1.5

//版權(quán)所有,盜版必究。

//Copyright(C) 廣州市星翼電子科技有限公司 2009-2019

//All rights reserved

//********************************************************************************

//V1.2修改說明

//修正了中斷中調(diào)用出現(xiàn)死循環(huán)的錯誤

//防止延時不準(zhǔn)確,采用do while結(jié)構(gòu)!



//V1.3修改說明

//增加了對UCOSII延時的支持.

//如果使用ucosII,delay_init會自動設(shè)置SYSTICK的值,使之與ucos的TICKS_PER_SEC對應(yīng).

//delay_ms和delay_us也進(jìn)行了針對ucos的改造.

//delay_us可以在ucos下使用,而且準(zhǔn)確度很高,更重要的是沒有占用額外的定時器.

//delay_ms在ucos下,可以當(dāng)成OSTimeDly來用,在未啟動ucos時,它采用delay_us實(shí)現(xiàn),從而準(zhǔn)確延時

//可以用來初始化外設(shè),在啟動了ucos之后delay_ms根據(jù)延時的長短,選擇OSTimeDly實(shí)現(xiàn)或者delay_us實(shí)現(xiàn).



//V1.4修改說明 20110929

//修改了使用ucos,但是ucos未啟動的時候,delay_ms中中斷無法響應(yīng)的bug.

//V1.5修改說明 20120902

//在delay_us加入ucos上鎖,防止由于ucos打斷delay_us的執(zhí)行,可能導(dǎo)致的延時不準(zhǔn)。

////////////////////////////////////////////////////////////////////////////////// 



static u8  fac_us=0;//us延時倍乘數(shù)   

static u16 fac_ms=0;//ms延時倍乘數(shù),在ucos下,代表每個節(jié)拍的ms數(shù)



#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.

//systick中斷服務(wù)函數(shù),使用ucos時用到

void SysTick_Handler(void)

{   

OSIntEnter(); //進(jìn)入中斷

    OSTimeTick();       //調(diào)用ucos的時鐘服務(wù)程序               

    OSIntExit();        //觸發(fā)任務(wù)切換軟中斷

}

#endif

  

//初始化延遲函數(shù)

//當(dāng)使用ucos的時候,此函數(shù)會初始化ucos的時鐘節(jié)拍

//SYSTICK的時鐘固定為HCLK時鐘的1/8

//SYSCLK:系統(tǒng)時鐘

void delay_init(u8 SYSCLK)

{

#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.

u32 reload;

#endif

  SysTick->CTRL&=~(1<<2);//SYSTICK使用外部時鐘源  

fac_us=SYSCLK/8;//不論是否使用ucos,fac_us都需要使用

   

#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.

reload=SYSCLK/8;//每秒鐘的計數(shù)次數(shù) 單位為K   

reload*=1000000/OS_TICKS_PER_SEC;//根據(jù)OS_TICKS_PER_SEC設(shè)定溢出時間

//reload為24位寄存器,最大值:16777216,在72M下,約合1.86s左右

fac_ms=1000/OS_TICKS_PER_SEC;//代表ucos可以延時的最少單位  

SysTick->CTRL|=1<<1;   //開啟SYSTICK中斷

SysTick->LOAD=reload; //每1/OS_TICKS_PER_SEC秒中斷一次 

SysTick->CTRL|=1<<0;   //開啟SYSTICK    

#else

fac_ms=(u16)fac_us*1000;//非ucos下,代表每個ms需要的systick時鐘數(shù)   

#endif

}    



#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.

//延時nus

//nus為要延時的us數(shù).      

void delay_us(u32 nus)

u32 ticks;

u32 told,tnow,tcnt=0;

u32 reload=SysTick->LOAD;//LOAD的值     

ticks=nus*fac_us; //需要的節(jié)拍數(shù)   

tcnt=0;

OSSchedLock();//阻止ucos調(diào)度,防止打斷us延時

told=SysTick->VAL;        //剛進(jìn)入時的計數(shù)器

while(1)

{

tnow=SysTick->VAL;

if(tnow!=told)

{    

if(tnow

else tcnt+=reload-tnow+told;   

told=tnow;

if(tcnt>=ticks)break;//時間超過/等于要延遲的時間,則退出.

}  

};

OSSchedUnlock();//開啟ucos調(diào)度    

}

//延時nms

//nms:要延時的ms數(shù)

void delay_ms(u16 nms)

if(OSRunning==TRUE)//如果os已經(jīng)在跑了   

{  

if(nms>=fac_ms)//延時的時間大于ucos的最少時間周期 

{

    OSTimeDly(nms/fac_ms);//ucos延時

}

nms%=fac_ms; //ucos已經(jīng)無法提供這么小的延時了,采用普通方式延時    

}

delay_us((u32)(nms*1000));//普通方式延時 

}

#else//不用ucos時

//延時nus

//nus為要延時的us數(shù).      

void delay_us(u32 nus)

u32 temp;      

SysTick->LOAD=nus*fac_us; //時間加載   

SysTick->VAL=0x00;        //清空計數(shù)器

SysTick->CTRL=0x01 ;      //開始倒數(shù)  

do

{

temp=SysTick->CTRL;

}

while((temp&0x01)&&!(temp&(1<<16)));//等待時間到達(dá)   

SysTick->CTRL=0x00;       //關(guān)閉計數(shù)器

SysTick->VAL =0X00;       //清空計數(shù)器 

}

//延時nms

//注意nms的范圍

//SysTick->LOAD為24位寄存器,所以,最大延時為:

//nms<=0xffffff*8*1000/SYSCLK

//SYSCLK單位為Hz,nms單位為ms

//對72M條件下,nms<=1864 

void delay_ms(u16 nms)

{   

u32 temp;   

SysTick->LOAD=(u32)nms*fac_ms;//時間加載(SysTick->LOAD為24bit)

SysTick->VAL =0x00;           //清空計數(shù)器

SysTick->CTRL=0x01 ;          //開始倒數(shù)  

do

{

temp=SysTick->CTRL;

}

while((temp&0x01)&&!(temp&(1<<16)));//等待時間到達(dá)   

SysTick->CTRL=0x00;       //關(guān)閉計數(shù)器

SysTick->VAL =0X00;       //清空計數(shù)器     

#endif





/*****************主程序 test.c**************/ 


#include "sys.h"

#include "usart.h" 

#include "delay.h" 

#include "led.h" 

#include "includes.h"

//ALIENTEK戰(zhàn)艦STM32開發(fā)板實(shí)驗(yàn)53

//UCOSII實(shí)驗(yàn)1-任務(wù)調(diào)度  

//技術(shù)支持:www.openedv.com

//廣州市星翼電子科技有限公司    





/////////////////////////UCOSII任務(wù)設(shè)置///////////////////////////////////

//START 任務(wù)

//設(shè)置任務(wù)優(yōu)先級

#define START_TASK_PRIO       10 //開始任務(wù)的優(yōu)先級設(shè)置為最低

//設(shè)置任務(wù)堆棧大小

#define START_STK_SIZE   64

//任務(wù)堆棧 

OS_STK START_TASK_STK[START_STK_SIZE];

//任務(wù)函數(shù)

void start_task(void *pdata); 

    

//LED0任務(wù)

//設(shè)置任務(wù)優(yōu)先級

#define LED0_TASK_PRIO       7 

//設(shè)置任務(wù)堆棧大小

#define LED0_STK_SIZE      64

//任務(wù)堆棧 

OS_STK LED0_TASK_STK[LED0_STK_SIZE];

//任務(wù)函數(shù)

void led0_task(void *pdata);





//LED1任務(wù)

//設(shè)置任務(wù)優(yōu)先級

#define LED1_TASK_PRIO       6 

//設(shè)置任務(wù)堆棧大小

#define LED1_STK_SIZE   64

//任務(wù)堆棧

OS_STK LED1_TASK_STK[LED1_STK_SIZE];

//任務(wù)函數(shù)

void led1_task(void *pdata);



int main(void)

{  

Stm32_Clock_Init(9); //系統(tǒng)時鐘設(shè)置

delay_init(72);    //延時初始化 

LED_Init(); 

LED_Init();   //初始化與LED連接的硬件接口

OSInit();   

  OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//創(chuàng)建起始任務(wù)

OSStart();    

}



 

//開始任務(wù)

void start_task(void *pdata)

{

    OS_CPU_SR cpu_sr=0;

pdata = pdata; 

  OS_ENTER_CRITICAL();//進(jìn)入臨界區(qū)(無法被中斷打斷)    

  OSTaskCreate(led0_task,(void *)0,(OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);  

  OSTaskCreate(led1_task,(void *)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);  

OSTaskSuspend(START_TASK_PRIO);//掛起起始任務(wù).

OS_EXIT_CRITICAL();//退出臨界區(qū)(可以被中斷打斷)

}



//LED0任務(wù)

void led0_task(void *pdata)

while(1)

{

LED0=0;

delay_ms(50);

LED0=1;

delay_ms(50);

};

}



//LED1任務(wù)

void led1_task(void *pdata)

{  

while(1)

{

LED1=0;

delay_ms(300);

LED1=1;

delay_ms(300);

};

}




/*********相關(guān)講解*************/ 


第五章  SYSTEM 文件夾介紹

上一章,我們介紹了如何在 MDK3.80A 下建立 STM32 工程,在這個新建的工程之中,我

們用到了一個 SYSTEM 文件夾里面的代碼,此文件夾里面的代碼由 ALIENTEK 提供,是

STM32F103 系列的底層核心驅(qū)動函數(shù),可以用在 STM32F103 系列的各個型號上面,方便大家快速構(gòu)建自己的工程。

SYSTEM 文件夾下包含了 delay、 sys、 usart 等三個文件夾。分別包含了 delay.c、 sys.c、 usart.c及其頭文件。通過這 3 個 c 文件,可以快速的給任何一款 STM32 構(gòu)建最基本的框架。使用起來是很方便的。

本章,我們將向大家介紹這些代碼,通過這章的學(xué)習(xí),大家將了解到這些代碼的由來,也

希望大家可以靈活使用 SYSTEM 文件夾提供的函數(shù),來快速構(gòu)建工程,并實(shí)際應(yīng)用到自己的項(xiàng)目中去。 

本章包括如下 3 個小結(jié):

5.1,delay 文件夾代碼介紹;

5.2,sys 文件夾代碼介紹;

5.3,usart 文件夾代碼介紹; 

5.1 delay 文件夾代碼介紹

delay 文件夾內(nèi)包含了 delay.c 和 delay.h 兩個文件,這兩個文件用來實(shí)現(xiàn)系統(tǒng)的延時功能,其中包含 3 個函數(shù)(這里我們不講 SysTick_Handler 函數(shù),該函數(shù)在講 ucos 的時候再介紹) :

void delay_init(u8 SYSCLK);

void delay_ms(u16 nms);

void delay_us(u32 nus);

下面分別介紹這三個函數(shù),在介紹之前,我們先了解一下編程思想:CM3 內(nèi)核的處理器,

內(nèi)部包含了一個 SysTick 定時器,SysTick  是一個 24  位的倒計數(shù)定時器,當(dāng)計到 0  時,將從RELOAD  寄存器中自動重裝載定時初值。只要不把它在 SysTick  控制及狀態(tài)寄存器中的使能位清除,就永不停息。SysTick 在《STM32 的參考手冊》(這里是指 V10.0 版本,下同)里面介紹的很簡單,其詳細(xì)介紹,請參閱《Cortex-M3 權(quán)威指南》第 133 頁。我們就是利用 STM32 的內(nèi)部 SysTick 來實(shí)現(xiàn)延時的,這樣既不占用中斷,也不占用系統(tǒng)定時器。

這里我們將介紹的是 ALIENTEK 提供的最新版本的延時函數(shù),該版本的延時函數(shù)支持在

ucos 下面使用,它可以和 ucos 共用 systick 定時器。首先我們簡單介紹下 ucos 的時鐘:ucos 運(yùn)行需要一個系統(tǒng)時鐘節(jié)拍(類似  “心跳”),而這個節(jié)拍是固定的(由 OS_TICKS_PER_SEC 設(shè)置),比如 5ms(設(shè)置:OS_TICKS_PER_SEC=200 即可),在 STM32 下面,一般是由 systick來提供這個節(jié)拍,也就是 systick 要設(shè)置為 5ms 中斷一次,為 ucos 提供時鐘節(jié)拍,而且這個時鐘一般是不能被打斷的(否則就不準(zhǔn)了)。

因?yàn)樵?ucos 下 systick 不能再被隨意更改,如果我們還想利用 systick 來做 delay_us 或者delay_ms 的延時,就必須想點(diǎn)辦法了,這里我們利用的是時鐘摘取法。以 delay_us 為例,比如delay_us (50),在剛進(jìn)入 delay_us 的時候先計算好這段延時需要等待的 systick 計數(shù)次數(shù),這里為 50*9 (假設(shè)系統(tǒng)時鐘為 72Mhz,那么 systick 每增加 1,就是 1/9us) ,然后我們就一直統(tǒng)計 systick的計數(shù)變化,直到這個值變化了 50*9,一旦檢測到變化達(dá)到或者超過這個值,就說明延時 50us時間到了。

下面我們開始介紹這幾個函數(shù)。

ALIENTEK 戰(zhàn)艦STM32開發(fā)板 www.openedv.com

79

5.1.1 delay_init 函數(shù)

該函數(shù)用來初始化 2 個重要參數(shù):fac_us 以及 fac_ms;同時把 SysTick 的時鐘源選擇為外部時鐘,如果使用了 ucos,那么還會根據(jù) OS_TICKS_PER_SEC 的配置情況,來配置SysTick的中斷時間,并開啟 SysTick 中斷。具體代碼如下:

//初始化延遲函數(shù)

//當(dāng)使用 ucos 的時候,此函數(shù)會初始化 ucos 的時鐘節(jié)拍

//SYSTICK 的時鐘固定為 HCLK 時鐘的 1/8

//SYSCLK:系統(tǒng)時鐘

void delay_init(u8 SYSCLK)

{

#ifdef OS_CRITICAL_METHOD //如果 OS_CRITICAL_METHOD 定義了,  則使用了 ucosII.

u32 reload;

#endif

SysTick->CTRL&=~(1<<2);  //SYSTICK 使用外部時鐘源

fac_us=SYSCLK/8;    //不論是否使用 ucos,fac_us 都需要使用   

#ifdef OS_CRITICAL_METHOD//如果 OS_CRITICAL_METHOD 定義了,則使用了 ucosII.

reload=SYSCLK/8;    //每秒鐘的計數(shù)次數(shù)  單位為 K 

reload*=1000000/OS_TICKS_PER_SEC;//根據(jù) OS_TICKS_PER_SEC 設(shè)定溢出時間

//reload 為 24 位寄存器,最大值:16777216,在 72M 下,約合 1.86s 左右

fac_ms=1000/OS_TICKS_PER_SEC;//代表 ucos 可以延時的最少單位 

SysTick->CTRL|=1<<1;      //開啟 SYSTICK 中斷

SysTick->LOAD=reload;    //每 1/OS_TICKS_PER_SEC 秒中斷一次

SysTick->CTRL|=1<<0;      //開啟 SYSTICK    

#else

fac_ms=(u16)fac_us*1000;   //非 ucos 下,代表每個 ms 需要的 systick 時鐘數(shù)  

#endif

}

可以看到,delay_init 函數(shù)使用了條件編譯,來選擇不同的初始化過程,如果不使用 ucos的時候,就和《不完全手冊》介紹的方法是一樣的,而如果使用 ucos 的時候,則會進(jìn)行一些不同的配置,這里的條件編譯是根據(jù) OS_CRITICAL_METHOD 這個宏來確定的,因?yàn)橹灰褂昧?ucos,就一定會定義 OS_CRITICAL_METHOD 這個宏。
SysTick 是 MDK 定義了的一個結(jié)構(gòu)體(在 stm32f10x_map.h 里面),里面包含 CTRL、 LOAD、VAL、CALIB 等 4 個寄存器,
SysTick->CTRL 的各位定義如圖 5.1.1.1 所示:

SysTick-> CALIB 不常用,在這里我們也用不到,故不介紹了。
SysTick->CTRL&=0xfffffffb;這一句把 SysTick 的時鐘選擇外部時鐘,這里需要注意的是:SysTick 的時鐘源自 HCLK 的 8 分頻,假設(shè)我們外部晶振為 8M,然后倍頻到 72M,那么 SysTick的時鐘即為 9Mhz,也就是 SysTick 的計數(shù)器 VAL 每減 1,就代表時間過了 1/9us。
在不使用 ucos 的時候:fac_us,為 us 延時的基數(shù),也就是延時 1us,SysTick->LOAD 所應(yīng)設(shè)置的值。 fac_ms 為 ms 延時的基數(shù),也就是延時 1ms, SysTick->LOAD 所應(yīng)設(shè)置的值。 fac_us為 8 位整形數(shù)據(jù), fac_ms 為 16 位整形數(shù)據(jù)。 Systick 的時鐘來自系統(tǒng)時鐘 8 分頻, 正因?yàn)槿绱?,系統(tǒng)時鐘如果不是 8 的倍數(shù)(不能被 8 整除),則會導(dǎo)致延時函數(shù)不準(zhǔn)確,這也是我們推薦外部時鐘選擇 8M 的原因。這點(diǎn)大家要特別留意。
當(dāng)使用 ucos 的時候, fac_us,還是 us 延時的基數(shù),不過這個值不會被寫到 SysTick->LOAD
寄存器來實(shí)現(xiàn)延時,而是通過時鐘摘取的辦法實(shí)現(xiàn)的(后面會介紹)。而 fac_ms 則代表 ucos 自帶的延時函數(shù)所能實(shí)現(xiàn)的最小延時時間(如 OS_TICKS_PER_SEC=200,那么 fac_ms 就是 5ms)。
5.1.2 delay_us 函數(shù)
該函數(shù)用來延時指定的 us,其參數(shù) nus 為要延時的微秒數(shù)。該函數(shù)有使用 ucos 和不使用ucos 兩個版本,這里我們分別介紹,首先是不使用 ucos 的時候,實(shí)現(xiàn)函數(shù)如下:
//延時 nus
//nus 為要延時的 us 數(shù).                       
void delay_us(u32 nus)
{   
ALIENTEK 戰(zhàn)艦STM32開發(fā)板 www.openedv.com
81
u32 temp;     
SysTick->LOAD=nus*fac_us; //時間加載       
SysTick->VAL=0x00;         //清空計數(shù)器
SysTick->CTRL=0x01 ;       //開始倒數(shù)   
do
{
temp=SysTick->CTRL;
}
while((temp&0x01)&&!(temp&(1<<16)));//等待時間到達(dá)
SysTick->CTRL=0x00;        //關(guān)閉計數(shù)器
SysTick->VAL =0X00;        //清空計數(shù)器   
}
有了上面對 SysTick 寄存器的描述,這段代碼不難理解。其實(shí)就是先把要延時的 us 數(shù)換算成 SysTick 的時鐘數(shù),然后寫入 LOAD 寄存器。然后清空當(dāng)前寄存器 VAL 的內(nèi)容,再開啟倒數(shù)
功能。等到倒數(shù)結(jié)束,即延時了 nus。最后關(guān)閉 SysTick,清空 VAL 的值。實(shí)現(xiàn)一次延時 nus的操作,但是這里要注意 nus 的值,不能太大,必須保證 nus<=(2^24)/fac_us,否則將導(dǎo)致延時時間不準(zhǔn)確。這里特別說明一下:temp&0x01,這一句是用來判斷 systick 定時器是否還處于開啟狀態(tài),可以防止 systick 被意外關(guān)閉導(dǎo)致的死循環(huán)。
再來看看使用 ucos 的時候,delay_us 的實(shí)現(xiàn)函數(shù)如下:
//延時 nus
//nus 為要延時的 us 數(shù).                         
void delay_us(u32 nus)

u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD;  //LOAD 的值     
ticks=nus*fac_us;         //需要的節(jié)拍數(shù)       
tcnt=0;
OSSchedLock();        //阻止 ucos 調(diào)度,防止打斷 us 延時
told=SysTick->VAL;           //剛進(jìn)入時的計數(shù)器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnowelse tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;//時間超過/等于要延遲的時間,則退出.
}  
};
OSSchedUnlock();      //開啟 ucos 調(diào)度                     
}
ALIENTEK 戰(zhàn)艦STM32開發(fā)板 www.openedv.com
82
這里就正是利用了我們前面提到的時鐘摘取法,ticks 是延時 nus 需要等待的 SysTick 計數(shù)次數(shù)(也就是延時時間),told 用于記錄最近一次的 SysTick->VAL 值,然后 tnow 則是當(dāng)前的SysTick->VAL 值,通過他們的對比累加,實(shí)現(xiàn) SysTick 計數(shù)次數(shù)的統(tǒng)計,統(tǒng)計值存放在 tcnt 里面,然后哦通過對比 tcnt 和 ticks,來判斷延時是否到達(dá),從而達(dá)到不修改 SysTick 實(shí)現(xiàn) nus 的延時,從而可以和 ucos 共用一個 SysTick。
上面的 OSSchedLock 和 OSSchedUnlock 是 ucos 提供的兩個函數(shù),用于調(diào)度上鎖和解鎖,這里為了防止 ucos 在 delay_us 的時候打斷延時,可能導(dǎo)致的延時不準(zhǔn),所以我們利用這兩個函數(shù)來實(shí)現(xiàn)免打斷,從而保證延時精度!同時,此時的 delay_us,可以實(shí)現(xiàn)最長 2^32us 的延時,大概是 4294 秒。
5.1.3 delay_ms 函數(shù)
該函數(shù)用來延時指定的 ms,其參數(shù) nms 為要延時的微秒數(shù)。該函數(shù)同樣有使用 ucos 和不使用 ucos 兩個版本,這里我們分別介紹,首先是不使用 ucos 的時候,實(shí)現(xiàn)函數(shù)如下: 
//延時 nms
//注意 nms 的范圍
//SysTick->LOAD 為 24 位寄存器,所以,最大延時為:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK 單位為 Hz,nms 單位為 ms
//對 72M 條件下,nms<=1864 
void delay_ms(u16 nms)
{           
u32 temp;   
SysTick->LOAD=(u32)nms*fac_ms;//時間加載(SysTick->LOAD 為 24bit)
SysTick->VAL =0x00;            //清空計數(shù)器
SysTick->CTRL=0x01 ;           //開始倒數(shù)
do
{
temp=SysTick->CTRL;
}
while((temp&0x01)&&!(temp&(1<<16)));//等待時間到達(dá)
SysTick->CTRL=0x00;        //關(guān)閉計數(shù)器
SysTick->VAL =0X00;        //清空計數(shù)器       
}
此部分代碼和 5.1.2 節(jié)的 delay_us(非 ucos 版本)大致一樣,但是要注意因?yàn)?LOAD 僅僅是一個 24bit 的寄存器,延時的 ms 數(shù)不能太長。否則超出了 LOAD 的范圍,高位會被舍去,導(dǎo)致延時不準(zhǔn)。最大延遲 ms 數(shù)可以通過公式:nms<=0xffffff*8*1000/SYSCLK  計算。SYSCLK單位為 Hz,nms 的單位為 ms。如果時鐘為 72M,那么 nms 的最大值為 1864ms。超過這個值,建議通過多次調(diào)用 delay_ms 實(shí)現(xiàn),否則就會導(dǎo)致延時不準(zhǔn)確。
再來看看使用 ucos 的時候,delay_ms 的實(shí)現(xiàn)函數(shù)如下:
//延時 nms
//nms:要延時的 ms 數(shù)
void delay_ms(u16 nms)
ALIENTEK 戰(zhàn)艦STM32開發(fā)板 www.openedv.com
83
{
if(OSRunning==TRUE)//如果 os 已經(jīng)在跑了 

if(nms>=fac_ms)//延時的時間大于 ucos 的最少時間周期
{
OSTimeDly(nms/fac_ms);//ucos 延時
}
nms%=fac_ms;//ucos 已經(jīng)無法提供這么小的延時了,采用普通方式延時
}
delay_us((u32)(nms*1000));  //普通方式延時
}
該函數(shù)中,OSRunning 是 ucos 正在運(yùn)行的一個標(biāo)志,OSTimeDly 是 ucos 提供的一個基于ucos 時鐘節(jié)拍的延時函數(shù),其參數(shù)代表延時的時鐘節(jié)拍數(shù)(假設(shè)OS_TICKS_PER_SEC=200,
那么 OSTimeDly(1),就代表延時 5ms)。
當(dāng) ucos 還未運(yùn)行的時候,我們的 delay_ms 就是直接由 delay_us 實(shí)現(xiàn)的, ucos 下的 delay_us可以實(shí)現(xiàn)很長的延時而不溢出! ,所以放心的使用 delay_us 來實(shí)現(xiàn) delay_ms,不過由于 delay_us的時候,任務(wù)調(diào)度被上鎖了,所以還是建議不要用 delay_us 來延時很長的時間,否則影響整個系統(tǒng)的性能。
當(dāng) ucos 運(yùn)行的時候,我們的 delay_ms 函數(shù)將先判斷延時時長是否大于等于 1 個 ucos 時鐘節(jié)拍 (fac_ms) ,當(dāng)大于這個值的時候,我們就通過調(diào)用 ucos 的延時函數(shù)來實(shí)現(xiàn) (此時任務(wù)可以調(diào)度) ,不足 1 個時鐘節(jié)拍的時候,直接調(diào)用 delay_us 函數(shù)實(shí)現(xiàn)(此時任務(wù)無法調(diào)度) 。


關(guān)鍵字:SysTick  普通計數(shù)模式  延遲 引用地址:使用SysTick的普通計數(shù)模式對延遲進(jìn)行管理

上一篇:STM32系統(tǒng)學(xué)習(xí)——SysTick(系統(tǒng)定時器)
下一篇:STM32中,systick具體延時時間計算

推薦閱讀

對于現(xiàn)場可編程門陣列(FPGA)、圖形處理器(GPU)和嵌入式計算器件等低電壓、高功耗應(yīng)用而言,管理并降低功耗至關(guān)重要。這些器件首先必須準(zhǔn)確測量功耗才能對其進(jìn)行管理,但高精度的功率測量解決方案通常意味著高成本,而且需要多個集成電路(IC)或電源配置來測量不同的軌道。為了滿足這些需求,Microchip Technology Inc.(美國微芯科技公司)推出全新...
綜合能源服務(wù)是一種基于泛在電力物聯(lián)網(wǎng)技術(shù),以滿足客戶多元化、個性化能源需求為中心,以提高能源利用效率、降低客戶用能成本、促進(jìn)新能源發(fā)展為目標(biāo)的業(yè)態(tài)。綜合能源服務(wù)的發(fā)展,一方面得益于泛在電力物聯(lián)網(wǎng)的全面賦能,另一方面需要攻破政策機(jī)制、技術(shù)等壁壘。未來基于泛在電力物聯(lián)網(wǎng),綜合能源的發(fā)展將進(jìn)一步服務(wù)于智慧城市與智慧能源,并切實(shí)服務(wù)于...
日前,SIA發(fā)布文章,表示美國的確應(yīng)該關(guān)注其芯片制造份額的下降,但是關(guān)注點(diǎn)應(yīng)該放在更多地方,而不應(yīng)只圍繞中國。文章作者為:全球政策研究總裁Devi Keller,全球政策研究副總裁Jimmy Goodrich以及研究經(jīng)理Zhi Su以下是文章詳情:長期以來,中國一直是美國商用半導(dǎo)體的重要市場,占美國芯片銷售總額的三分之一以上。這是因?yàn)橹袊娮咏M裝大國,成品芯...
1. 準(zhǔn)備工作硬件準(zhǔn)備首先需要準(zhǔn)備一個開發(fā)板,這里我準(zhǔn)備的是STM32L4的開發(fā)板(BearPi):軟件準(zhǔn)備需要安裝好Keil - MDK及芯片對應(yīng)的包,以便編譯和下載生成的代碼。2.生成MDK工程 — 初始化GPIO為輸入選擇芯片型號打開STM32CubeMX,打開MCU選擇器:搜索并選中芯片STM32L431RCT6:配置時鐘源如果選擇使用外部高速時鐘(HSE),則需要在System Core中...

史海拾趣

小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved