STM32 GPIO 配置之ODR, BSRR, BRR 詳解
用stm32 的配置GPIO 來控制LED 顯示狀態,可用ODR,BSRR,BRR 直接來控制引腳輸出狀態.
ODR暫存器可讀可寫:既能控制管腳為高電平,也能控制管腳為低電平。
管腳對於位寫1 gpio 管腳為高電平,寫 0 為低電平
BSRR 只寫暫存器:[color=Red]既能控制管腳為高電平,也能控制管腳為低電平。
對暫存器高 16bit 寫1 對應管腳為低電平,對暫存器低16bit寫1對應管腳為高電平。寫 0 ,無動作
BRR 只寫暫存器:只能改變管腳狀態為低電平,對暫存器 管腳對於位寫 1 相應管腳會為低電平。寫 0 無動作。
剛開始或許你跟我一樣有以下疑惑:
1.既然ODR 能控制管腳高低電平為什麼還需要BSRR和SRR暫存器?
2.既然BSRR能實現BRR的全部功能,為什麼還需要SRR暫存器?
對於問題 1 ------ 意法半導體給的答案是---
“This way, there is no risk that an IRQ occurs between the read and the modify access.”
什麼意思呢?就就是你用BSRR和BRR去改變管腳狀態的時候,沒有被中斷打斷的風險。也就不需要關閉中斷。
用ODR操作GPIO的虛擬碼如下:
disable_irq()
save_gpio_pin_sate = read_gpio_pin_state();
save_gpio_pin_sate = xxxx;
chang_gpio_pin_state(save_gpio_pin_sate);
enable_irq();
關閉中斷明顯會延遲或丟失一事件的捕獲,所以控制GPIO的狀態最好還是用SBRR和BRR
對於問題 2 ------- 個人經驗判斷意法半導體僅僅是為了程式設計師操作方便估計做麼做的。
因為BSRR的 低 16bsts 恰好是set操作,而高16bit是 reset 操作 而BRR 低 16bits 是reset 操作。
簡單地說GPIOx_BSRR的高16位稱作清除暫存器,而GPIOx_BSRR的低16位稱作設定暫存器。
另一個暫存器GPIOx_BRR只有低16位有效,與GPIOx_BSRR的高16位具有相同功能。
舉個例子說明如何使用這兩個暫存器和所體現的優勢。
例如GPIOE的16個IO都被設定成輸出,而每次操作僅需要
改變低8位的資料而保持高8位不變,假設新的8位資料在變數Newdata中,
這個要求可以通過操作這兩個暫存器實現,STM32的韌體庫中有兩個函式
GPIO_SetBits()和GPIO_ResetBits()使用了這兩個暫存器操作埠。
上述要求可以這樣實現:
GPIO_SetBits(GPIOE, Newdata & 0xff);
GPIO_ResetBits(GPIOE, (~Newdata & 0xff));
也可以直接操作這兩個暫存器:
GPIOE->BSRR = Newdata & 0xff;
GPIOE->BRR = ~Newdata & 0xff;
當然還可以一次完成對8位的操作:
GPIOE->BSRR = (Newdata & 0xff) | ( (~Newdata & 0xff)<<16 );
當然還可以一次完成對16位的操作:
GPIOE->BSRR = (Newdata & 0xffff) | ( (~Newdata )<<16 );
從最後這個操作可以看出使用BSRR暫存器,可以實現8個埠位的同時修改操作。
有人問是否BSRR的高16位是多餘的,請看下面這個例子:
假如你想在一個操作中對GPIOE的位7置'1',位6置'0',則使用BSRR非常方便:
GPIOE->BSRR = 0x400080;
GPIOE->BRR = 0x40;
BSRR還有一個特點,就是Set比Reset的級別高,
就是說同一個bit又做Set又做Reset,最後結果是Set
要同步變化只要簡單的 GPIOx->BSRR = 0xFFFF0000 | PATTEN;
即可,不用考慮哪些需要置1,哪些需要清零
從最後這個操作可以看出使用BSRR暫存器,可以實現8個埠位的同時修改操作。