Both sides previous revisionPrevious revisionNext revision | Previous revision |
et:examples:communication:i2c [2015/02/27 20:45] – mikk | et:examples:communication:i2c [2020/07/20 09:00] (current) – external edit 127.0.0.1 |
---|
~~PB~~ | <pagebreak> |
====== Kahejuhtme liides TWI/I2C ====== | ====== Kahejuhtme liides TWI/I2C ====== |
//Vajalikud teadmised: | //Vajalikud teadmised: |
Kahejuhtme liides (inglise keeles //Two Wire Interface//, lühend TWI) tuntakse enamasti lühendi I<sup>2</sup>C all, mis on sama protokolli patenteeritud nimetus protokolli looja Philipsi poolt. I<sup>2</sup>C 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. | Kahejuhtme liides (inglise keeles //Two Wire Interface//, lühend TWI) tuntakse enamasti lühendi I<sup>2</sup>C all, mis on sama protokolli patenteeritud nimetus protokolli looja Philipsi poolt. I<sup>2</sup>C 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. |
| |
I<sup>2</sup>C 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õik seadmedete 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 I<sup>2</sup>C siinile ühendada palju seadmeid ilma, et nende väljundid maha põleksid. | I<sup>2</sup>C 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 I<sup>2</sup>C siinile ühendada palju seadmeid ilma, et nende väljundid maha põleksid. |
| |
[{{ :examples:communication:i2c:twi.png?580 |I2C andmesiin}}] | [{{ :examples:communication:i2c:twi.png?580 |I2C andmesiin}}] |
~~CL~~ | ~~CL~~ |
| |
Iga seade I<sup>2</sup>C 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 edastakse ü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 I<sup>2</sup>C kaabli pikkus võib olla vaid paar meetrit. | Iga seade I<sup>2</sup>C 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 I<sup>2</sup>C kaabli pikkus võib olla vaid paar meetrit. |
| |
I<sup>2</sup>C 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: | I<sup>2</sup>C 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: |
* alam võtab vastu | * 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 bit. Kui alam, mille aadressi 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 andmed. | Ü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 bit kujutab endast SDA liini madalaks tõmbamist sel hetkel, kui SCL liin on kõrge. Stop bit 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. | 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. |
| |
~~CL~~ | ~~CL~~ |
| |
// TWI katkestuste vektor, | // TWI katkestuste vektor, |
// tegeleb taustal TWI siinile kirjutamisega ning lugemisega. | // tegeleb taustal TWI siinile kirjutamisega ning lugemisega |
ISR(TWIE_TWIM_vect) | ISR(TWIE_TWIM_vect) |
{ | { |
TWI_MasterInterruptHandler(&twiMaster); | TWI_MasterInterruptHandler(&twiMaster); |
} | } |
| |
// TWIE siini käivitamine master režiimis katkestuse prioriteediga madal, | // TWIE siini käivitamine master režiimis katkestuse prioriteediga madal, |
// TWI kiirus 100 kHz 32 MHz süsteemikellaga | // TWI kiirus 100 kHz 32 MHz süsteemikellaga |
TWI_MasterInit(&twiMaster,&TWIE,TWI_MASTER_INTLVL_LO_gc, | TWI_MasterInit(&twiMaster, &TWIE,TWI_MASTER_INTLVL_LO_gc, |
TWI_BAUD(32000000, 100000)); | TWI_BAUD(32000000, 100000)); |
// Madala prioriteediga katkestuste lubamine | // Madala prioriteediga katkestuste lubamine |
PMIC.CTRL |= PMIC_LOLVLEN_bm; | PMIC.CTRL |= PMIC_LOLVLEN_bm; |
sei(); | sei(); |
| |
// Algse kellaaja määramine | // Algse kellaaja määramine |
time[0] = 0; // Aadress, kuhu kirjutatakse kellaaeg | time[0] = 0; // Aadress, kuhu kirjutatakse kellaaeg |
time[1] = 0; // Sekund | time[1] = 0; // Sekund |
time[2] = (4<<4) | 4; // Minut (44) | time[2] = (4<<4) | 4; // Minut (44) |
time[3] = (1<<4) | 1; // Tund (11) | time[3] = (1<<4) | 1; // Tund (11) |
time[4] = 3; // Nädalapäev (3) | time[4] = 3; // Nädalapäev (3) |
time[5] = (0<<4) | 5; // Kuupäev (5) | time[5] = (0<<4) | 5; // Kuupäev (5) |
time[6] = (0<<4) | 2; // Kuu (2) | time[6] = (0<<4) | 2; // Kuu (2) |
time[7] = (1<<4) | 4; // Aasta (14) | time[7] = (1<<4) | 4; // Aasta (14) |
// DS3231 kella käivitamine (kui see ei ole juba töös) | // DS3231 kella käivitamine (kui see ei ole juba töös) |
TWI_MasterWrite(&twiMaster,DS3231,time,8); | TWI_MasterWrite(&twiMaster, DS3231, time, 8); |
| |
// Lõputu tsükkel | // Lõputu tsükkel |
while (true) | while (1) |
{ | { |
// TWI siini DS3231 registritest kellaaja uuesti lugemine | // TWI siini DS3231 registritest kellaaja uuesti lugemine |
TWI_MasterWriteRead(&twiMaster,DS3231,(uint8_t *)0x00,1,7); | TWI_MasterWriteRead(&twiMaster,DS3231,(uint8_t *)0x00,1,7); |
| |
// Vastuse ootamine | // Vastuse ootamine |
while (twiMaster.status != TWIM_STATUS_READY); | while (twiMaster.status != TWIM_STATUS_READY); |
| |
// Registritest saadud informatsiooni kellaks ja kuupäevaks teisendamine | // Registritest saadud informatsiooni kellaks ja kuupäevaks teisendamine |
seconds = ((twiMaster.readData[0]>>4)*10) + (twiMaster.readData[0] & 0x0F); | seconds = ((twiMaster.readData[0]>>4)*10) + (twiMaster.readData[0] & 0x0F); |
minutes = ((twiMaster.readData[1]>>4)*10) + (twiMaster.readData[1] & 0x0F); | minutes = ((twiMaster.readData[1]>>4)*10) + (twiMaster.readData[1] & 0x0F); |
hours = ((twiMaster.readData[2]>>4)*10) + (twiMaster.readData[2] & 0x0F); | hours = ((twiMaster.readData[2]>>4)*10) + (twiMaster.readData[2] & 0x0F); |
date = ((twiMaster.readData[4]>>4)*10) + (twiMaster.readData[4] & 0x0F); | date = ((twiMaster.readData[4]>>4)*10) + (twiMaster.readData[4] & 0x0F); |
month = ((twiMaster.readData[5]>>4)*10) + (twiMaster.readData[5] & 0x0F); | month = ((twiMaster.readData[5]>>4)*10) + (twiMaster.readData[5] & 0x0F); |
year = ((twiMaster.readData[6]>>4)*10) + (twiMaster.readData[6] & 0x0F); | year = ((twiMaster.readData[6]>>4)*10) + (twiMaster.readData[6] & 0x0F); |
| |
// Kella LCD ekraanil kuvamine | // Kella LCD ekraanil kuvamine |
sprintf(buff,"%02d:%02d:%02d %02d.%02d.20%02d", | sprintf(buff,"%02d:%02d:%02d %02d.%02d.20%02d", |
hours,minutes,seconds,date,month,year); | hours,minutes,seconds,date,month,year); |
lcd_gfx_goto_char_xy(2,2); | lcd_gfx_goto_char_xy(2,2); |
lcd_gfx_write_string(buff); | lcd_gfx_write_string(buff); |