久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 13463|回復: 0
打印 上一主題 下一主題
收起左側

學習筆記-STM32 SysTick 滴答定時器原理及應用

[復制鏈接]
跳轉到指定樓層
樓主
ID:91350 發表于 2015-10-29 15:52 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
中秋國慶長假,各種事情,一眨眼,就過去了,變懶咯。。。
 
 第21集 SysTick滴答定時器

一、功能
SysTick定時器是一個簡單的定時器,CM3\CM4內核芯片都具備此定時器。SysTick定時器常用來做延時,采用實時系統時則用來做系統時鐘。
無論用作延時還是用作系統心跳時鐘,不需要太復雜的功能,SysTick即可勝任。
二、實現原理
SysTick定時器是一個24位的倒計數,當倒計數為0時,將從RELOAD寄存器中取值作為定時器的初始值,同時可以選擇在這個時候產生中斷(異常號:15)。
例如從RELOAD的值為999,那么當倒計數為0時,就會從復位為999繼續倒計數。
        只要不把它在SysTick控制及狀態寄存器中的使能位清楚,就永不停息,即使在睡眠模式下也能繼續工作。
三、SysTick寄存器(在 core_cm3.h 有定義,凡是 M3 內核的單片機都是一樣的)
#define SysTick             ((SysTick_Type *)       SysTick_BASE) 
#define SysTick_BASE        (SCS_BASE +  0x0010)
#define SCS_BASE            (0xE000E000) 
typedef struct
{
 __IO uint32_t CTRL; // 控制及狀態寄存器
 __IO uint32_t LOAD;   // 重裝載數值寄存器
 __IO uint32_t VAL; // 當前計數數值寄存器
 __I  uint32_t CALIB;  // 校準寄存器
} SysTick_Type;
SysTick->CTRL: (可通過 SysTick_CLKSourceConfig() 函數設置)
COUNTFLAG(16)R: 計數標志位
當SysTick數到0,則該位被硬件置 1,當讀取該位時,將被硬件清零
CLKSOURCE(2)R/W: 時鐘源設置
1 = 外部時鐘源(STCLK) (AHB總線時鐘的1/8(HCLK/8))
0 = 內核時鐘(FCLK)  (AHB總線時鐘的頻率(HCLK))
TICKINT(1)R/W: 中斷使能位
1 = SysTick 倒數到0時產生 SysTick 異常請求
0 = 數到 0 時無動作
ENABLE(0)R/W: SysTick 定時器使能位
(當中斷被使能后,需要關注 void SysTick_Handler(void) 函數)
SysTick_Type->LOAD: (SysTick_Config() 函數會設置該寄存器)
RELOAD(23:0)R/W: 重裝載數值寄存器
當SysTick數到0,將被重裝載的值
SysTick_Type->VAL: (SysTick_Config() 函數會設置該寄存器)
CURRENT(23:0)R/Wc: 當前計數數值寄存器
讀取時返回當前倒計數的值,寫它則使之清零,同時還會清除在 SysTick 控制及狀態寄存器中的 COUNTFLAG 標志。
四、庫函數分析
misc.c
----------------------------------------------------------------------------------
#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
((SOURCE) == SysTick_CLKSource_HCLK_Div8))
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
 /* Check the parameters */
 assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
 if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
 {
SysTick->CTRL |= SysTick_CLKSource_HCLK; // 設置 CLKSOURCE 為 1
 }
 else
 {
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;     // 設置 CLKSOURCE 為 0
 }
}

core_cm3.c
----------------------------------------------------------------------------------
#define SysTick_LOAD_RELOAD_Pos             0                                           
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)
typedef enum IRQn
{
//...
SysTick_IRQn                = -1, 
//...
}IRQn_Type;
#define __NVIC_PRIO_BITS          4
#define SysTick_CTRL_CLKSOURCE_Pos          2                                           
#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)          

#define SysTick_CTRL_TICKINT_Pos            1                                           
#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)            

#define SysTick_CTRL_ENABLE_Pos             0                                           
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos) 
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
 if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
 // 設置計數值為 ticks - 1 
 // 原因1:視頻說是執行這些代碼需要時間,所以減少一個節拍
 // 原因2:我認為是因為 SysTick 的倒計數到 0,例如設置 1000 ,那么范圍就應該是 999 ~ 0。
 SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;     
 // 設置中斷優先級
 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
 SysTick->VAL   = 0;                                
 // 設置時鐘源為外部時鐘源,同時開啟中斷、并使能 SysTick 定時器
 SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
  SysTick_CTRL_TICKINT_Msk   | 
  SysTick_CTRL_ENABLE_Msk;                   
 return (0);                                                 
}
五、延時應用
1、中斷方式
static __IO uint32_t TimingDelay;
void Delay(__IO uint32_t nTime)
  TimingDelay = nTime;
  while(TimingDelay != 0);
}
/* 中斷服務函數 */
void SysTick_Handler(void)
{
if (TimingDelay != 0x00) 
TimingDelay--;
}
}
int main(void)
{  
// ...
if (SysTick_Config(SystemCoreClock / 1000)) // 注意,這里systick時鐘為HCLK,中斷時間間隔1ms
{
while (1);
}
while(1)
{
Delay(200);//2ms
// ...
}
}
SysTick_Config(SystemCoreClock / 1000): (原代碼這里假設是采用時鐘源為 HCLK)
這里設置的是 72000000Hz / 1000 = 72000 ticks,也就是說 SysTick 從 (72000-1) 開始倒數。
每倒數完 72000 個節拍就觸發一次中斷。
一個節拍的時間為:72000000 / 72000 = 1000us == 1ms
SysTick_Config((SystemCoreClock / 8000000) * 1000 * 1): 
SysTick_Config() 會設置時鐘源為 HCLK/8 所以實際應用中不能按照上述代碼的參數。
SystemCoreClock / 8000000: 1us 的節拍數
1us的節拍數 * 1000: 則為 1ms 的節拍數
1ms 的節拍數 * 1: 設置 1ms 一個SysTick中斷,即從 ((SystemCoreClock / 8000000) * 1000 * 1) - 1 開始倒數。
2、輪詢方式
static u8  fac_us=0; //us延時倍乘數   
static u16 fac_ms=0; //ms延時倍乘數
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //選擇外部時鐘  HCLK/8
fac_us = SystemCoreClock/8000000;        // 為系統時鐘的1/8  1us = 72000000 / 8000000 =  9 個節拍
fac_ms = (u16)fac_us*1000; // 1ms 需要 9 * 1000 = 9000 個節拍
}
//延時 nus 微秒       
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //時間加載    
SysTick->VAL=0x00;       //清空計數器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;                //開始倒數
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達  
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;//關閉計數器
SysTick->VAL =0X00;                     //清空計數器  
}
//延時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;                       //清空計數器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;  //開始倒數 
do
{
temp=SysTick->CTRL;
                //等待時間到達,這里使用了一個小技巧,通過(temp&0x01)檢查 SysTick 的使能位,避免 Systick 定時器被關閉而導致無限循環 
}while((temp&0x01)&&!(temp&(1<<16)));  
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器
SysTick->VAL =0X00;                      //清空計數器      
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91在线视频播放 | 日韩一级免费 | 精品成人69xx.xyz | 玖玖玖在线观看 | 一级黄片一级毛片 | 在线观看av网站永久 | 国产精品亚洲精品久久 | 一区二区久久精品 | 91高清免费 | 国产日韩免费视频 | 在线观看免费av片 | 伊人精品久久久久77777 | 自拍偷拍中文字幕 | 日本久久网 | 美女黄18岁以下禁止观看 | 三级高清| 青青久久| 激情五月激情综合网 | 一本一道久久a久久精品综合蜜臀 | 亚洲福利 | 在线观看av网站 | 四虎影音| 欧美精品久久久久久久久久 | 国产精品精品视频一区二区三区 | 91不卡| 午夜影院在线观看视频 | 精品国产91亚洲一区二区三区www | 国产免费一区二区三区最新6 | 国产高清在线观看 | 免费观看一级毛片视频 | 一区二区成人 | 夜夜爽99久久国产综合精品女不卡 | 午夜在线 | 天天视频一区二区三区 | 国产乱码精品一区二区三区中文 | 丁香六月伊人 | 成人在线视频一区二区三区 | 成人在线看片 | 欧美高清视频在线观看 | 日韩精品一区二区三区四区 | 91porn国产成人福利 |