[單晶片]-寫I2C通訊(MPU6050為範例)
因為使用到MPU6050因此自己寫了I2C的架構
主要參考網路上許多範例
在此把學習到的東西寫下
I2C架構 主要是利用兩條線
SCL // I2C 的CLK
SDA // I2C 的DATA線
每次要傳送1Byte資料的時候前後都得加上開始和結束訊號
每個晶片通訊都有自己特殊的規範,可以參考晶片的datasheet
以下介紹為一般I2C的架構,地址等函式設定則針對MPU6050做優化
一般而言需要開始信號和結束信號才代表一次的command傳遞完成
上圖代表著開始訊號和結束訊號
開始訊號是由SDA和SCL拉HIGH後,之後SDA拉到LOW
結束訊號是由SCL為高位時,將SDA從LOW拉到HIGH
開始訊號程式碼範例:
delay一段時間讓晶片確認收到
結束訊號程式碼範例:
之後我們必須做一個寫資料和讀資料的動作
資料的輸出和輸入都是從最前面的BIT開始
當SCL=0時 SDA資料是混亂的,因此改變SDA的值
當SCL=1時 SDA資料是穩定的,因此接收SDA的值
利用此方式寫下讀取和寫入
另外需要注意的是I2C傳送中確認是否收到資料
會利用ACK或是NACK來確認
ACK為將SDA拉到HIGH後 晶片會將腳位拉回LOW 表示成功接收資料
NACK為 傳送資料完畢後,將SDA拉到HIGH表示成功傳送資料
WRITE_BYTE的範例程式碼
因為不同用法會有不同的移向
read模式bit7為1
write模式bit7為0
寫入內部位置時不需更改 因此分三模式可以根據自己需要而改寫
READ_BYTE的範例程式碼
接下來就是要讀取一個資料和寫入一個資料所需要的動作
只要結合上述副程式便能夠完成。
溝通的流程
MPU6050 本身Address (0x68)
寫入資料:
Write的步驟如下
1.寫入裝置位置(0x68,0)模式0=write
2.寫入內部address 模式2 不須更改
3.寫入資料
程式碼範例如下
WRITE_ALL
READ_ALL
這些完成後變成完成MPU6050的溝通
另外使用上需要注意事項為
MPU6050 GY521模組
雖然DATASHEET上寫的預設除了幾個Address以外都為0
但是實際使用上發現
一開始模組處於sleep狀態
如果想要得到測量值,必須先甦醒
初始化指令如下
便可以順利得到測試數據。
正常使用MPU6050模組
如果有想到問題再額外補上
大致如此
主要參考網路上許多範例
在此把學習到的東西寫下
I2C架構 主要是利用兩條線
SCL // I2C 的CLK
SDA // I2C 的DATA線
每次要傳送1Byte資料的時候前後都得加上開始和結束訊號
每個晶片通訊都有自己特殊的規範,可以參考晶片的datasheet
以下介紹為一般I2C的架構,地址等函式設定則針對MPU6050做優化
一般而言需要開始信號和結束信號才代表一次的command傳遞完成
上圖代表著開始訊號和結束訊號
開始訊號是由SDA和SCL拉HIGH後,之後SDA拉到LOW
結束訊號是由SCL為高位時,將SDA從LOW拉到HIGH
開始訊號程式碼範例:
delay一段時間讓晶片確認收到
SDA=1
SCL=1;
delay(20);
SDA=0;
delay(20);
SCL=0;
結束訊號程式碼範例:
delay(20);
SDA=0;
delay(20);
SCL=1;
delay(20);
SDA=1;
delay(20);
之後我們必須做一個寫資料和讀資料的動作
資料的輸出和輸入都是從最前面的BIT開始
當SCL=0時 SDA資料是混亂的,因此改變SDA的值
當SCL=1時 SDA資料是穩定的,因此接收SDA的值
利用此方式寫下讀取和寫入
另外需要注意的是I2C傳送中確認是否收到資料
會利用ACK或是NACK來確認
ACK為將SDA拉到HIGH後 晶片會將腳位拉回LOW 表示成功接收資料
NACK為 傳送資料完畢後,將SDA拉到HIGH表示成功傳送資料
WRITE_BYTE的範例程式碼
void i2c_write_byte(char address,int mode)
{
int count=0; //計數用
char temp=0,ACK;
//因為address 只有7bit+1biy(R/W)
if(mode==0) // 0=write資料用 1=read用 2=不改
{
address=address<<1; //向左移 表示最後一個bit為0
}
else if(mode==1)
{
address=(address<<1)|1; //向左移後 or最後一個bit為1
}
else if (mode==2)
{
address=address ;
//internal_register 不改
}
// WRITE
for(count=0;count<8;count++)
{
temp=address>>(7-count)&0x01; //寫入的資料
delay(20);
SDA=temp;
delay(20);
SCL=1;
delay(20);
SCL=0;
}
//WRITE
//ACK 的寫入
delay(20);
SDA=1;
delay(20);
SCL=1;
delay(20);
ACK=SDA;
delay(20);
SCL=0;
delay(20);
//ACK
}
上面mode有分三種的原因在於,希望呼叫副程式的時候不需要改Address因為不同用法會有不同的移向
read模式bit7為1
write模式bit7為0
寫入內部位置時不需更改 因此分三模式可以根據自己需要而改寫
READ_BYTE的範例程式碼
char i2c_read_byte(void)
{
int count=0;
char word=0,temp=0;
for(count=0;count<8;count++)
{
word=word<<1; //先接收到的資料往右位移
delay(20);
SCL=1;
delay(20);
word|=SDA; //用OR如果資料為1就是顯示1
delay(20);
SCL=0;
}
//指令之間要delay 讓sensor及時感測和傳輸資料 如果clock跳太過就會導致錯誤
delay(20);
SDA=1;
delay(20);
SCL=1;
delay(20);
SCL=0;
return word;
}
接下來就是要讀取一個資料和寫入一個資料所需要的動作
只要結合上述副程式便能夠完成。
溝通的流程
MPU6050 本身Address (0x68)
寫入資料:
Write的步驟如下
1.寫入裝置位置(0x68,0)模式0=write
2.寫入內部address 模式2 不須更改
3.寫入資料
程式碼範例如下
WRITE_ALL
void i2c_write_all(char internal_address,char command)
{
i2c_start();
i2c_write_byte(0x68,0);
i2c_write_byte(internal_address,2);
i2c_write_byte(command,2);
i2c_stop();
}
READ_ALL
char i2c_read_all(char internal_address)
{
char word=0;
i2c_start();
i2c_write_byte(0x68,0);
i2c_write_byte(internal_address,2);
i2c_start();
i2c_write_byte(0x68,1);
word=i2c_read_byte();
i2c_stop();
return word;
}
這些完成後變成完成MPU6050的溝通
另外使用上需要注意事項為
MPU6050 GY521模組
雖然DATASHEET上寫的預設除了幾個Address以外都為0
但是實際使用上發現
一開始模組處於sleep狀態
如果想要得到測量值,必須先甦醒
初始化指令如下
//i2c initial
i2c_write_all(0x6b,0x00); //I2C START MPU6050從SLEEP醒來
//i2c initail
便可以順利得到測試數據。
正常使用MPU6050模組
如果有想到問題再額外補上
大致如此
留言
張貼留言