Kahejuhtme liides TWI/I2C

Vajalikud teadmised: [HW] Kontrollermoodul, [HW] Kombomoodul, [AVR] Katkestused,
[LIB] Kahejuhtmeliides TWI, [LIB] Graafiline LCD

Teooria

Kahejuhtme liides (inglise keeles Two Wire Interface, lühend TWI) tuntakse enamasti lühendi I2C all, mis on sama protokolli patenteeritud nimetus protokolli looja Philipsi poolt. I2C on akronüüm inglisekeelsele mõistele Inter-Integrated Circuit mis tähendab, et see liides on loodud skeemisiseseks kasutamiseks. Kõnekeeles kasutatakse enamasti mugavamaid “ii-ruut-c” või “ii-kaks-c” väljendeid.

I2C liides kasutab kahte liini, millest üks on kahesuunaline andmeliin (inglise keeles Serial Data line, lühend SDA) ning teine taktisignaali (inglise keeles Serial Clock line, lühend SCL) liin. Kõigi seadmete väljundid siinil peavad olema avatud-neeluga (kollektoriga) ning mõlemal liinil peavad olema pull-up takistid (skeemil R1 ja R2). Selline ühendamine lubab ühele I2C siinile ühendada palju seadmeid ilma, et nende väljundid maha põleksid.

I2C andmesiin

Iga seade I2C siinil omab unikaalset aadressi mis olenevalt seadmest on 7 või 10-bitine. Levinumad sagedused taktsignaali liinil on 10 kHz (inglise keeles Low-speed mode), 100 kHz (inglise keeles Standard mode), 400 kHz (inglise keeles Fast mode). Uuemad standardid lubavad ka suuremaid kiirusi kuid need on vähem levinud. Taktsignaali sagedusest tuleneb ka andmesidekiirus kuna iga taktiga edastatakse üks bitt informatsiooni. Maksimaalne seadmete arv ühel siinil tuleneb aadressruumist ning lisandunud elektrilisest mahtuvusest. Maksimaalne siini mahtuvus on 400 pF, mis tähendab, et maksimaalne I2C kaabli pikkus võib olla vaid paar meetrit.

I2C protokollis jagunevad seadmed rolli järgi ülemateks ning alamateks (inglise keeles master ja slave). Maksimaalset ülemate ega alamate arvu ei ole määratud ja seadmed võivad vahepeal oma rolli muuta. Defineeritud on neli erinevat siini operatsiooni:

  • ülem saadab
  • ülem võtab vastu
  • alam saadab
  • alam võtab vastu

Ülem on algselt üldjuhul saatmise režiimis, saates kõigepealt start biti, millele järgneb 7-bitine alammooduli aadress ning lugemise/kirjutamise bitt. Kui alam, mille aadress oli sõnumis siinil eksisteerib, vastab see ACK bitiga (hoiab siini madalas asendis). Pärast seda ülem valib, kas jääb kuulama või saadab alamale uusi andmeid.

Start bitt kujutab endast SDA liini madalaks tõmbamist sel hetkel, kui SCL liin on kõrge. Stop bitt on defineeritud kui SDA liini kõrgeks liigutamine sel hetkel, kui SCL liin on kõrge. Kõik ülejäänud nivoovahetused peavad toimuma sel hetkel, kui SCL liin on madal.

Kirjutamine ja lugemine toimub bait haaval, igale õnnestunud baidivahetusele peab järgnema ACK signaal selle poolt, kelle poole andmeid saadeti. Kui andmevahetus on lõppenud saadab juhtmoodul, kas Stop biti või uue Start biti koos aadressiga.

Praktika

RTC moodul DS3231

I2C on Atmeli kontrolleris nimetatud TWI mooduliks. Suurem osa TWI protokolli tööst teeb ära mikrokontrolleri riistvara, kuid sellegipoolest on vaja ka tarkvarateeki, kus on realiseeritud funktsioonid siinile kirjutamise ja siinilt lugemise hõlbustamiseks.

Näites on ära toodud reaalaja kellamooduli (inglise keeles Real Time Clock, lühend RTC) DS3231 kasutamine Kodulabor III põlvkonna kontrolleriga. Reaalajakell omab väikese Li-patarei näol autonoomset toidet ja peale esmast aja seadistamist ei ole hiljem enam eraldi vaja aega algväärtustada, kuna reaalajakell loendab aega iseseisvalt ja seda ka ilma välise toiteta mitme aasta vältel. Seega peale algväärtustamist võib sama moodulit kasutada ainult kella täpseks lugemiseks ning ei pea muretsema aja täpsuse või algoleku määramise pärast.

// Kodulabori RTC mooduli DS3231 näidisprogramm
// Moodul on ühendatud PORTE TWI siinile: SDA - PE0, SCL - PE1
#include <homelab/pin.h>
#include <homelab/module/lcd_gfx.h>
#include <homelab/xmega/clksys_driver.h>
#include <homelab/xmega/twi_master_driver.h>
#include <avr/interrupt.h>
 
// DS1307 TWI aadress
#define DS3231 0b1101000
 
// TWI ülemmooduli defineerimine
TWI_Master_t twiMaster;
 
// TWI katkestuste vektor, 
// tegeleb taustal TWI siinile kirjutamisega ning lugemisega
ISR(TWIE_TWIM_vect)
{
  TWI_MasterInterruptHandler(&twiMaster);
}
 
// Põhiprogramm
int main(void)
{
  char buff[30];
  uint8_t time[8];
  uint8_t seconds = 0, minutes, hours;
  uint8_t date, month, year;
 
  // LCD ekraani seadistamine
  lcd_gfx_init();
  lcd_gfx_write_string("I2C RTC Module");
 
  // TWIE siini käivitamine master režiimis katkestuse prioriteediga madal,
  // TWI kiirus 100 kHz 32 MHz süsteemikellaga
  TWI_MasterInit(&twiMaster, &TWIE,TWI_MASTER_INTLVL_LO_gc,
                                TWI_BAUD(32000000, 100000));
  // Madala prioriteediga katkestuste lubamine
  PMIC.CTRL |= PMIC_LOLVLEN_bm;
  sei();
 
  // Algse kellaaja määramine
  time[0] = 0;          // Aadress, kuhu kirjutatakse kellaaeg
  time[1] = 0;          // Sekund
  time[2] = (4<<4) | 4; // Minut (44)
  time[3] = (1<<4) | 1; // Tund (11)
  time[4] = 3;          // Nädalapäev (3)
  time[5] = (0<<4) | 5; // Kuupäev (5)
  time[6] = (0<<4) | 2; // Kuu (2)
  time[7] = (1<<4) | 4; // Aasta (14)
 
  // DS3231 kella käivitamine (kui see ei ole juba töös)
  TWI_MasterWrite(&twiMaster, DS3231, time, 8);
 
  // Lõputu tsükkel
  while (1)
  {
    // TWI siini DS3231 registritest kellaaja uuesti lugemine
    TWI_MasterWriteRead(&twiMaster,DS3231,(uint8_t *)0x00,1,7);
 
    // Vastuse ootamine
    while (twiMaster.status != TWIM_STATUS_READY);
 
    // Registritest saadud informatsiooni kellaks ja kuupäevaks teisendamine
    seconds = ((twiMaster.readData[0]>>4)*10) + (twiMaster.readData[0] & 0x0F);
    minutes = ((twiMaster.readData[1]>>4)*10) + (twiMaster.readData[1] & 0x0F);
    hours   = ((twiMaster.readData[2]>>4)*10) + (twiMaster.readData[2] & 0x0F);
    date    = ((twiMaster.readData[4]>>4)*10) + (twiMaster.readData[4] & 0x0F);
    month   = ((twiMaster.readData[5]>>4)*10) + (twiMaster.readData[5] & 0x0F);
    year    = ((twiMaster.readData[6]>>4)*10) + (twiMaster.readData[6] & 0x0F);
 
    // Kella LCD ekraanil kuvamine
    sprintf(buff,"%02d:%02d:%02d  %02d.%02d.20%02d",
            hours,minutes,seconds,date,month,year);
    lcd_gfx_goto_char_xy(2,2);
    lcd_gfx_write_string(buff);
    _delay_ms(100);
  }
}
et/examples/communication/i2c.txt · Last modified: 2020/07/20 09:00 by 127.0.0.1
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0