並非所有處理器都有庫函式,而只有在stm32才擁有庫函式以方便的呼叫庫函式去書寫**。真正操作處理器的本質還是暫存器,只有理解如何利用暫存器去執行程式,去學習其他處理器就會比較容易上手了
程式在位址中跳轉,而位址以暫存器的方式進行分布。所以今天先嘗試使用位址來操作暫存器寫入程式。具體的位址分布可根據文件《stm32f103xe資料手冊》及《stm32f10x參考手冊》進行查詢
預備知識
1、main()函式及編譯的預處理工作
編譯器在編譯時總是從main.c入口函式開始執行(初學暫未能遇到從其他.c開始編譯的型別),然後去讀取在預處理階段(include)的其他.**件,將其他.**件中的巨集、變數、函式等進行檢查觀測是否出現重複定義或者錯誤,最後將其內容掃瞄進.c檔案中執行。其他.**件中包含的函式一般寫入其對應的.c檔案中加以模組化呼叫
2、volatile關鍵字
volatile關鍵字告訴編譯器從暫存器位址取值而不是在快取器裡取值,使用volatile關鍵字宣告變數的值,可以保證對特殊位址的穩定訪問而不至於被改變
3、gpio
gpio標準:標準i/o口承受5v電壓;18mhz翻轉速度;每個gpio口分為7個埠;可對位設定及清零
埠:每個埠配置兩個配置暫存器、兩個資料暫存器、乙個置位/復位暫存器、乙個復位暫存器、乙個鎖定暫存器
埠位配置
4、gpio庫函式
5、gpio暫存器
有了以上的基礎,那麼先簡單的編寫乙個點亮gpioa埠1,2,3,4管腳的led燈程式吧——首先在main.c檔案中包含stm32f10x.h標頭檔案,這個檔案中包含了各種外設庫函式的定義,並且在.c檔案中寫下入口函式,具體如下
#include "stm32f10x.h"
int main(void)
注意一件有趣的事情是,在keil軟體中若最後一行** } 後面沒有多加一行,就會出現如下錯誤:
user\led_exti.c(46): warning: #1-d: last line of file ends without a newline這只是工程師設計軟體時候的設定,以後只要記得寫完**後多回車一行即可
——關於gpiox_crl的配置
通過上面的圖示可以看出,若需要配置gpioa的1234管腳,那麼需要使用到埠配置低暫存器gpiox_crl
需要解釋的是,每個埠都有16個管腳,其中0-7為低位,8-15為高位。
可以看出編號為0123的位屬於pa0,4567的位屬於pa1,依次類推可找出需要設定的pa1/2/3/4
因為按要求需要點亮gpioa,則暫存器名:gpioa_crl。表中mode和cnfx依次排列,mode用於選擇輸入/輸出速率,cnfx用於選擇輸入/輸出工作模式。
絕大多數情況下使用推挽式輸出,遇到i2c匯流排使用開漏輸出所以在cnf中選擇00即可,而在速率選擇中暫選擇50mhz,也即是11。故在pa1管腳,也即是4567位上寫入0011,依次可推斷出其他管腳的值都是換算成十六進製制的0x3。
在暫存器中,乙個位址的是由基位址+偏移位址組成,從《stm32f103xe資料手冊》(以下簡稱資料手冊)中可得知,porta的位址對映在0x40010800-0x40010bff中,這是基位址,另可知偏移位址為0x00。所以當前gpiox_crl的位址等於0x40010800h+0x00h,之後在此位址中寫入0011、0011的資料就可以實現管腳的初始化配置。
#define gpio_crl (*(volatile unsigned long *)0x40010800)
——關於gpiox_odr的配置
gpiox_odr是埠輸出資料暫存器,其引數如下
此暫存器16-31位是保留位。在0-15管腳中寫入1,則輸入高電平;寫入0,則輸入低電平。若設定的led是共陰極觸發,則寫入1輸出高電平點亮,寫入0輸出低電平熄滅。可知odr的偏移位址為0ch,則暫存器gpiox_odr的位址為0x40010800h+0x0ch。
其中gpiox_bsrr也可實現埠位設定,不過暫時不管,其brr為埠位清除。
gpiox_lckr為埠配置鎖定暫存器,可以讓埠為寫入操作期間不可改變埠值,也暫時不需要考慮。
#define gpioa_odr (*(unsigned long *)0x4001080c)
—— 關於rcc暫存器的配置
由系統的構架圖可以看出
具體rcc中包含了如下暫存器
該暫存器的埠位設定如下
若要開啟gpioa埠使能,則需要將位2寫入1
其中rcc_apb2enr的暫存器偏移位址是0x18。所以可知暫存器rcc_apb2enr的位址為0x40021000h+0x18h
#define rccapb2enr (*(volatile unsigned long *)0x40021018)
——當我們整理好資料後,最終編寫出的程式即為
#include "stm32f10x.h"
#define rccapb2enr (*(volatile unsigned long *)0x40021018)
#define gpio_crl (*(volatile unsigned long *)0x40010800)
#define gpioa_odr (*(unsigned long *)0x4001080c)
void delay(unsigned long n);
int main(void)
}void delay(unsigned long n)
}
STM32F10x系列 中斷
概念問題 中斷與事件有什麼聯絡與區別?stm32之中斷與事件 中斷與事件的區別 簡單概括下。中斷 cpu單執行緒情況下只能處理單一任務,在有零時任務需要處理時,可以暫時放下當前任務,優先處理零時任務,再回過來處理之前的任務。多個中斷可以進行巢狀,比如產生了多個零時任務,那麼就可以按照優先順序處理這多...
STM32F10x系列UART中斷異常除錯經歷
硬體環境 stm32f105rct6 軟體環境 freertosv8 問題描述 採用中斷方式接收資料,然後將收到的一幀資料放入訊息佇列,然後有專門的乙個任務用來從訊息佇列中取資料並處理。jlink除錯以及燒錄執行都是可以的,但是當隨著通訊頻率的增加以及執行時間的加長,系統會出現 宕機 即,不停的進入...
STM32F10X入門 流水燈
2019 3 16 2019 3 19 core cm32.c stdin.h中定義了字元型 stm32f10x.h stm32f10x conf.h中定義了引用的外設標頭檔案 庫檔案之間的依賴呼叫關係 pngstm32f10x.h檢視位址對映 比如define gpioa base apb2per...