整理: MilerShao 某日,有個工程師電話跟我交流,他在使用STM32F042芯片開發(fā)產(chǎn)品,用到其中的硬件I2C。利用ST官方提供的標(biāo)準(zhǔn)固件庫開發(fā)應(yīng)用軟件。他說發(fā)現(xiàn)I2C功能基本不受控,尤其令他奇怪的是,I2C即使關(guān)閉了,卻發(fā)現(xiàn)I2C腳上還有脈沖出現(xiàn)。 他問我是否STM32F0芯片在I2C這里做了什么特別的調(diào)整,因?yàn)樗坝眠^STM32F1系列的芯片。我心想,再怎么調(diào)整也不應(yīng)該調(diào)整出這個效果啊,我首先懷疑他代碼是否哪里有問題,尤其I2C及相關(guān)GPIO的配置。建議其做與I2C有關(guān)的初始化配置代碼的檢查確認(rèn)。 后來,他通過QQ留言反饋給我,說找到原因了。原因就是將有關(guān)PA9,PA10的復(fù)用功能配置語句做了調(diào)整就OK。顯然,這里PA9,PA10是被復(fù)用為I2C通信腳。 
調(diào)整前的代碼 GPIO_PinAFConfig(GPIOA,GPIO_Pin_9,GPIO_AF_4); GPIO_PinAFConfig(GPIOA,GPIO_Pin_10,GPIO_AF_4);
調(diào)整后的代碼 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_4); GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_4);
不難看出,該工程師調(diào)整的就是上面紅色參數(shù)部分。一個是GPIO_Pin_N,一個是GPIO_PinSourceN,其實(shí)這2個參數(shù)是不一樣的。 GPIO_Pin_n可以理解為某端口腳在整個端口的位置。比方某GPIO口的第6管腳位置編碼GPIO_Pin_6 被定義為 ((uint16_t)0x0040) ,在對相應(yīng)GPIO管腳做基本屬性配置時會用到,如配置輸入輸出模式、模擬輸入模式的選擇等。有興趣的話,可以點(diǎn)擊GPIO_Init( )進(jìn)去看看。
而GPIO_PinSourceN一般是在對某GPIO口相應(yīng)pin腳的復(fù)用功能進(jìn)行選擇配置才會用到。它是根據(jù)端口各腳位的位置按順序從0開始依次遞增編號,可以理解為該管腳在該端口的序號。比方某GPIO口的第6號復(fù)用功能腳的序號GPIO_PinSource6 被定義為 ((uint8_t)0x06) 。有興趣的話,也可以打開GPIO_PinAFConfig( )函數(shù)看看。顯然,GPIO_PinSource6跟上面的GPIO_Pin_6的值相差甚遠(yuǎn)。
下面是ST官方庫代碼中有關(guān)GPIO_Pin_N的定義:
#define GPIO_Pin_0 ((uint16_t)0x0001) #define GPIO_Pin_1 ((uint16_t)0x0002) #define GPIO_Pin_2 ((uint16_t)0x0004) #define GPIO_Pin_3 ((uint16_t)0x0008) #define GPIO_Pin_4 ((uint16_t)0x0010) #define GPIO_Pin_5 ((uint16_t)0x0020) #define GPIO_Pin_6 ((uint16_t)0x0040) #define GPIO_Pin_7 ((uint16_t)0x0080) #define GPIO_Pin_8 ((uint16_t)0x0100) #define GPIO_Pin_9 ((uint16_t)0x0200) #define GPIO_Pin_10 ((uint16_t)0x0400) 。。。。。。 #define GPIO_Pin_15 ((uint16_t)0x8000) #define GPIO_Pin_All ((uint16_t)0xFFFF) 下面是有關(guān)GPIO_PinSourceN的定義: #define GPIO_PinSource0 ((uint8_t)0x00) #define GPIO_PinSource1 ((uint8_t)0x01) #define GPIO_PinSource2 ((uint8_t)0x02) #define GPIO_PinSource3 ((uint8_t)0x03) #define GPIO_PinSource4 ((uint8_t)0x04) #define GPIO_PinSource5 ((uint8_t)0x05) #define GPIO_PinSource6 ((uint8_t)0x06) #define GPIO_PinSource7 ((uint8_t)0x07) #define GPIO_PinSource8 ((uint8_t)0x08) #define GPIO_PinSource9 ((uint8_t)0x09) #define GPIO_PinSource10 ((uint8_t)0x0A) 。。。。。。 #define GPIO_PinSource15 ((uint8_t)0x0F)
小結(jié):上面的問題只有基于STM32官方固件庫開發(fā)時才會碰到。說實(shí)在的,這兩個參數(shù)的確容易讓人誤解成一個東西或者弄混淆,尤其剛接觸的人。經(jīng)常有人在這個地方遇到麻煩,之前我在一篇文章中提到過。這里再特意提醒下。 不過ST官方后來推出的STM32CUBE庫在這個地方的代碼寫法做了調(diào)整,不再定義GPIO_PinSourceN。當(dāng)然,因?yàn)楣苣_配置導(dǎo)致異常的問題時有發(fā)生,建議使用ST官方推出的STM32CUBE配置環(huán)境及CUBE參考固件庫著手開發(fā),這樣會省不少事。 |