STM32延时函数的四种方法:普通延时(2种)、SysTick 定时器延时(2种)
STM32延時(shí)函數(shù)的三種方法:普通延時(shí)、SysTick 定時(shí)器延時(shí)(1.中斷方式;2.非中斷方式)
?
單片機(jī)編程過(guò)程中經(jīng)常用到延時(shí)函數(shù),最常用的莫過(guò)于微秒級(jí)延時(shí)delay_us( )和毫秒級(jí)delay_ms( )。
1.普通延時(shí)法
(1)普通延時(shí)法1
這個(gè)比較簡(jiǎn)單,讓單片機(jī)做一些無(wú)關(guān)緊要的工作來(lái)打發(fā)時(shí)間,經(jīng)常用循環(huán)來(lái)實(shí)現(xiàn),不過(guò)要做的比較精準(zhǔn)還是要下一番功夫。下面的代碼是在網(wǎng)上搜到的,經(jīng)測(cè)試延時(shí)比較精準(zhǔn)。
//粗延時(shí)函數(shù),微秒 void delay_us(u16 time) {????u16 i=0;??while(time--){i=10;??//自己定義while(i--) ;????} } //毫秒級(jí)的延時(shí) void delay_ms(u16 time) {????u16 i=0;??while(time--){i=12000;??//自己定義while(i--) ;????} }(2)普通延時(shí)法2
void delay(u16 num) {u16 i,j;for(i=0;i<num;i++)for(j=0;j<0x800;j++); }2.SysTick?定時(shí)器延時(shí)
CM3?內(nèi)核的處理器,內(nèi)部包含了一個(gè)SysTick?定時(shí)器,SysTick?是一個(gè)24?位的倒計(jì)數(shù)定時(shí)器,當(dāng)計(jì)到0?時(shí),將從RELOAD?寄存器中自動(dòng)重裝載定時(shí)初值。只要不把它在SysTick?控制及狀態(tài)寄存器中的使能位清除,就永不停息。SysTick?在STM32的參考手冊(cè)里面介紹的很簡(jiǎn)單,其詳細(xì)介紹,請(qǐng)參閱《Cortex-M3?權(quán)威指南》。
?這里面也有兩種方式實(shí)現(xiàn):
(1)中斷方式?如下,定義延時(shí)時(shí)間time_delay,SysTick_Config()定義中斷時(shí)間段,在中斷中遞減time_delay,從而實(shí)現(xiàn)延時(shí)。
volatile unsigned long time_delay; //?延時(shí)時(shí)間,注意定義為全局變量 //延時(shí)n_ms void delay_ms(volatile unsigned long nms) {//SYSTICK分頻--1ms的系統(tǒng)時(shí)鐘中斷if (SysTick_Config(SystemFrequency/1000)){while (1);}time_delay=nms;//讀取定時(shí)時(shí)間while(time_delay);SysTick->CTRL=0x00; //關(guān)閉計(jì)數(shù)器SysTick->VAL =0X00; //清空計(jì)數(shù)器 } //延時(shí)nus void delay_us(volatile unsigned long nus) {//SYSTICK分頻--1us的系統(tǒng)時(shí)鐘中斷if (SysTick_Config(SystemFrequency/1000000)){while (1);}time_delay=nus;//讀取定時(shí)時(shí)間while(time_delay);SysTick->CTRL=0x00; //關(guān)閉計(jì)數(shù)器SysTick->VAL =0X00; //清空計(jì)數(shù)器 }//在中斷中將time_delay遞減。實(shí)現(xiàn)延時(shí)void SysTick_Handler(void) {if(time_delay)time_delay--; }(2)非中斷方式
主要仿照原子的《STM32不完全手冊(cè)》。SYSTICK?的時(shí)鐘固定為HCLK?時(shí)鐘的1/8,在這里我們選用內(nèi)部時(shí)鐘源72M,所以SYSTICK的時(shí)鐘為9M,即SYSTICK定時(shí)器以9M的頻率遞減。SysTick?主要包含CTRL、LOAD、VAL、CALIB?等4?個(gè)寄存器。
CTRL: SysTick控制和狀態(tài)寄存器
LOAD: SysTick重裝載值寄存器
VAL:? ? SysTick當(dāng)前值寄存器
CALIB:SysTick校準(zhǔn)值寄存器
對(duì)這幾個(gè)寄存器的操作被封裝到core_cm3.h中:
SysTick->CTRL
| 位段 | 名稱 | 類型 | 復(fù)位值 | 描述 |
| 16 | COUNTFLAG | R | 0 | 如果在上次讀本寄存器后systick已為0,則該位為1,若?讀該位自動(dòng)清零 |
| 2 | CLKSOURCE | RW | 0 | 0:外部時(shí)鐘源?1:內(nèi)部時(shí)鐘 |
| 1 | TICKINT | RW | 0 | 0:減到0無(wú)動(dòng)作;1:減到0產(chǎn)生systick異常請(qǐng)求 |
| 0 | ENABLE | RW | 0 | systick定時(shí)器使能位 |
?
SysTick-> LOAD
| 位段 | 名稱 | 類型 | 復(fù)位值 | 描述 |
| 23:0 | RELOAD | RW | 0 | 減到0時(shí)被重新裝載的值 |
SysTick-> VAL
| 位段 | 名稱 | 類型 | 復(fù)位值 | 描述 |
| 23:0 | CURRENT | RW | 0 | 讀取時(shí)返回當(dāng)前倒計(jì)數(shù)的值,寫(xiě)則清零,同時(shí)還會(huì)清除在systick控制及狀態(tài)寄存器中的COUNTFLAG標(biāo)志 |
SysTick-> CALIB?不常用,在這里我們也用不到,故不介紹了。
程序如下,相當(dāng)于查詢法。
//仿原子延時(shí),不進(jìn)入systic中斷 void delay_us(u32 nus) {u32 temp;SysTick->LOAD = 9*nus;SysTick->VAL=0X00;//清空計(jì)數(shù)器SysTick->CTRL=0X01;//使能,減到零是無(wú)動(dòng)作,采用外部時(shí)鐘源do{temp=SysTick->CTRL;//讀取當(dāng)前倒計(jì)數(shù)值}while((temp&0x01)&&(!(temp&(1<<16))));//等待時(shí)間到達(dá)SysTick->CTRL=0x00; //關(guān)閉計(jì)數(shù)器SysTick->VAL =0X00; //清空計(jì)數(shù)器 } void delay_ms(u16 nms) {u32 temp;SysTick->LOAD = 9000*nms;SysTick->VAL=0X00;//清空計(jì)數(shù)器SysTick->CTRL=0X01;//使能,減到零是無(wú)動(dòng)作,采用外部時(shí)鐘源do{temp=SysTick->CTRL;//讀取當(dāng)前倒計(jì)數(shù)值}while((temp&0x01)&&(!(temp&(1<<16))));//等待時(shí)間到達(dá)SysTick->CTRL=0x00; //關(guān)閉計(jì)數(shù)器SysTick->VAL =0X00; //清空計(jì)數(shù)器 }三種方式各有利弊,第一種方式容易理解,但不太精準(zhǔn)。第二種方式采用庫(kù)函數(shù),編寫(xiě)簡(jiǎn)單,由于中斷的存在,不利于在其他中斷中調(diào)用此延時(shí)函數(shù)。第三種方式直接操作寄存器,看起來(lái)比較繁瑣,其實(shí)也不難,同時(shí)克服了以上兩種方式的缺點(diǎn),個(gè)人感覺(jué)比較好用。
總結(jié)
以上是生活随笔為你收集整理的STM32延时函数的四种方法:普通延时(2种)、SysTick 定时器延时(2种)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言数组的一些运算*a,a+1,a+1
- 下一篇: 已解决:大家使用原子哥的延时函数dela