https://www.cnblogs.com/bluettt/p/11768239.html
舉個例子來說,如果我們想改變ARR寄存器中的值,但是當前的定時還沒有結束,在這時如果未設置影子寄存器,那么設定的值會立即生效。而如果設置了影子寄存器,那么新的值會在當前計數周期結束之后生效。
在STM32基本定時器的PSC預分頻寄存器和ARR自動裝載寄存器都有影子寄存器。
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
是下個周期立即生效
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
是下下個周期生效
馬下——大神的知識
原文鏈接:https://blog.csdn.net/chenyuanlidejiyi/article/details/108715097
0 公式
系統時鍾CLK 和 分頻數Prescaler 和 時鍾計數cnt 和定時器定時的時間
定時器時鍾=系統時鍾/分頻Prescaler
1/定時器時鍾 表示的是跳動1個tick需要的時間
那跳動cnt個tick需要多長時間呢?cnt*(1/定時器時鍾)
1
在日常使用定時器的時候我們往往會通過改變重裝載值來實現不同時間的一個定時,就像我在一個項目功能中,使用的定時器7,剛開始我設置的是
//該CPU時鍾是48M,分頻系數為48,則48M/48=1M--->對應的是1us
//整個產生的中斷時間是=CPU時鍾/(分頻系數+1)*(重裝載值+1),這里對應的就是1us*5000=5000us=5ms
htim7.Instance = TIM7;
htim7.Init.Prescaler = 4800-1; //分頻系數 0.1ms,跳動一下需要0.1ms。
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;//向上計數器
htim7.Init.Period = 52-1; //自動裝載值,跳動52下需要5.2ms。
htim7.Instance->CNT=0;
htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//時鍾分頻因子
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_Base_Init(&htim7);
HAL_TIM_Base_Start_IT(&htim7);
這樣的話定時器7就是每5.2ms進入一次中斷,同時我代碼中還有一個外部中斷,我在外部中斷中改變定時器7的ARR值,
__HAL_TIM_DISABLE(&htim7);
htim7.Instance->CNT=0;
htim7.Instance->ARR=105-1;//跳動105下需要10.5ms。
__HAL_TIM_ENABLE(&htim7);
想讓他后面10.5ms進入一次中斷,(注意重新設置重裝載值的時候最好先關閉定時器,設置參數,再開啟),按照之前對重裝載值的理解,只要修改ARR寄存器,就會修改他的周期時間,那么產生更新中斷的時間也就變了,但是我通過邏輯分析儀測出的現象是,代碼執行完我外部中斷中修改ARR的命令,並沒有在10.5ms后進入定時器7的中斷服務函數,而是先在5.2ms后進入中斷服務函數,再在10.5ms后進入定時器7的中斷服務函數。然后通過查找資料,定時器的寄存器有一個這樣的功能:
這里有一個ARR的緩沖器,關於這個緩沖器我是這樣理解的,
當開啟緩沖器的時候,修改ARR的值,他會先將這個值放到緩沖器里,那么這樣的話這個值作用的就是下下一個周期;當關閉緩沖器,修改ARR的值,直接作用於下個周期。即:
TIM_CR1_ARPE=1,有緩沖區,對ARR修改影響的是下下一個周期的定時長度;
TIM_CR1_ARPE=0,無緩沖區,對ARR修改影響的是下一個周期的定時長度;
然后在發現在初始化的時候
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
這個參數定義的就是開啟緩沖器的開關
#define TIM_AUTORELOAD_PRELOAD_DISABLE (0x0000U) /*!< TIMx_ARR register is not buffered */
#define TIM_AUTORELOAD_PRELOAD_ENABLE (TIM_CR1_ARPE) /*!< TIMx_ARR register is buffered */
之后我將這個參數改為TIM_AUTORELOAD_PRELOAD_DISABLE 時,通過驗證,確實是這個問題。