|
發布時間: 2025-12-8 20:16
正文摘要:通訊協議是干什么用的?它是各設備包括單片機以及各種外設之間用于傳輸數據的人為規則。前面的12864屏,我們采用的是一次傳輸一個字節8位二進制數的方式來傳輸數據的,這種傳輸方式的極其明顯的缺點是占用的單片機的 ... |
|
我經過研究發現,IIC用軟件模擬,分別寫啟動程序,停止程序,再寫移位和位與屏蔽取高一位判斷就1還是0,然后把它等于到SDA上,發送程序,再ACK應答程序。用時在組裝起來。硬件這些程序已經是寄存器命令,一字節數據放入BUF發送。好多通訊由軟件模擬變為硬件,寫程序就簡單 你可以看IIC文字很難理解,不過直接看視頻IIC軟件手寫過程,就通了 #ifndef __IIC_H #define __IIC_H #include "config.h" // ===================== 引腳定義 ======================= sbit SCL = P1^0; // 時鐘線 sbit SDA = P1^1; // 數據線 // ===================== 函數聲明 ======================= void IIC_Init(void); void IIC_Start(void); void IIC_Stop(void); void IIC_Send_Byte(unsigned char txd); unsigned char IIC_Read_Byte(unsigned char ack); bit IIC_Wait_Ack(void); void IIC_Ack(void); void IIC_NAck(void); #endif // ============================== // 2. IIC起始信號 // ============================== void IIC_Start(void) { SDA = 1; // 確保SDA高 SCL = 1; // 時鐘高 delay_us(5); SDA = 0; // 時鐘高電平時,SDA從高變低 = 起始信號 delay_us(4); SCL = 0; // 拉低時鐘,準備發送數據 }// ============================== // 3. IIC停止信號 // ============================== void IIC_Stop(void) { SDA = 0; // 確保SDA低 SCL = 1; // 時鐘高 delay_us(5); SDA = 1; // 時鐘高時,SDA從低變高 = 停止信號 delay_us(4); } // ============================== // 4. 發送一個字節(8位) // ============================== void IIC_Send_Byte(unsigned char txd) { unsigned char t; for(t=0;t<8;t++) // 循環8次,發8位 { SCL = 0; // 時鐘拉低,才能改變SDA delay_us(2); if((txd & 0x80)>>7) // 取最高位 SDA = 1; else SDA = 0; txd <<= 1; // 左移一位 delay_us(2); SCL = 1; // 時鐘拉高,從機采樣數據 delay_us(2); } SCL = 0; // 8位發完,拉低時鐘 delay_us(2);// ============================== // 5. 等待從機應答(ACK) // ============================== bit IIC_Wait_Ack(void) { unsigned char ucErrTime = 0; SDA = 1; delay_us(1); // 主機釋放SDA SCL = 1; delay_us(1); // 時鐘拉高 while(SDA) // 讀取SDA:低=應答,高=不應答 { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; // 失敗 } } SCL = 0; // 時鐘拉低 return 0; // 成功 } }// ============================== // 6. 主機產生應答 ACK // ============================== void IIC_Ack(void) { SCL = 0; SDA = 0; // 應答:SDA=0 delay_us(2); SCL = 1; delay_us(2); SCL = 0; } // ============================== // 8. 讀取一個字節 // ============================== unsigned char IIC_Read_Byte(unsigned char ack) { unsigned char i,receive = 0; for(i=0;i<8;i++) { SCL = 0; delay_us(2); SCL = 1; // 時鐘拉高,讀取數據 receive <<= 1; if(SDA) receive++; delay_us(1); } if(!ack) IIC_NAck(); // 最后一個字節發NACK else IIC_Ack(); // 繼續讀發ACK return receive; } START → 發送設備地址 → 等待ACK → 發送寄存器地址 → ACK → 發送數據 → ACK → STOP START → 設備地址 → ACK → 寄存器地址 → ACK → START → 設備地址+1 → ACK → 讀取數據 → NACK → STOP 五、必須記住的 5 條規則 SCL 高電平時,SDA 不能變 SCL 高電平時,SDA 下降沿 = START SCL 高電平時,SDA 上升沿 = STOP 數據高位先發 每發 1 個字節必須等應答 六、這個代碼能直接驅動哪些設備? ✅ OLED 顯示屏 ✅ 24C02 EEPROM ✅ MPU6050 ✅ SHT30 / SHT20 ✅ HMC5883 ✅ 所有 IIC 設備 |
| 寫得很詳細,慢慢研究才行 |
| 很棒! |
| 很給力啊! |
| 講解非常的細致,謝謝樓主 加油 努力 |
| 來學習學習 |
| 講解非常的細致,看其他資料都沒弄太明白 |
| 講的明白。 |
|
任何串行通訊協議,其原理其實極其簡單,就一條:通訊雙方事先協商好,用不同的變化組合來表達不同的意思。 剩下的,就只是規則了:誰主誰從、什么樣的動作組合表示開始、什么樣的動作組合表示結束、什么樣的動作表示開始傳遞數據、什么樣的動作組合表示放上去了一位數據、什么樣的動作表示可以讀取數據了、什么樣的動作表示這一位數據是1或是0、什么樣的動作表示反饋信號、傳輸方向怎么確定、是從高位到低位還是從低位到高位進行傳輸、哪些數據是命令類數據哪些數據才是本次要傳送的目標內容、要不要對接收到的數據進行正確性校驗、對錯誤數據怎么處理,等等。 你在學習任何通訊協議時,要弄清楚的就是這些規則,萬變不離其宗,這些規則沒多少道理可講,設計者就是這樣規定的,我們該做的就是個死記。如果你看不慣或者覺得不夠合理,可以,你自己想怎么設計就怎么設計,然后當然你也可以申請專利,至于能不能得到推廣?要不你自娛自樂吧。 關于動作組合,實在是乏善可陳,就三個要素:電位、時間、傳輸數據線。 |
dyx811 發表于 2025-12-9 12:32 謝了,你們的肯定,就是我的動力。 |
| IIC讓我迷惑了好久,這里終于悟到了IIC通訊的真理,感謝樓主的分享!講解非常的細致入微,是我學習的指路明燈,向您致敬! |