ARR是啥
自動重載寄存器是預裝載的。對自動重載寄存器執行寫入或讀取操作時會訪問預裝載寄存器。預裝載寄存器的內容既可以直接傳送到影子寄存器,也可以在每次發生更新事件
(UEV) 時傳送到影子寄存器,這取決于 TIMx_CR1 寄存器中的自動重載預裝載使能位 (ARPE)。當>計數器達到上溢值(或者在遞減計數時達到下溢值)并且 TIMx_CR1 寄存器中的 UDIS 位為 0時,將發送更新事件。該更新事件也可由軟件產生。
計數器時序圖,ARPE=0 時更新事件,未預裝載
立刻改變ARR重裝載值,計數器從當前值計數到36,而不是原來的FF
計數器時序圖,ARPE=1 時更新事件(TIMx_ARR 已預裝載)
原來ARR的值F5,現在寫入36,但是計數器依舊按照原來的計數到F5,溢出后,然后再重新從0開始計數,直到計數到新的ARR-36。
如果沒有預裝載,此時ARR的值直接更新,而此時計數器已經是F1,超過了新寫入的值36,計數器不是直接從零計數,而是一直加到溢出,再從0重新開始計數到ARR,這就造成了一些問題,計數時間不是你想要的,
ARPE,自動重裝載使能,默認0,無預裝載
通過下邊程序進行更改ARPE
/*** @brief Enables or disables TIMx peripheral Preload register on ARR.* @param TIMx: where x can be 1 to 14 to select the TIM peripheral.* @param NewState: new state of the TIMx peripheral Preload register* This parameter can be: ENABLE or DISABLE.* @retval None*/
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Set the ARR Preload Bit */TIMx->CR1 |= TIM_CR1_ARPE;}else{/* Reset the ARR Preload Bit */TIMx->CR1 &= (uint16_t)~TIM_CR1_ARPE;}
}
援引網友的一段話
https://blog.csdn.net/qq_46015011/article/details/107108739
預加載寄存器是自動重裝載寄存器的“影子”,也就是預加載寄存器是自動重裝載寄存器的緩沖器。但是自動重裝載寄存器不是用戶用程序可以直接進行操作的,用戶需要借助于預加載寄存器(緩沖區)才能訪問它。
其目的是為了保證自動重裝載寄存器在合適的時候被修改,不允許其隨便被修改,否則可能導致在切換的時候發生事與愿違的結果。
簡單來說:沒有預加載寄存器,這次修改的值,立馬會被執行。而有了預加載寄存器,這次修改值會等到這次執行完后,才去執行。
總結:
因為定時器的周期都比較短,我們可以通過預加載寄存器配合自動重裝載寄存器,來更好的操作定時器,以達到我們期望的效果。
下面的這個解釋挺好的:
👀使能預裝載的意義在于可以多個通道同時輸出時,時序能準確地同步。網上的一段有意義的解釋是:設計preload register和shadow register的好處是,所有真正需要起作用的寄存器(shadow register)可以在同一個時間(發生更新事件時)被更新為所對應的preload register的內容,這樣可以保證多個通道的操作能夠準確地同步。如果沒有shadow register,或者preload register和shadow register是直通的,即軟件更新preload register時,同時更新了shadow register,因為軟件不可能在一個相同的時刻同時更新多個寄存器,結果造成多個通道的時序不能同步,如果再加上其它因素(例如中斷),多個通道的時序關系有可能是不可預知的。可見如果只是單通道輸出,多通道輸出時沒時序精準的同步更新要求,不使能也可以的。
參考文獻是這樣說的:自動重載寄存器是預裝載的。對自動重載寄存器執行寫入或讀取操作時會訪問預裝載寄存器。預裝載寄存器的內容既可以直接傳送到影子寄存器,也可以在每次發生更新事件 (UEV) 時傳送到影子寄存器,這取決于 TIMx_CR1 寄存器中的自動重載預裝載使能位 (ARPE)。這里對自動重載寄存器執行寫入或讀取操作時會訪問預裝載寄存器我很疑惑,TIMx_ARR應該不是它們對應的預裝載寄存器,可能是有三個寄存器的,自動重裝載寄存器、預裝載寄存器、和真正起作用的影子寄存器。希望得到解答。
我李某人遇到的問題
最近因為這個重裝載問題困擾了我好久,我此時只想說:
下邊就是我做的一些測試,來查找這個問題,因為這個跳變不是一直出現的,一直測測測,yue了
//#define debug_config_init_c//改變引腳的初始化,上下拉等
//#define debug_config_init_h//引腳輸入輸出,OD開漏無需配置引腳的輸入輸出,推挽要配置
//#define debug_stm32f4xx_c//增加d2讀取時間,未曾跳變,
//#define debug_stm32f4xx_it_c_two//將d1,2讀取順序對調,D2采用平均值
#define debug_stm32f4xx_it_c_500ms//統一定時5ms,大于轉換時間1。17ms
#define debug_tiaobian//捕捉跳變
//#define debug_Priority//增加氣壓計優先級,還會跳變,不是中斷引起的
//#define debug_interruppt//只保留氣壓計中斷,未曾跳變,驗證是因為被其他中斷打斷引起的跳變
#define debug_NACK//讀取數據結束,按照手冊增加這個非應答信號
//#define debug_filter_D2_1//這幾個值均不為零,才更新高度,跳變均是0
#define debug_data_type//char接收了一個超范圍的值A0-AE,char最大127,
//#define debug_IIC_WaitAck
#define debug_IIC_communicate//更改IIC時序,降低讀取數據的頻率,增大延時
初心是定時器中斷里不斷改變ARR的值,達到一個不同定時時間case的切換,執行不同的命令,可是事與愿違,不到2.5ms,直接到了下一個case,因為ARPE默認是0,假如在到達250這個case之前,計數器已經到了248,你直接給了ARR250,這不直接定時時間直接到下一個case嘍,不知哪位師兄寫的程序害我,哈哈,本來八百多萬的數據直接變成了0,這不導致無人機上跳下竄的,雖然控制有濾波,萬一跳變過多,沒有濾掉呢,一架架飛機炸裂,那我直接跑路吧,也別畢業了。。。
0x52,0xEE,這兩個命令之間本來按照程序有一個2.5ms的延時,可是這里沒有起作用,導致我這邊數據讀取到0
增加這個延時的作用就是給氣壓計一個轉換時間,數據轉換完成,我再去讀取,這倒好,還沒轉換完我就去讀取,可不就是00000,服了