周末需要休息,也需要做事,像我這種,周末也不忘寫文章分享給你們。目的很簡單,就是讓你們不休息。
開玩笑啦
像我這種人
還是希望你們多學點知識
正所謂學到老,活到老
Ⅰ
寫在前面
相信看過前面那篇文章“更加深入理解 I2C總線、協議及應用”的人,對I2C都有一定的了解了。那篇文章是針對I2C使用單片機IO模擬I2C方式實現讀寫操作。
本文將講述硬件I2C讀寫操作,也就是由處理器自身硬件的I2C實現時鐘、數據的傳輸過程。
為方便大家閱讀,本文內容已經整理成PDF文件:
http://pan.baidu.com/s/1i5uWhJR
Ⅱ
STM8硬件I2C知識
STM8S的I2C模塊不僅可以接收和發送數據,還可以在接收時將數據從串行轉換成并行數據,在發送時將數據從并行轉換成串行數據。可以開啟或禁止中斷。接口通過數據引腳(SDA)和時鐘引腳(SCL)連接到I2C總線。允許連接到標準(最高100kHz)或快速(最高400kHz)的I2C總線。
1.I2C的4種模式
● 從設備發送模式
● 從設備接收模式
● 主設備發送模式
● 主設備接收模式
2.I2C的主要特點
● 并行總線/I2C總線協議轉換器
● 多主機功能:該模塊既可做主設備也可做從設備
● I2C主設備功能
─ 產生起始和停止信號
● I2C從設備功能
─ 停止位檢測
● 產生和檢測7位/10位地址和廣播呼叫
● 支持不同的通訊速度
─ 標準速度(最高 100 kHz)
─ 快速(最高 400 kHz)
● 狀態標志:
─ 發送器/接收器模式標志
─ I2C 總線忙標志
─ 主模式時的仲裁失敗
─ 地址/數據傳輸后的應答(ACK)錯誤
─ 檢測到錯誤的起始或停止條件
─ 禁止時鐘展寬功能時數據過載或欠載
● 3種中斷
─ 1 個通訊中斷
─ 1 個出錯中斷
─ 1 個喚醒中斷
● 喚醒功能
─ 從模式下如果檢測到地址匹配可以將 MCU 從低功耗模式中喚醒
● 可選的時鐘展寬功能
3.主模式所要求的操作順序
● 在I2C_FREQR寄存器中設定該模塊的輸入時鐘以產生正確的時序
● 配置時鐘控制寄存器
● 配置上升時間寄存器
● 編程I2C_CR1寄存器啟動外設
● 置I2C_CR1寄存器中的START位為1,產生起始條件
● I2C模塊的輸入時鐘頻率必須至少是:
● 標準模式下為:1MHz
● 快速模式下為:4MHz
Ⅲ
軟件工程源代碼
1.關于工程
本文提供的工程代碼是基于前面軟件工程“STM8S-A04_UART基本收發數據”增加I2C接口修改而來。讀寫EEPROM的方式和之前“模擬I2C讀寫”的方式不一樣。
2.硬件I2C初始化
void I2C_Initializes(void)
{
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
I2C_Cmd(ENABLE);
I2C_Init(I2C_SPEED, I2C_SLAVE_ADDRESS7, I2C_DUTYCYCLE_2, I2C_ACK_CURR,
I2C_ADDMODE_7BIT, 16);
}
I2C_SPEED:I2C速度,一般是100K - 400K
I2C_SLAVE_ADDRESS7:從設備地址,作為主設備時,這個地址不起作用。
I2C_DUTYCYCLE_2:快速模式
I2C_ACK_CURR:應答
I2C_ADDMODE_7BIT:設備地址位數
16:輸入時鐘(單位M)
2.EEPROM_WriteByte寫一字節
寫一字節分為5個步驟:
void EEPROM_WriteByte(uint16_t Addr, uint8_t Data)
{
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
/* 1.開始 */
I2C_GenerateSTART(ENABLE);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
/* 2.設備地址/寫 */
I2C_Send7bitAddress(EEPROM_DEV_ADDR, I2C_DIRECTION_TX);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 3.數據地址 */
#if (8 == EEPROM_WORD_ADDR_SIZE)
I2C_SendData((Addr&0x00FF));
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
#else
I2C_SendData((uint8_t)(Addr>>8));
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData((uint8_t)(Addr&0x00FF));
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
#endif
/* 4.寫一字節數據 */
I2C_SendData(Data);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* 5.停止 */
I2C_GenerateSTOP(ENABLE);
}
3.EEPROM_ReadByte讀一字節
讀一字節比寫一字節多了2個步驟,原因是讀的時候多寫地址到讀數據這個切換過程。
void EEPROM_ReadByte(uint16_t Addr, uint8_t *Data)
{
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
/* 1.開始 */
I2C_GenerateSTART(ENABLE);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
/* 2.設備地址/寫 */
I2C_Send7bitAddress(EEPROM_DEV_ADDR, I2C_DIRECTION_TX);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 3.數據地址 */
#if (8 == EEPROM_WORD_ADDR_SIZE)
I2C_SendData((Addr&0x00FF));
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
#else
I2C_SendData((uint8_t)(Addr>>8));
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData((uint8_t)(Addr&0x00FF));
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
#endif
/* 4.重新開始 */
I2C_GenerateSTART(ENABLE);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
/* 5.設備地址/讀 */
I2C_Send7bitAddress(EEPROM_DEV_ADDR, I2C_DIRECTION_RX);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
/* 6.讀一字節數據 */
I2C_AcknowledgeConfig(I2C_ACK_NONE);
while(I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY) == RESET);
*Data = I2C_ReceiveData();
/* 7.停止 */
I2C_GenerateSTOP(ENABLE);
}
Ⅳ下載
STM8S資料:
http://pan.baidu.com/s/1o7Tb9Yq
軟件源代碼工程兩版本(STM8S-A10_I2C讀寫EEPROM(硬件)):
http://pan.baidu.com/s/1c2EcRo0
-
EEPROM
+關注
關注
9文章
1010瀏覽量
81416 -
I2C
+關注
關注
28文章
1482瀏覽量
123364 -
STM8S
+關注
關注
16文章
149瀏覽量
31369
發布評論請先 登錄
相關推薦
評論