Saturday, April 29, 2017

I2C 使用Microchip plib

I2C 使用Microchip plib

本篇以dsPIC30F為主。

plib 安裝

Legacy PIC24 MCU & dsPIC DSC Peripheral Library下載最新的plib,然後她會要求將plib安裝到你電腦中xc16 complier的資料夾下(linux在”/opt/microchip/xc16”下)。

函式概覽

安裝後文件會在xc16 complier的docs/periph_libs下。
其中plib提供以下函式。
AckI2C
CloseI2C
ConfigIntI2C
DataRdyI2C
IdleI2C
MastergetsI2C
MasterputsI2C
MasterReadI2C
MasterWriteI2C
NotAckI2C
OpenI2C
RestartI2C
SlavegetsI2C
SlaveputsI2C
SlaveReadI2C
SlaveWriteI2C
StartI2C
StopI2C
還有一些MARCO
EnableIntMI2C
DiableIntMI2C
SetPriorityIntMI2C
EnableIntSI2C
DisableIntSI2C
SetPriorityIntSI2C
這份文件16 bit language tools第191頁開始有詳述這些函式的介面。所以本文主要會面向如何運用這些函式達成master與slave溝通。

I2C (dsPIC30F as Master with 7bit address)

reception

以下圖片來自於http://ww1.microchip.com/downloads/en/DeviceDoc/70046E.pdf

對應到plib的流程為。(以下為我在i2cdevlib中所新增的片段,為一次讀多個bytes)。
Master |S |Device Addr+W| |Reg Addr| |S |Device Addr+R| | |NACK|P|
Slave | | |ACK| |ACK| | |ACK|DATA| | |
view raw I2C_read_seq hosted with ❤ by GitHub

請先透過ConfigIntI2C和OpenI2C設定好硬體參數。
IFS0bits.MI2CIF = 0;
IEC0bits.MI2CIE = 0;
/*master Start*/
StartI2C();
/* Clear interrupt flag */
/* Wait till Start sequence is completed */
while(I2CCONbits.SEN);
/*master send AD+W*/
/* Write Slave Address (Write)*/
MasterWriteI2C(devAddr << 1 | 0x00);
/* Wait until address is transmitted */
while(I2CSTATbits.TBF); // 8 clock cycles
/*Slave send Ack*/
while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
IFS0bits.MI2CIF = 0; // Clear interrupt flag
while(I2CSTATbits.ACKSTAT);
/*Master send RA*/
/* Write Register Address */
MasterWriteI2C(regAddr);
/* Wait until address is transmitted */
while(I2CSTATbits.TBF); // 8 clock cycles
/*Slave send ACK*/
while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
IFS0bits.MI2CIF = 0; // Clear interrupt flag
while(I2CSTATbits.ACKSTAT);
/*Master Pause*/
StopI2C();
/* Wait till stop sequence is completed */
while(I2CCONbits.PEN);
/*Master Start*/
StartI2C();
/* Wait till Start sequence is completed */
while(I2CCONbits.SEN);
/*Master send AD+R*/
/* Write Slave Address (Read)*/
MasterWriteI2C(devAddr << 1 | 0x01);
/* Wait until address is transmitted */
while(I2CSTATbits.TBF); // 8 clock cycles
/*Slave send Ack*/
while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
IFS0bits.MI2CIF = 0; // Clear interrupt flag
while(I2CSTATbits.ACKSTAT);
data[0] = MasterReadI2C();
unsigned int i;
for (i = 1 ; i < length ; i++ ){
AckI2C();
while(I2CCONbits.ACKEN == 1);
data[i] = MasterReadI2C();
}
NotAckI2C();
while(I2CCONbits.ACKEN == 1);
/*Master Pause*/
StopI2C();
/* Wait till stop sequence is completed */
while(I2CCONbits.PEN);
view raw I2C_read.cpp hosted with ❤ by GitHub
值得注意的是在dsPIC30F manual中第5步驟。要透過StartI2C再次產生start condition。而讀入多個data bytes可用MastergetsI2C函式。

transmission

transmission只要全部都由Master端給資料即可。
對應到plib的流程為。(以下為我在i2cdevlib中所新增的片段,為一次寫多個bytes)。
Master |S |Device Addr+W| |Reg Addr| |DATA| |P|
Slave | | |ACK| |ACK| |ACK | |
view raw I2C_write_seq hosted with ❤ by GitHub
請先透過ConfigIntI2C和OpenI2C設定好硬體參數。

IFS0bits.MI2CIF = 0;
IEC0bits.MI2CIE = 0;
/*Master Start*/
StartI2C();
/* Wait util Start sequence is completed */
while(I2CCONbits.SEN);
/* Clear interrupt flag */
IFS0bits.MI2CIF = 0;
/*Master send AD+W*/
/* Write Slave address (Write)*/
MasterWriteI2C(devAddr << 1 | 0x00);
/* Wait till address is transmitted */
while(I2CSTATbits.TBF); // 8 clock cycles
/*Slave send ACK*/
while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
IFS0bits.MI2CIF = 0; // Clear interrupt flag
while(I2CSTATbits.ACKSTAT);
/*Master send RA*/
/* Write Slave address (Write)*/
MasterWriteI2C(regAddr);
/* Wait till address is transmitted */
while(I2CSTATbits.TBF); // 8 clock cycles
/*Slave send ACK*/
while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
IFS0bits.MI2CIF = 0; // Clear interrupt flag
while(I2CSTATbits.ACKSTAT);
/*Master send data*/
/* Transmit string of data */
uint8_t i;
for (i = 0 ; i < length ; i++){
MasterWriteI2C(data[i]);
/* Wait till address is transmitted */
while(I2CSTATbits.TBF); // 8 clock cycles
/*Slave send ACK*/
while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
IFS0bits.MI2CIF = 0; // Clear interrupt flag
}
StopI2C();
/* Wait till stop sequence is completed */
while(I2CCONbits.PEN);
view raw I2C_write.cpp hosted with ❤ by GitHub
Written with StackEdit.

Thursday, April 27, 2017

MPU6050 Gyroscope/Accelerometer 使用筆記

MPU6050 Gyroscope/Accelerometer 使用筆記

特性與參數

  • 用途:量測姿態
  • 精度:
    • Gyro : 250/500/1000/2000 dps (degree per second)
    • Accel : +-2/4/6/16 g
  • 輸出資料:為angular rate(角速度) ,16bit , LSB/g
  • 原始感應器電壓VDD(僅有晶片):2.375V-3.46V
  • 原始晶片通訊電氣參數:
    • Vlogic = 1.8V (+-5%) OR VDD
    • VIH(Voltage high level) : 必須超過0.7*Vlogic(MPU6050)
    • VIL(Voltage low level):必須低於0.3*Vlogic(MPU6050)
    • Ci(Input Capacitance): <5pF
    • I2C address: 1101000(when AD0 = 0),1101001(when AD0 = 1)
    • I2C最快頻率:400KHZ
  • 模組(GY521)電壓:3~5V
  • 其他特色:
    • 有內建low pass filter可供程式選擇
    • 中斷信號選擇
    • Auxiliary I2C port可與其他模組串接
    • 可作自我校正
    • 可透過FSYNC pin與外部模組做synchronization (Gyro)
    • On-chip DIgital motion processor
    • 有內建FIFO
  • 通信方式:I2C(MPU6050,MPU6000)/SPI(MPU6000)
  • 晶片datasheet:連結在此

資料單位換算

Gyroscope

首先先看下表為MPU6050 datasheet。

最重要的是scale factor。
透過公式
Gyro_value = (Data Register value) / (Scale factor)
其中單位為degree/second

Accelerometer

首先先看下表

一樣,最重要的是scale factor。
透過公式
Accel_value = (Data Register value) / (Scale factor)
其中單位為g

軟體應用方式

Ardunio使用i2cdevlib。運用其中的MPU6050 lib來溝通。其中,可以安裝processing IDE並開啟i2cdevlib的examplelink,這樣你可獲得一個有小飛機形狀的gui,她會呈現感測器的當前姿態。
dsPIC30F也可以使用i2cdevlib,近日有開始支援MPU6050。
而MPU6050的digital motion proccesor是其一大亮點。透過開啟這個功能,你可以透過interrupt直接獲得sensor當前姿態。她會幫你將角加速度轉成角度,這樣你就不用一直輪詢了。(輪詢計算範例:L3G4200)。
Written with StackEdit.

精選文章

使用Ardunio Atmega2560 連接 nRF24L01+

使用Ardunio Atmega2560 連接 nRF24L01+ 關於library 目前主流有 https://github.com/maniacbug/RF24 與 https://github.com/TMRh20/RF24 這兩個。 其中TMRh20大大做...