STM32埠IO方向設定問題的IO方向設定問題

果果小師弟發表於2021-01-01

例程:STM32F103系列 I2C軟體模擬實驗(mini板)

問題:下面兩行關於“IO方向”的程式碼不太明白。

//IO 方向設定
#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

進過研讀開發手冊大概解決了這個問題。

STM32 的 IO 口可以由軟體配置成如下 8 種模式:
1、輸入浮空
2、輸入上拉
3、輸入下拉
4、模擬輸入
5、開漏輸出
6、推輓輸出
7、推輓式複用功能
8、開漏複用功能

每個 IO 口可以自由程式設計,但 IO 口暫存器必須要按 32 位字被訪問。STM32 的很多 IO 口都是 5V 相容的,這些 IO 口在與 5V 電平的外設連線的時候很有優勢,具體哪些 IO 口是 5V 相容的,可以從該晶片的資料手冊管腳描述章節查到(I/O Level 標 FT 的就是 5V 電平相容的)。STM32 的每個 IO 埠都有 7 個暫存器來控制。他們分別是:配置模式的 2 個 32 位的埠配置暫存器 CRL 和 CRH;2 個 32 位的資料暫存器 IDR 和 ODR;1 個 32 位的置位/復位暫存器BSRR;一個 16 位的復位暫存器 BRR;1 個 32 位的鎖存暫存器 LCKR;我們常用的 IO 埠暫存器只有 4 個:CRL、CRH、IDR、ODR。CRL 和 CRH 控制著每個 IO 口的模式及輸出速率。
STM32 的 IO 口位配置表如表 6.1.1 所示:

STM32 輸出模式配置如表 :

接下來我們看看埠低配置暫存器 CRL 的描述

STM32 的 CRL 控制著每組 IO 埠(A~G)的低 8 位的模式。每個 IO 埠的位佔用 CRL 的 4 個位,高兩位為 CNF,低兩位為 MODE。

換句話說我們要控制PA0,就只要這樣寫:

GPIOA->CRL&=0XFFFFFFF0

把PA0設定為輸入就要這樣寫:

GPIOC->CRL|=8<<0;

合起來控制PA0為輸入就是這樣寫:

GPIOC->CRL&=0XFFFFFFF0;GPIOC->CRL|=8<<0;

PA0為輸出

GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;

PA1為輸出

GPIOA->CRL&=0XFFFFFF0F;GPIOA->CRL|=8<<4;

PA2為輸出

GPIOA->CRL&=0XFFFFF0FF;GPIOA->CRL|=8<<8;

PA3為輸出

GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=8<<12;

PA4為輸出

GPIOA->CRL&=0XFFF0FFFF;GPIOA->CRL|=8<<16;

PA5為輸出

GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=8<<20;

PA6為輸出

GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=8<<24;

PA7為輸出

GPIOA->CRL&=0X0FFFFFFF;GPIOA->CRL|=8<<28;

同理設定為輸入就是

PA0為輸入

GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;

PA1為輸入

GPIOA->CRL&=0XFFFFFF0F;GPIOA->CRL|=3<<4;

PA2為輸入

GPIOA->CRL&=0XFFFFF0FF;GPIOA->CRL|=3<<8;

PA3為輸入

GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=3<<12;

PA4為輸入

GPIOA->CRL&=0XFFF0FFFF;GPIOA->CRL|=3<<16;

PA5為輸入

GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=3<<20;

PA6為輸入

GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=3<<24;

PA7為輸入

GPIOA->CRL&=0X0FFFFFFF;GPIOA->CRL|=3<<28;

PA8為輸出

GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=8<<0;

PA9為輸出

GPIOA->CRH&=0XFFFFFF0F;GPIOA->CRH|=8<<4;

PA10為輸出

GPIOA->CRH&=0XFFFFF0FF;GPIOA->CRH|=8<<8;

PA11為輸出

GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<12;

PA12為輸出

GPIOA->CRH&=0XFFF0FFFF;GPIOA->CRH|=8<<16;

PA13為輸出

GPIOA->CRH&=0XFF0FFFFF;GPIOA->CRH|=8<<20;

PA14為輸出

GPIOA->CRH&=0XF0FFFFFF;GPIOA->CRH|=8<<24;

PA15為輸出

GPIOA->CRH&=0X0FFFFFFF;GPIOA->CRH|=8<<28;

同理設定為輸入就是

PA8為輸入

GPIOA->CRH&=0XFFFFFF0F;GPIOA->CRH|=3<<0;

PA9為輸入

GPIOA->CRH&=0XFFFFFF0F;GPIOA->CRH|=3<<4;

PA10為輸入

GPIOA->CRH&=0XFFFFF0FF;GPIOA->CRH|=3<<8;

PA11為輸入

GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<12;

PA12為輸入

GPIOA->CRH&=0XFFF0FFFF;GPIOA->CRH|=3<<16;

PA13為輸入

GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRH|=3<<20;

PA14為輸入

GPIOA->CRH&=0XF0FFFFFF;GPIOA->CRH|=3<<24;

PA15為輸入

GPIOA->CRH&=0X0FFFFFFF;GPIOA->CRH|=3<<28;

GPIOC->CRL&=0XFFFFFFF0;
GPIOx->CRL,這句話表示要操作GPIOx的低8位,就是Px0 ~ Px7,(CRL表示操作高8位,就是Px8~Px15);
所以GPIOC->CRL,這句話表示要操作GPIOC的第0位,就是PC0

後面的0XFFFFFFF0,表示操作PC0;0XFFFFFF0F,表示操作PC1;0XFFFFF0FF,表示操作PC2;0XFFFF0FFF,表示操作PC3;0XFFF0FFFF,表示操作PC4;0XFF0FFFFF,表示操作PC5;0XF0FFFFFF,表示操作PC3;0X0FFFFFFF,表示操作PC7;合起來的意思就是:利用“與”運算,把這個位清0,同時不影響其他的位的設定。

GPIOC->CRL|=8<<0;
意思就是將1000左移0位(不移位),然後再與GPIOC->CRL進行“或”運算。再根據原子的暫存器開發手冊可以知道CNF0[10]、MODEO[00],對應的就是設定為上拉/輸入模式。

相關文章