將上一節搭建的LED工程複製一份,命名爲「2.systick」。這一節主要講如何使用系統的SysTick節拍定時器來進行精準延時程序。函數
SysTick是CM3/CM4內核芯片提供的一個定時器,咱們的板子使用的SAM4N芯片是CM4內核的,天然少不了這個定時器。ui
首先在Drivers文件夾中創建delay.c和delay.h文件並添加到工程中,在delay.c中寫入以下代碼:it
#include "delay.h"配置
uint32_t timeout=0;循環
/**************************************************************************下載
* 函數名:SysTick_Handler()定時器
* 參數 :void程序
* 返回值:voidim
* 描述 :系統節拍中斷服務函數命名
**************************************************************************/
void SysTick_Handler(void)
{
/*定時計數自減1*/
timeout--;
}
/**************************************************************************
* 函數名:systick_hw_init()
* 參數 :void
* 返回值:void
* 描述 :系統節拍初始化函數
**************************************************************************/
void systick_hw_init(void)
{
//選擇系統節拍定時器的時鐘源爲系統內核時鐘
SysTick->CTRL|=0x01<<2;
//設置重裝值,配置系統節拍定時器爲1ms中斷一次
/*1ms <-->SystemCoreClock/1000
* 100us <-->SystemCoreClock/10000
* 10us <-->SystemCoreClock/100000
*/
SysTick->LOAD = SystemCoreClock/1000 - 1;
//使能系統節拍時鐘中斷
SysTick->CTRL|=0x02;
//使能系統節拍時鐘
SysTick->CTRL|=0x01;
}
/**************************************************************************
* 函數名:delay_ms()
* 參數 :uint32_t n 延時的毫秒數
* 返回值:void
* 描述 :使用系統節拍進行精準延時函數
**************************************************************************/
void delay_ms(uint32_t n)
{
timeout = n; //設置系統節拍延時
while(timeout!=0); //等待延時時間到
}
/**************************************************************************
* 函數名:delay()
* 參數 :uint32_t n 延時的循環個數
* 返回值:void
* 描述 :簡單的循環延時函數
**************************************************************************/
void delay(uint32_t n)
{
while(n--);
}
雖然註釋已經寫得很清楚了,但仍是講一下吧,主要是systick_hw_init函數,這是初始化配置SysTick的代碼,第一步先選擇SysTick的時鐘源,這裏我選擇使用系統內核時鐘做爲時鐘源;第二步是設置SysTick的Load值,這裏設置爲ystemCoreClock/1000 - 1;,這樣SysTick就會每毫秒中斷一次,最後是開啓中斷和使能SysTick。
延時主要是經過設定timeout的值,而後等待timeout爲0,在Systick中斷中,timeout會自減1,直到爲0。這樣就實現了ms級的精準延時函數delay_ms()。
在delay.h中主要寫寫函數聲明,以下:
#ifndef __DELAY_H
#define __DELAY_H
#include "sam4n16c.h"
/**************************************************************************
* 函數名:SysTick_Handler()
* 參數 :void
* 返回值:void
* 描述 :系統節拍中斷服務函數
**************************************************************************/
void SysTick_Handler(void);
/**************************************************************************
* 函數名:systick_hw_init()
* 參數 :void
* 返回值:void
* 描述 :系統節拍初始化函數
**************************************************************************/
void systick_hw_init(void);
/*************************************************************************
* 函數名:delay_ms()
* 參數 :uint32_t n 延時的毫秒數
* 返回值:void
* 描述 :使用系統節拍進行精準延時函數
**************************************************************************/
void delay_ms(uint32_t n);
/**************************************************************************
* 函數名:delay()
* 參數 :uint32_t n 延時的循環個數
* 返回值:void
* 描述 :簡單的循環延時函數
**************************************************************************/
void delay(uint32_t n);
#endif
接下來把main.c中的delay改掉,以下:
int main(void)
{
systick_hw_init();
led_hw_init();
while(1){
led_hw_on();
delay_ms(500);
led_hw_off();
delay_ms(500);
}
}
好了,下載程序到板子,這下是否是延時很準?