1、前言
這段時(shí)間一直在折騰自己的畢設(shè),第二塊板子到手基本上調(diào)通了所有的內(nèi)容,還有幾塊芯片還在寫(xiě)測(cè)試代碼。
其中有一塊BMP280氣壓傳感器,這塊芯片在第一塊板子中是完全能用的,因此可以排除是代碼以及原理圖的問(wèn)題。
在這一版的設(shè)計(jì)中,BMP280單獨(dú)占用了一組I2C1,但是在焊接之后測(cè)試過(guò)程中發(fā)現(xiàn)不能與BMP280建立完整的通訊。
由于我所有的器件都是手焊的,并且該器件屬于QFN封裝,在焊接上重復(fù)了好幾遍,并且也更換過(guò)了器件,但是依舊無(wú)法解決問(wèn)題。
昨天晚上突發(fā)奇想,干脆把I2C1的SCL和SDA線飛到臨近的一組I2C上,接著在初始化的過(guò)程中取消掉I2C1的功能將其空置。
居然莫名其妙的能夠通訊了。
但是這樣子實(shí)在是太丑了,于是今天嘗試能不能解決掉原來(lái)I2C1為什么不能通訊的問(wèn)題。
2、奇怪的引腳狀態(tài)
在GPIO中有一個(gè)只讀寄存器IDR,它記錄芯片主控測(cè)得的引腳電平。
查詢(xún)IDR寄存器的地址值(STM32U0中GPIO的基地址是0x50000000,GPIOB的偏移地址是0x400,IDR寄存器的偏移地址是0x10,因此GPIOB的IDR寄存器的位置是0x50000410)發(fā)現(xiàn)其值是0x3EE2
PB6和PB7初始化都是正常的高電平狀態(tài),但是使用過(guò)I2C之后。
該值變成了0x3E22,對(duì)應(yīng)著PB7/6始終為低電平。
并且將I2C1總線釋放后,將其配置為普通的GPIO模式,開(kāi)漏輸出上拉,強(qiáng)制拉高,其值依舊為0。
可能正是這種異常狀態(tài),導(dǎo)致了I2C1不能正常使用。
3、硬件I2C的死鎖?
在論壇和平時(shí)的了解中,偶爾有人會(huì)提到STM32系列的硬件I2C出現(xiàn)死鎖問(wèn)題。
大體的原因是在數(shù)據(jù)傳輸過(guò)程中,主接收器在接收到最后一個(gè)字節(jié)后會(huì)發(fā)送ACK信號(hào),這會(huì)導(dǎo)致從機(jī)持續(xù)等待數(shù)據(jù),從而造成總線死鎖,這據(jù)說(shuō)是STM32的硬件I2C為了避開(kāi)飛利浦的I2C專(zhuān)利而不得已留下的BUG。
但是I2C的專(zhuān)利在早些年就已經(jīng)過(guò)期了,如果是在F103中遇到的這種問(wèn)題我還能理解(103的硬件I2C我好像也沒(méi)遇到死鎖的問(wèn)題)。
但是STM32U0作為較新的產(chǎn)品,出現(xiàn)I2C死鎖的BUG感覺(jué)是不太應(yīng)該。
4、解決辦法
后來(lái)為了測(cè)試電壓到底是多少,在I2C初始化之后,發(fā)現(xiàn)實(shí)際的情況居然是SCL(PB6)的電壓為2.5V+
這是一個(gè)非常經(jīng)典的空置電壓,這說(shuō)明SCL引腳并沒(méi)有被上拉。由于我一般沒(méi)有習(xí)慣接上拉電阻,都是靠GPIO的內(nèi)部上拉來(lái)充當(dāng)上拉電阻。
那么顯然問(wèn)題就是SCL引腳的內(nèi)部上拉出現(xiàn)了問(wèn)題。
但是明明代碼中很明顯的寫(xiě)的是內(nèi)部上拉,而且非常奇怪的是I2C4明明是配置的內(nèi)部上拉模式,但是I2C1飛到I2C4的時(shí)候(飛線)依舊無(wú)法使用I2C1。并且如果使能I2C1的話會(huì)同樣的導(dǎo)致I2C4癱瘓出現(xiàn)同樣的問(wèn)題。
查詢(xún)芯片手冊(cè)得知GPIO的PUPDR寄存器記錄引腳的上下拉狀態(tài),查詢(xún)?cè)摰刂返闹蛋l(fā)現(xiàn)PB6,PB7均是正常的上拉,但是引腳懸空確實(shí)實(shí)打?qū)嵈嬖诘膯?wèn)題。于是看看能不能通過(guò)外接上拉電阻的情況來(lái)解決問(wèn)題。
當(dāng)在I2C1中接入4.9K的上拉電阻后,發(fā)現(xiàn)BMP280正常使用。
并且使用完I2C后,IDR寄存器的值也是正常的顯示高電平。
5、疑問(wèn)
主要是奇怪為什么同樣的I2C總線,一組I2C1不能使用,其他的I2C總線可以正常使用。
而且如果同時(shí)開(kāi)啟I2C1并且和其他I2C總線連接到一起,會(huì)導(dǎo)致其他I2C總線的SCL引腳處于懸空狀態(tài),從而讓其他的I2C總線失效~~~很奇怪。