Komunikasi I2C pada Microcontroller AVR

Sumber:

http://www.robot-electronics.co.uk/acatalog/I2C_Tutorial.html

http://en.wikipedia.org/wiki/I%C2%B2C

SPC Motor Controller Manual Guide.

Help — CodeVisionAVR.

I2C (Inter-Integrated Circuit) (umumnya disebut sebagai “two-wire interface”). Berikut konfigurasi dari sistem I2C.

Berikut timing diagram dari komunikasi I2C.

Pada komunikasi I2C terdapat perangkat master dan slave. Master adalah perangkat yang mengatur jalur clock SCL. Sedangkan slave adalah perangkat yang merespon perintah master. Slave tidak dapat mengirim sinyal untuk dapat mentransfer data pada jalur I2C, hanya master yang dapat melakukannya.Dimungkinkan untuk memiliki banyak master, tapi hal tersebut tidak biasa.

Berikut adalah timing diagram dari sebuah master yang ingin meminta data yang terdiri dari dua sekuen khusus yang ditetapkan untuk I2C yaitu Start dan Stop.

Data terdiri dari 8 bit dan menjadi 9 bit dengan bit terakhir adalah ACK. ACK adalah sinyal yang dikirim oleh sinyal penerima. Jika perangkat penerima mengirim kembali bit low ACK, karena sudah menerima data dan berarti siap menerima data selanjutnya.   Jika sinyal ACK yang dikirim adalah high maka perangkat tersebut tidak dapat menerima data lebih lanjut dan master harus menghentikan transfer dengan mengirim Stop sequence.

Standar kecepatan clock (SCL) untuk I2C bisa mencapai 100KHz. Philips sebagai perusahaan yang memperkenalkan pertamakali I2C mendefinisikan beberapa tingkatan kecepatan: Fast mode, bisa mencapai 400KHz dan High Speed mode yang mencapai 3.4MHz. Untuk beberapa aplikasi pada perangkat yang sederhana tampaknya 100KHz sudah cukup.

Semua pengalamatan I2C terdiri dari 7bit atau 10bit. Penggunaan pengalamatan 10bit jarang. Biasanya yang banyak digunakan adalah pengalamatan 7bit. Berarti kita bisa mempunyai 128 perangkat yang akan tersambung ke bus, dari 0 sampai 127. Seperti pada gambar di atas yang terdiri dari 9bit terdapat R/W sebagai bit pengatur apakah maksud dari master adalah untuk write/menulis (nilai R/W bit = 0) data atau read/membaca (nilai R/W bit = 1) data dari slave.  Pada intinya data yang dikirim adalah 8bit dengan LSB adalah R/W bit.

Berikut contoh kode untuk master yang saya dapatkan dari http://www.robot-electronics.co.uk/acatalog/I2C_Tutorial.html jika ingin membuat kode sendiri. Contoh di bawah ini untuk mikrokontroler PIC akan tetapi tampaknya bisa digunakan untuk mikrokontroler lainnya yang mempunyai format pemograman yang sama.

#define SCL     TRISB4 // I2C bus
#define SDA     TRISB1 //
#define SCL_IN  RB4    //
#define SDA_IN  RB1    //

To initialize the ports set the output resisters to 0 and the tristate registers to 1 which disables the outputs and allows them to be pulled high by the resistors.
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;

We use a small delay routine between SDA and SCL changes to give a clear sequence on the I2C bus. This is nothing more than a subroutine call and return.
void i2c_dly(void)
{
}

The following 4 functions provide the primitive start, stop, read and write sequences. All I2C transactions can be built up from these.
void i2c_start(void)
{
SDA = 1;             // i2c start bit sequence
i2c_dly();
SCL = 1;
i2c_dly();
SDA = 0;
i2c_dly();
SCL = 0;
i2c_dly();
}

void i2c_stop(void)
{
SDA = 0;             // i2c stop bit sequence
i2c_dly();
SCL = 1;
i2c_dly();
SDA = 1;
i2c_dly();
}

unsigned char i2c_rx(char ack)
{
char x, d=0;
SDA = 1;
for(x=0; x<8; x++) {
d <<= 1;
do {
SCL = 1;
}
while(SCL_IN==0);    // wait for any SCL clock stretching
i2c_dly();
if(SDA_IN) d |= 1;
SCL = 0;
}
if(ack) SDA = 0;
else SDA = 1;
SCL = 1;
i2c_dly();             // send (N)ACK bit
SCL = 0;
SDA = 1;
return d;
}

bit i2c_tx(unsigned char d)
{
char x;
static bit b;
for(x=8; x; x–) {
if(d&0×80) SDA = 1;
else SDA = 0;
SCL = 1;
d <<= 1;
SCL = 0;
}
SDA = 1;
SCL = 1;
i2c_dly();
b = SDA_IN;          // possible ACK bit
SCL = 0;
return b;
}

The 4 primitive functions above can easily be put together to form complete I2C transactions. Here’s and example to start an SRF08 ranging in cm:

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0×00);             // SRF08 command register address
i2c_tx(0×51);             // command to start ranging in cm
i2c_stop();               // send stop sequence

Now after waiting 65mS for the ranging to complete (I’ve left that to you) the following example shows how to read the light sensor value from register 1 and the range result from registers 2 & 3.

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0×01);             // SRF08 light sensor register address
i2c_start();              // send a restart sequence
i2c_tx(0xE1);             // SRF08 I2C address with R/W bit set

lightsensor = i2c_rx(1);  // get light sensor and send acknowledge. Internal register address will increment automatically.
rangehigh = i2c_rx(1);    // get the high byte of the range and send acknowledge.
rangelow = i2c_rx(0);     // get low byte of the range – note we don’t acknowledge the last byte.
i2c_stop();               // send stop sequence

I2C pada CodeVisionAVR

Create New Project

Klik OK.

Jika ada pertanyaan “Do you want to use the CodeWizardAVR?”, klik Yes. Lalu pilih type dari avr yang digunakan dan klik OK. Setelah itu, aturlah konfigurasi dari mikrokontroler yang digunakan. Lalu klik pada menu I2C untuk mengatur fitur I2C yang akan digunakan. Cobalah konfigurasi seperti gambar di bawah ini.

Setelah itu “Generate, Save and Exit” yang dipilih pada menubar CodeWizardAVR – Program. Jika pada CVAVR versi lama, hal itu terdapat pada menubar file.

Setelah setting dari CodeWizardAVR selesai, maka program sudah mulai bisa diedit.

Berikut sintax Master yang bisa digunakan untuk berkomunikasi dengan perangkat Slave pada komunikasi I2C.

//mengirim data I2C
i2c_start();

i2c_write(Device_ADDRESS);

i2c_write(address);

i2c_write(data);

i2c_stop();

/* 10ms delay untuk memastikan proses pengiriman data sudah selesai */

delay_ms(10);

-Device_ADDRESS adalah alamat dari perangkat slave I2C.

-address adalah alamat dari register yang akan dituliskan data.

-data 8-bits.

//menerima data I2C

i2c_start();

i2c_write(Device_ADDRESS);

i2c_write(address);

i2c_start();

i2c_write(Device_ADDRESS | 1);

data=i2c_read(0);

i2c_stop();

-Device_ADDRESS adalah alamat dari perangkat slave I2C.

-address adalah alamat dari register yang akan diakses.

-i2c_write(Device_ADDRESS | 1); Bit terakhir di or dengan 1 yang hasilnya pasti bit terakhir 1 berarti perintah menulis.

-data 8-bits dari slave dimasukan ke variable data.

Biasanya format pengiriman data I2C tergantung pada perangkat yang diakses yang dijelaskan terlebih dahulu pada datasheet.

Berikut contoh komunikasi I2C pada SPC MOTOR CONTROLLER.

i2c_start();        // Start Condition

i2c_write(0xE0);    // Tulis ke modul SPC MOTOR CONTROLLER

i2c_write(0x0E);    // Perintah “Set PWM”

i2c_write(0×01);    // Untuk Motor DC ke-2

i2c_write(128);     // Level PWM

i2c_stop();         // Stop Condition

delay_us(10);       // delay 10 us

i2c_start();        // Start Condition

i2c_write(0xE1);    // Baca ke modul SPC MOTOR CONTROLLER

temp1 = i2c_read(0);// Data Acknowledgement

i2c_stop();         // Stop Condition

___________________________________________________________

Berikut website yang membahas tentang I2C:

https://ccrma.stanford.edu/courses/250a-fall-2003/docs/avrlib-new/i2c_8c.html

http://www.engineersgarage.com/embedded/avr-microcontroller-projects/atmega32-twi-two-wire-interface

The I2C Physical Protocol
When the master (your controller) wishes to talk to a slave (our CMPS03 for example) it begins by issuing a start sequence on the I2C bus. A start sequence is one of two special sequences defined for the I2C bus, the other being the stop sequence. The start sequence and stop sequence are special in that these are the only places where the SDA (data line) is allowed to change while the SCL (clock line) is high. When data is being transferred, SDA must remain stable and not change whilst SCL is high. The start and stop sequences mark the beginning and end of a transaction with the slave device.
About these ads

28 Responses to Komunikasi I2C pada Microcontroller AVR

  1. reza says:

    gan kasih tau cara program ultrasonik srf 08
    itu kan pake i2c, saya pake atmega 16
    bngung ni
    tlong email saya ya
    amaterasu182@gmail.com

  2. nugraha says:

    mAAf mas mw tanya,
    tw program AVR sistem antrian pke i2c g?
    berbagi ilmunya dnk..
    mksh.

  3. fajar says:

    mas tau cara program komunikasi sensor adxl345 dengan mikro atmega128?
    adxl345 menggunakan komunikasi I2C
    KLO boleh tolong kah tau contoh program’a mas

    • wangready says:

      gk tau mas, belum nyoba…tp formatnya biasanya sama,
      WRITE: START–>kirim ID perangkat–>kirim address–>kirim data–>STOP
      READ: START–>kirim ID perangkat–>kirim address–>START–>kirim ID perangkat+1 –> READ –> STOP

  4. menirisme says:

    kalo mau nyoba simulasi code di atas di proteus, bisa tolong kasih tau rangakaiannya gmn ga???
    makasiihhh

    • wangready says:

      coba aja mas liat di CodeVisionAVR bagian Help, Help Topics, lalu search I2C…kalo nyoba nya bisa nyoba koneksi dengan EEPROM eksternal, koneksi port nya SCL ke SCL, SDA ke SDA…

  5. jamal says:

    gan wang, tanya dong.
    ane pny problem akses gyro itg3200. awalnya saya pake crystal prosessor 4MHz dan tidak ada masalah. kemudian saya ganti 16MHz. itu jadi masalah.
    sepertinya clock i2c harus diganti juga. lha cara setup clock i2c nya gmna? bisa g ya?

    • wangready says:

      setau saya klo I2C CVAVR clock nya gk bisa diganti, klo gk I2C nya pake mode two wire aja…

      • jamal says:

        lah kalo pk TWI kondisi start sama stop nya gmn ya? mohon petunjuknya..

      • wangready says:

        saya jg gk tau mas, belum nyoba, tp saya liat temen saya klo gk salah dia bikin koding pake register TWI nya…di datasheet atmega yg lengkap, ada contoh kodingannya dalam bahasa asembli maupun C, klo di datasheet atmega8535 yg saya download ada di halaman 187

  6. comet says:

    mas kalo mau komunikasi 2 mikrokontroler pake i2c gimana ya?

    • wangready says:

      belum nyoba gan, pernah nya nyoba pake modul yg beli baru 1 lg pake mikro bikin, klo dua2nya bikin belum pernah nyoba…pake serial aja gan, dikasih address per-device-nya…

  7. Deny says:

    maaf mas, saya mau tanya saya mau menggunakan sensor suhu dan kelembaban jenis DHT 11
    kalau menggunakan mikrokontroler ATMega8535 harus menggunakan komunikasi i2c, konfigurasi nya seperti apa yah
    makasih yah mass…

    • wangready says:

      ane belum ngoprek gan, pernahnya yang SHT11, ini kodingannya…

      
      /*======================================================================= 
         Chip type           : ATmega8535
         Program type        : Application
         Clock frequency     : 4,000000 MHz
         Memory model        : Small
         External SRAM size  : 0
         Data Stack size     : 128         
      ========================================================================*/
      
      
      #include 
      #include 
      #include 
      
      #asm
         .equ __lcd_port=0x15 ;PORTC
      #endasm
      #include 
      
      sfrb PORTA=0x1b;
      sfrb PINA=0x19;
      #define SDAOut PORTA.0
      #define SDAIn PINA.0
      #define SCLK PORTA.1
      #define out PORTB.0
      
      
      // Declare your global variables here   
      unsigned char TimeOut,AckBit,buf[33];  //Ackbit : '0' (ACK), '1' (NOACK)
      unsigned int DataTempSHT,DataRHSHT,DataRead;
      float RH,Temp; 
      
      /*Membuat kondisi "start" ke SHT11 ("Transmission Start" sequence)
                _____         _____
       ShtData       |_______|
                    ___     ___
       ShtClock ___|   |___|   |___
       Clock         1       2        */
      void StartSignal (void)
      {        
      unsigned char DDRATemp;
          DDRATemp = DDRA;    
          DDRA |= 0x01;       // PortA.0 sbg Output
          SDAOut = 1;
          SCLK = 0;
          SCLK = 1;           //Clock pertama
          SDAOut = 0;
          SCLK = 0;
          SCLK = 1;           //Clock kedua
          SDAOut = 1;
          SCLK = 0;           //Pin Clock = '0'
          DDRA = DDRATemp;        
      }
      
      //Reset komunikasi: 9 clock cyle dengan ShtData '1', lalu kondisi start 
      void ResetSHT (void)
      {
      unsigned char i,DDRATemp;
          DDRATemp = DDRA;
          DDRA |= 0x01;
          SDAOut = 1;
          SCLK = 0;
          for (i=0; i measure OK)
      void SHTWait (void)
      {
          unsigned char i,DDRATemp;
          DDRATemp = DDRA;
          DDRA |= 0x01;
          SDAOut=1;          //Pin ShtData sebagai input
          DDRA &= 0xFE;
          for (i=0; i pengukuran selesai
              if (TimeOut==0) goto ExitSHT_Wait;
              delay_ms(1);
            }       
          ExitSHT_Wait:        
          DDRA = DDRATemp;  
      } 
      
      // Transmit Data dan ambil bit Acknowledge
      void SHTWriteByte (unsigned char data)
      {
          unsigned char i,DDRATemp;
          DDRATemp = DDRA;
          DDRA |= 0x01;
          for (i=0; i>7)==1) SDAOut = 1;    //Kirim MSB first
              else SDAOut = 0;
              SCLK = 1;                       //Kirim Data (ShtClock rising edge)
              SCLK = 0;
              data <<= 1;                     // geser data kekiri 1 bit
            }
          SDAOut = 1;                         //Pin ShtData sebagai input
          SCLK = 1;
          DDRA &= 0xFE;
          AckBit = SDAIn;                     //Ambil sinyal acknowledge
          SCLK = 0;
          DDRA = DDRATemp; 
      }
      
      //Receive Data dan kirim bit "AckBit" ('0' untuk ACK atau '1' untuk NACK)
      void SHTReadByte (void)
      {
          unsigned char i,DDRATemp;
          DataRead = 0x00;
          DDRATemp = DDRA;
          DDRA |= 0x01;
          SDAOut = 1;          //Pin ShtData sebagai input
          DDRA &= 0xFE;
          for (i=0; i<8; i++)
            {
              DataRead<<=1;
              SCLK = 1;
              DataRead |= SDAIn;  //Ambil Data (MSB first)
              SCLK = 0;
            }
          DDRA |= 0x01;    
          if (AckBit==1) SDAOut = 1;   //Kirim Noacknowledge
          else SDAOut = 0;             //Kirim Acknowledge
          SCLK = 1;
          SCLK = 0;
          SDAOut = 1;          //Pin ShtData sebagai input
          DDRA = DDRATemp;
      }
      
      // Pembacaan Temperature dari SHt11
      void SHTReadTemp (void)
      {        
          StartSignal();
          SHTWriteByte(0x03);                 //Command Measure Temperature
          if (AckBit==0)
            {
              SHTWait();                      //Tunggu sampai pengukuran selesai
              if (TimeOut==0)
                {
                 AckBit=0;                    //Kirim ACK untuk menerima byte berikutnya
                  SHTReadByte();              // Ambli Byte MSB
                  DataTempSHT = DataRead;
                  DataTempSHT <<= 8;
                  AckBit=1;                   //Kirim NACK untuk mengakhiri pengambilan data
                  SHTReadByte();
                  DataTempSHT |= DataRead;   //Ambil byte LSB
                  
                  DataRead = DataTempSHT;            
                }
            }
      }
      
      void SHTReadHumidity (void)
      {
          StartSignal();
          SHTWriteByte(0x05);   //Command Measure Humidity
          if (AckBit==0)
            {
              SHTWait();
              if (TimeOut==0)
                {
                  AckBit=0;
                  SHTReadByte();
                  DataRHSHT = DataRead;
                  DataRHSHT < A.1 = Output(SCLK), A.0 = Input/Output(SDA)
      PORTA=0x00;
      DDRA=0x02;
      
      PORTB=0x00;
      DDRB=0x08;  
      
      PORTD=0x00;
      DDRD=0x04;  
        
      // Timer/Counter 0 initialization
      // Clock source: System Clock
      // Clock value: 500.000 kHz
      // Mode: Normal top=FFh
      // OC0 output: Disconnected
      TCCR0=0x71;
      TCNT0=0x00;
      OCR0=0x00;
      
      // Timer(s)/Counter(s) Interrupt(s) initialization
      TIMSK=0x00;
      
      //#asm("sei")
      
      lcd_init(16);
      
      delay_ms(1000);
      ResetSHT();      //Connection Reset
         
      while (1)
            {
            // Place your code here    
                                
            SHTReadHumidity();
            RH=((float)(DataRead*0.0405)-(DataRead*DataRead*0.0000028)-4);
            ResetSHT();
            SHTReadTemp();
            Temp=((float)(DataRead-4000))/100;
            ResetSHT();
            lcd_clear();
            lcd_gotoxy(0,0);
            lcd_putsf(" RH  Temp");
            lcd_gotoxy(0,1); 
            sprintf(buf,"%0.2f %0.2f",RH,Temp);
            lcd_puts(buf);
            delay_ms(1000);
            };
      }
      
      
      
  8. tatang_soetarma says:

    untuk komunikasi i2c dgn sensor accelerometer gimana ya Mas? mohon bantuannya… trims

  9. KOMUNIKASI MODUL KAMERA DENGAN METODE I2C gimana ya Mas?
    minta skematik nya yah ?
    mohon bantuannya… trims

  10. aji says:

    gan…lo mau gnti alamat i2c TPA81 gmn ya??
    thx b4….

  11. Wulan says:

    Maaf mas…itu codingan buat SHT11 belum lengkap yaa.. pas di compile masih ada kurang-kurang ; sama ( gitu…
    Kalo bisa kirim yg lengkap ke email wulanlalan@gmail.com ya mas… thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.