在後續我們對講解多個感測器,這幾個感測器對時序的要求都比較高,比如溫濕度感測器dh11,檢視晶元手冊時序,至少就需要微秒級的延時函式。
延時函式的方式一般有兩種:
使用for迴圈的方式,可能會因為硬體的差異,導致延時函式不准,因此這裡我們使用定時器的方式。
開啟之前的timers.c檔案,修改timer_init函式的配置。
pclk仍然等於50000000,將prescaler value改為4,divider value設定為2,
這樣,每減1, 對應0.2us;每減5, 對應1us;從50000減到0,對應10ms。
修改對應的暫存器:
tcfg0 = 4; /* prescaler 0 = 4, 用於timer0,1 */tcfg1 &= ~0xf; /* mux0 : 1/2 *//* 設定timer0的初值 */tcntb0 = 50000; /* 10ms中斷一次 */
我們先寫乙個us延時的函式,然後ms延時就呼叫us即可。
因此,us延時函式裡,盡量少呼叫函式。
假如現在要延時nus,我們先將n*5,得到nus對應的「計數時鐘數」。
然後如果傳入「計數時鐘週期」如果大於0,則一直計算過去了多少個「計數時鐘數」,與傳入的「計數時鐘數」相減,直到為零,退出迴圈,也就實現了延時nus。
怎樣計算過去了多少個「計算週期」呢?
自然是當前的值,減去一開始進入函式的值。
但還有一種情況是定時器裡的計數記到0時,會自動變成5000,計數計數,這時候,計算方式就變成了pre+(5000-cur):
/* 盡量少呼叫函式 */void udelay(int n)}
然後是ms延時函式:
void mdelay(int m)
我們可以寫乙個測試函式,簡單的測試下是否可用,測試函式隔1分鐘進行列印一下。
如果us不准的話,放大至s,會有比較大的偏差,這樣可以進行粗略的檢測,精確檢測可以使用示波器等工具。
void hrtimer_test(void)}
前面延時裡的計算還是比較耗費時間的,因此,我們盡量提高cpu的執行時鐘,並且 將盡可能的啟動icache、dcache和mmu。
此外,如果延時過程中,發生了中斷,如果中斷比較耗時的話,就會導致延時可能出現不準確,所以,我們可以延時之前關中斷, 延時之後開中斷;
課後作業:
「新品首發」stm32mp157開發板火爆預售!首批僅300套
STM32 BSRR暫存器和BRR暫存器
置gpioa bsrr低16位的某位為 1 則對應的i o埠管腳置 1 置gpioa bsrr低16位的某位為 0 則對應的i o埠管腳保持不變。置gpioa bsrr高16位的某位為 1 則對應的i o埠管腳置 0 置gpioa bsrr高16位的某位為 0 則對應的i o埠管腳保持不變。置gpi...
STM32預裝載暫存器與影子暫存器
捕獲 比較模組由乙個預裝載暫存器和乙個影子暫存器組成。讀寫過程僅操作預裝載暫存器。在捕獲模式下,捕獲發生在影子暫存器上,然後再複製到預裝載暫存器中。在比較模式下,預裝載暫存器的內容被複製到影子暫存器中,然後影子暫存器的內容和計數器進行比較。根據 timx cr1 暫存器中 apre 位的設定 apr...
STM32蜂鳴器 暫存器
這次實驗犯了個笑話,竟然在巨集定義後面加分號.就像這樣 define 大家千萬不要學我,結果報錯expected expression,還苦惱半天,想為啥操作不了暫存器了?我真愚蠢!剛開始我也不會寫這些東西,其實摸清套路就好,rcc時鐘使能 gpio初始化 相關暫存器初始化 延時函式 串列埠等初始化...