AT24CXX的自寫入周期是“小于5ms”,所以可以用延時函數(shù)延時5ms解決。
痛點:寫延時函數(shù)可以用軟件延時和定時器延時。軟件延時,時間是多少,需要借助示波器才能看出來精確時間,沒有示波器,或者用示波器看,都是很麻煩,而且如果單片機主頻一改變,軟件延時的值又需要改變。定時器延時占用一個定時器,浪費單片機資源。還有,萬一由于AT24CXX由于自身問題,突然延長了本次的寫入時間,再加上寫程序的時候沒有考慮到這一點,整個系統(tǒng)就完蛋了。
解決辦法:看寫入時序,單片機向AT24CXX發(fā)送起始信號,再發(fā)送一個地址數(shù)據(jù)后,AT24CXX會返回一個ACK信號,如果自寫入周期沒有結(jié)束,就不會返回一個ACK信號,所以,我們可以觀察有沒有這個ACK來判斷自寫入周期是否結(jié)束。這樣的話,不管24CXX的自寫入周期是多長時間,都可以立即進行再寫入一個數(shù)據(jù)或者進行讀操作,提高程序的效率。
下面是用STM32庫函數(shù)寫的程序,實現(xiàn)步驟就是上面解決辦法所講的。
voidWaitWriteCycleOver(void){do{/*發(fā)送開始信號*/I2C_GenerateSTART(I2C1,ENABLE);/*讀SR1寄存器,用于清除開始標志*/I2C_ReadRegister(I2C1,I2C_Register_SR1);/*發(fā)送器件地址*/I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);/*檢測是否成功發(fā)送器件地址*/}while(!(I2C_ReadRegister(I2C1,I2C_Register_SR1)&I2C_FLAG_ADDR));/*清除ACK標志*/I2C_ClearFlag(I2C1,I2C_FLAG_AF);/*發(fā)送停止信號*/I2C_GenerateSTOP(I2C1,ENABLE);}
看完后,你會對程序有若干疑問:
疑問1:為什么不檢測ACK而檢測ADDR?
因為我們用的是硬件I2C,檢測ACK的事情,就由硬件完成了,SR1中的ADDR置位,就說明硬件檢測到了ACK,否則,就沒有檢測到ACK。
疑問2:為什么要單獨清除ACK,不清除其它標志位?
因為ACK位需要軟件清除,其它位讀一下,就自動清除了。