先上完整滴答定時器部分代碼!!!
EXTI.c部分
#include "ext.h"
#define SYSTICK_E 9
/**
* @brief 用於SysTick初始化
* @param None
* @retval None
*/
void TICK_Init(void)
{
//1.設置SysTick的時鐘頻率
SysTick->CTRL&=~(1<<2); //選擇當前時鐘爲AHB/8,在72MHz情況下,SysTick就是9MHz
}
/**
* @brief ms級別延遲,最大值在達到1864的情況下,會出現時間不精確
* @param u32 count:ms級別延遲時間數
* @retval None
*/
void sleep_ms(u32 count)
{
if(count<=0)return;
u8 n=count/1000;
u16 last=count%1000;
if(n>=1){
//循環n次1000ms
u8 i=0;
for(i=0;i<n;i++){
sleep_us(1000*1000);
}
}
if(last!=0){
//在等待最後剩餘的時間
sleep_us(last*1000);
}
}
/**
* @brief us級別延遲
* @param u32 count:us級別延遲時間數
* @retval None
*/
void sleep_us(u32 count)
{
if(count<=0)return;
//1.先設置LOAD寄存器
SysTick->LOAD=SYSTICK_E*count;
//2.清零
SysTick->VAL=0;
//3.使能(開啓SysTick)
SysTick->CTRL=0x01;
while(!(SysTick->CTRL&0x10000));
//關閉SysTick
SysTick->CTRL&=~(1<<0);
}
EXTI.h部分
void TICK_Init(void); //用於SysTick初始化
void sleep_ms(u32 count); //ms級別延遲
void sleep_us(u32 count); //us級別延遲
好!按照老樣子,接下來開始詳細講解每行代碼的用處,以及爲什麼這樣寫!
滴答定時器初始化部分
//1.設置SysTick的時鐘頻率
SysTick->CTRL&=~(1<<2); //選擇當前時鐘爲AHB/8,在72MHz情況下,SysTick就是9MHz
//
//由上圖可以得知滴答定時器爲24位,自動裝載值也是24位,並且計數器計數的方式是從當前給定的load裝載值一直減少到0。
//有上一篇文章我們得知,HCLK爲72MHz,那麼systick就是9MHz。
//
//
//由上圖我們可以得知,設置CLKSOURCE爲0,則代表當前時鐘頻率是9MHz。
//所以左移兩位,並且取反。
滴答定時器延時us部分
if(count<=0)return;
//這裏就是爲了防止輸入該函數的參數是0,那麼如果不加這個操作的話,這個函數毫無意義,最終返回。
//1.先設置LOAD寄存器
SysTick->LOAD=SYSTICK_E*count;
//在上main我們已經得知,該時鐘頻率爲9MHz,那麼就相當於爲1/9us,也就是每滴答一次就是1/9us,但是我們想要延時1us,是以1us爲基準單位的,那麼這裏就需要我們人爲擴大9倍。
//2.清零
SysTick->VAL=0;
//這裏就是在賦值的時候先清零,以防止之前寄存器裏面有值。
//3.使能(開啓SysTick)
SysTick->CTRL=0x01;
while(!(SysTick->CTRL&0x10000));
//關閉SysTick
SysTick->CTRL&=~(1<<0);
////當第0位爲0時,不使能滴答定時器,反之當第0位爲1時,則使能滴答定時器。並且再次清零。
////同時由上圖得知,當裝載值減少到0時,則該位返回1。
//那麼我們就需要通過判斷該位是否爲1來得知延時是否完成。
//由於COUNTFLAG爲第17位。
//
//最後關閉使能,取反即可。
滴答定時器延時ms部分
if(count<=0)return;
//同樣的道理,不再贅述。
u8 n=count/1000;
u16 last=count%1000;
if(n>=1){
//循環n次1000ms
u8 i=0;
for(i=0;i<n;i++){
sleep_us(1000*1000);
}
}
//正常來說該裝載值寄存器是24位的,那麼通過計算器可知爲16777216。這時是以秒爲單位的那麼折算成ms,則需要除以1000。然後再除以9,得到如下所示。
//
//相當於最終算出來ms函數的輸入參數最大是1864,不能超過1864。那麼我們如果輸入的參數大於1864呢?那我們該怎麼辦?
//所以我們爲了解決這個問題,這時需要知道此時輸入的參數裏面到底有多少個1000,也就是有多少個1s。
//
//如上圖所示,我們通過除運算,得知有多少個1000ms,通過%運算,得知還剩多少ms。
//如果n>=1代表肯定比1000多,那麼就需要先循環延時n次1000ms。
if(last!=0){
//在等待最後剩餘的時間
sleep_us(last*1000);
}
//如果最終執行完n次1000ms之後還有剩餘一部分時間(ms)(小於1000ms),那麼就在執行last ms即可。這就完美解決問題了!!!滴答定時器如此簡單!!!
結束語
如果覺得這篇文章還不錯的話,記得點贊 ,支持下!!!
以後我會繼續推出關於嵌入式(stm32)的協議方面的講解,下一講會推出DMA部分的文章!敬請期待!!!
**我先休息去了~~╭(╯^╰)╮