Operácie

Zbernica i2c: EEPROM: Rozdiel medzi revíziami

Z SensorWiki

(Vytvorená stránka „==='''K. Zbernica i2c: EEPROM'''=== Prečítajte obsah predloženej pamäti EEPROM a zobrazte na PC. Obrázok:i2c_M24C02.jpg '''Literatúra:''' * [http://www.s...“)
 
(1. Schéma zapojenia)
 
(14 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 1: Riadok 1:
==='''K. Zbernica i2c:  EEPROM'''===
 
  
Prečítajte obsah predloženej pamäti EEPROM a zobrazte na PC.
+
== Oboznámenie so zbernicou i2c ==
  
[[Obrázok:i2c_M24C02.jpg]]
 
  
'''Literatúra:'''  
+
'''Úlohy:'''
* [http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00001163.pdf M24C02 Datasheet]
+
 
 +
# Pripojte k procesoru pamäť podľa schémy zapojenia
 +
# Schému upravte tak, aby adresa zariadenia bola ?? - určí cvičiaci
 +
# Zapíšte na prvé pamäťové miesto (adresa 0x00) znak 'A'
 +
# Prečítajte, či je znak správne zapísaný
 +
# Prečítajte obsah celej pamäte a vypíšte ho na terminál PC
 +
# Zapíšte do pamäte  10 bytov nejakej informácie a zistite, ako dlho trvá zápis jedného byte, t.j. aká veľká musí byť prestávka medzi jednotlivými zápismi.
 +
 
 +
 
 +
==='''Literatúra'''===
 +
 
 +
* Official I2C Specification Version 6 http://www.nxp.com/documents/user_manual/UM10204.pdf
 +
* Official List of assigned NXP / Philips I2C addresses http://www.diolan.com/downloads/i2c-address-allocation-table.pdf
 
* Mitchell Kahn: ''[http://ap.urpi.fei.stuba.sk/mmp/doc/prog_i2c.pdf Programming the i2c interface].'' Dr. Dobb's Journal, June 1992.
 
* Mitchell Kahn: ''[http://ap.urpi.fei.stuba.sk/mmp/doc/prog_i2c.pdf Programming the i2c interface].'' Dr. Dobb's Journal, June 1992.
 
* [http://www.nongnu.org/avr-libc/user-manual/group__twi__demo.html Example using the two-wire interface (TWI)]. AVRlibc demo projects.
 
* [http://www.nongnu.org/avr-libc/user-manual/group__twi__demo.html Example using the two-wire interface (TWI)]. AVRlibc demo projects.
Riadok 12: Riadok 22:
  
  
<source lang="c">
+
=== Datasheets ===
  
#include <avr/interrupt.h> 
 
#include <stdlib.h>
 
#include <avr/io.h>
 
#include <util/delay.h>
 
#include <util/twi.h>
 
#include <stdio.h>
 
  
//#include "lcd.h"
+
* [http://www.atmel.com/images/doc0180.pdf AT24C02 EEPROM memory]
#include "Uart_ch.h"
+
* [http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00001163.pdf M24C02 Datasheet]
  
unsigned char RD_EEprom(unsigned char adr_RAM);
 
void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo);
 
void obsluha_Stav_Aut_I2C(void);
 
  
 +
[[Obrázok:i2c_M24C02.jpg]] [[Obrázok:i2c_M24C02_pinout.jpg]]
  
  
#define ADR_IC_WR 0xA0  // EEPROM Adresa IC+WR
 
#define ADR_IC_RD 0xA1  // EEPROM Adresa IC+RD
 
  
 +
=== 1. Schéma zapojenia ===
  
 +
[[Súbor:i2c_schematic.png|400px|center]][[Súbor:i2c_breadboard.png|400px|center]]
  
volatile  unsigned char buffer_I2C[10]; // buffer pre obsluhu I2C
 
 
  
 +
Správnosť zapojenia si môžete vyskúšať programom [[Médiá:i2c_scan.ino]] - nájde všetky obvody pripojené na zbernici.
 +
Nachádza sa aj priamo vo vývojovom prostredí Arduino, pozri Examples -> Wire -> i2c_scan.
  
 +
=== 2. Device address ===
  
 +
[[Súbor:i2c_address.png|400px|center]]
  
FILE mystdout_Uart = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE);
 
  
  
void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo)
 
{ // nastavenie globalnych premennych
 
  
buffer_I2C[0]=adr_IC; // Adr obvodu + wr
 
buffer_I2C[1]=adr_pocitadlo;     // Nastavenie Adresneho citaca 24LC04 , Adresa (z ktorej citam)/(do ktorej zapisujem)
 
// buffer_I2C[1]=<obsah>; // zapisovane data, byte,-ty
 
 
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition
 
// a odovzdanie riadenia "preruseniu od I2C"
 
obsluha_Stav_Aut_I2C();
 
  
}
+
=== 3. Inicializácia ===
  
  
 +
Pri tvorbe programu pre modul budeme využívať už hotovú knižnicu <code>i2cmaster</code> dostupnú odtiaľto http://senzor.robotika.sk/mmp/src/i2c/
  
unsigned char RD_EEprom(unsigned char adr_RAM)
+
Najprv je potrebné zbernicu inicializovať:
{
+
<source lang="c">
// nastavenie globalnych premennych
 
  
buffer_I2C[0]=ADR_IC_RD; // Adr obvodu + rd
+
        i2c_init();                                       // initialize I2C library
buffer_I2C[1]=adr_RAM;     // Sem vrati obsah z nastavenej adresy 24LC04
 
  
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition
+
</source>
// a odovzdanie riadenia "preruseniu od I2C"
 
obsluha_Stav_Aut_I2C();
 
return(buffer_I2C[1]);
 
 
}
 
  
// tato funkcia vyuziva globalne premenne
 
// buffer_I2C[x]
 
// Wr_data - tato premenna nadobuda vyznam az pri komunikacii s konkretnou premennou
 
//          vid. "instrukcny subor" I2C periferie
 
  
// implementovany instrukcny subor pre seriovu EEPROM max 256 byte
 
// S|adr_IO+wr|<AC>|P                -- nastavenie adresneho citaca pamate EEPROM
 
// {nie je implementova} S|adr_IO+wr|<AC>|data|P          -- zapisanie dat na nastavenu adresu pamate EEPROM
 
// S|adr_IO+rd|data|P                -- precitanie jedneho bytu z aktualne nastavenej adresy pamate EEPROM
 
//                                      obsah adresneho citaca sa inkrementne
 
  
void obsluha_Stav_Aut_I2C(void)
 
{ unsigned char pom_St_Aut=0;
 
 
 
nav:while ((TWCR & _BV(TWINT)) == 0);  /* wait for transmission */
 
  
    {  pom_St_Aut=TWSR & 0xf8; // precitaj stav
+
=== 4. Zápis ===
    printf(" %02x",pom_St_Aut);
 
switch(pom_St_Aut)
 
{ case TW_START:// = 0x08 // odvysielany start
 
  case TW_REP_START:// = 0x10 // odvysielany repeated start
 
                TWDR = buffer_I2C[0];// Adr+wr/rd, adresa IO
 
  TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
 
  break;
 
 
 
  case TW_MT_SLA_ACK: //        0x18  Data byte has been tramsmitted and ACK received
 
                TWDR = buffer_I2C[1]; // tu konkretne, nastavenie Adreseho citaca pamate.
 
  TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
 
  break;
 
  
  case TW_MT_DATA_ACK: //        0x28  Data byte has been tramsmitted and ACK received
+
Zápis je jednoduchší, preto ním začneme:
  TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
 
return; //  tento riadok v preruseni vypadne
 
  break;
 
  
  case TW_MR_SLA_ACK: //  0x40  // Data byte has been tramsmitted and NACK received
+
<source lang="c">
  TWCR = _BV(TWINT) | _BV(TWEN) ; // clear interrupt to start transmission
 
  break;
 
  
  case TW_MR_DATA_NACK: // 0x58 // Data byte has been tramsmitted and ACK received
+
      // zapis hodnotu 0x41 ('A') to EEPROM address 00 (Byte Write)  
      buffer_I2C[1]= TWDR;     // Vycitaj jeden byte z  24LC04.  Adresny citac sa posunie
 
      TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); // send stop condition
 
return; // tento riadok v preruseni vypadne
 
  break;
 
  
  default:
+
    i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);     // 1: set device address and write mode
  TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
+
    i2c_write(0x00);                                     // 2: write address = 0
return; // tento riadok v preruseni vypadne
+
    i2c_write(0x41);                                     // 3: write value 0x41 to EEPROM
  break;
+
    i2c_stop();                                         // 4: set stop conditon = release bus
}
 
}
 
goto nav; // toto v preruseni vypadne
 
}
 
  
 +
</source>
  
 +
<div style='text-align: center;'>
 +
  [[Súbor:i2c_write.png|600px|center]]<br>
 +
''Postupnosť pre zápis hodnoty z EEPROM pamäte.''
 +
</div>
  
 +
=== 5. Čítanie ===
  
int main(void)
+
Čítanie vyžaduje trocha viac krokov, pretože najprv musíme smerom do EEPROM nastaviť adresu, z ktorej chceme čítať a potom obrátime smer komunikácie a počkáme na data z pamäti.
{ unsigned char znak;
 
  
unsigned int i=0;
+
<source lang="c">
unsigned char poc_adresa_EEPROM=0;
 
 
  
 +
  /*  Precitame hodnotu zapisanu v predchadzajucom kroku z EEPROM addresy 0  */
  
inituart(); // inicializacia UARTU                      // inicializacia v 4-bitovom rezime
+
    i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);     // 1: set device address and write mode
                   
+
    i2c_write(0x00);                                      // 2: write address = 0
  
//  sei();                   // Enable ALL interrupts                     
+
    i2c_rep_start( (EEPROM_ADDR << 1) | I2C_READ );       // 3: set device address and read mode
  
// ini I2C
+
    val = i2c_readNak();                                 // 4: read one byte from EEPROM
+
    i2c_stop();                                           // 5: stop
 
 
  TWCR = _BV(TWEN); /* send start condition */
 
  TWBR = 72; // fi2c= fosc/(16 +2(preddelic=00=> 1)(<TWBR>)) = 100kHz
 
  TWSR=1;
 
}
 
  
 +
</source>
  
// TODO: to USART
+
Program je samozrejme vhodné doplniť o zobrazenie prečítanej hodnoty v termináli cez sériové rozhranie.
/* ************************************************************ */
 
  
stdout = &mystdout_Uart;
+
<div style='text-align: center;'>
 +
  [[Súbor:i2c_read.png|600px|center]]<br>
 +
''Postupnosť pre čítanie hodnoty z EEPROM pamäte.''
 +
</div>
  
 +
Jednoduchý program na prečítanie 1 byte z pamäte pre Arduino s využitím knižnice [https://www.arduino.cc/reference/en/libraries/i2c_eeprom/ I2C_EEPROM] je tu:
  
printf("Nastavenie adresy EEPROM = %02x \n\r",poc_adresa_EEPROM);
+
<source lang="c">
WR_EEprom(ADR_IC_WR,poc_adresa_EEPROM);
+
#include <I2C_eeprom.h>
  
 +
#define MAXBYTES 2048/8        // it's only 2Kbit
 +
#define DEVICEADDRESS (0x50)  // the address of your EEPROM
  
printf("\n\r\rVypis EEPROM: \n\r");
+
I2C_eeprom eeprom(DEVICEADDRESS,MAXBYTES);
  
// vypisme prvych 10 znakov
+
byte value;
    while (i<10) //256)// kapacita pamate 256 znakov, bytov,
+
byte adresa = 0x00;
{  
+
 
znak = RD_EEprom(ADR_IC_RD); // obsah adresneho citaca EEPROM sa automaticky inkrementuje
+
void setup()
if(znak==0xff)i=256; // vymazane pametove miesto
+
{
{
+
  Serial.begin(9600);
printf("   %02d %02x %c\r",i++,znak,znak);
+
  Serial.println("*** Reading memory content: ***");
}
+
 
       
+
  Wire.begin();
}
+
   eeprom.begin();
+
 
for(;;); // a cakam napr. na  "RESET"
+
  value = eeprom.readByte(adresa);
 +
  Serial.print((char)value);  
 
   
 
   
 +
  Serial.println("\nDone...");
 
}
 
}
 +
 +
void loop()
 +
{
 +
  // Nothing to do during loop
 +
}
 +
 
</source>
 
</source>
  
  
[[Category:DVPS]]
+
 
 +
[[Category:DVPS]][[Category:AVR]][[Category:MMP]][[Category:I2C]][[Category:MIPS]]

Aktuálna revízia z 07:08, 26. apríl 2024

Oboznámenie so zbernicou i2c

Úlohy:

  1. Pripojte k procesoru pamäť podľa schémy zapojenia
  2. Schému upravte tak, aby adresa zariadenia bola ?? - určí cvičiaci
  3. Zapíšte na prvé pamäťové miesto (adresa 0x00) znak 'A'
  4. Prečítajte, či je znak správne zapísaný
  5. Prečítajte obsah celej pamäte a vypíšte ho na terminál PC
  6. Zapíšte do pamäte 10 bytov nejakej informácie a zistite, ako dlho trvá zápis jedného byte, t.j. aká veľká musí byť prestávka medzi jednotlivými zápismi.


Literatúra


Datasheets


I2c M24C02.jpg I2c M24C02 pinout.jpg


1. Schéma zapojenia

I2c schematic.png
I2c breadboard.png


Správnosť zapojenia si môžete vyskúšať programom Médiá:i2c_scan.ino - nájde všetky obvody pripojené na zbernici. Nachádza sa aj priamo vo vývojovom prostredí Arduino, pozri Examples -> Wire -> i2c_scan.

2. Device address

I2c address.png



3. Inicializácia

Pri tvorbe programu pre modul budeme využívať už hotovú knižnicu i2cmaster dostupnú odtiaľto http://senzor.robotika.sk/mmp/src/i2c/

Najprv je potrebné zbernicu inicializovať:

         i2c_init();                                       // initialize I2C library



4. Zápis

Zápis je jednoduchší, preto ním začneme:

       // zapis hodnotu  0x41 ('A') to EEPROM address 00 (Byte Write) 

     i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);     // 1: set device address and write mode
     i2c_write(0x00);                                     // 2: write address = 0
     i2c_write(0x41);                                     // 3: write value 0x41 to EEPROM
     i2c_stop();                                          // 4: set stop conditon = release bus
I2c write.png

Postupnosť pre zápis hodnoty z EEPROM pamäte.

5. Čítanie

Čítanie vyžaduje trocha viac krokov, pretože najprv musíme smerom do EEPROM nastaviť adresu, z ktorej chceme čítať a potom obrátime smer komunikácie a počkáme na data z pamäti.

  /*  Precitame hodnotu zapisanu v predchadzajucom kroku z EEPROM addresy 0   */

     i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);      // 1: set device address and write mode
     i2c_write(0x00);                                      // 2: write address = 0

     i2c_rep_start( (EEPROM_ADDR << 1) | I2C_READ );       // 3: set device address and read mode

     val = i2c_readNak();                                  // 4: read one byte from EEPROM
     i2c_stop();                                           // 5: stop

Program je samozrejme vhodné doplniť o zobrazenie prečítanej hodnoty v termináli cez sériové rozhranie.

I2c read.png

Postupnosť pre čítanie hodnoty z EEPROM pamäte.

Jednoduchý program na prečítanie 1 byte z pamäte pre Arduino s využitím knižnice I2C_EEPROM je tu:

#include <I2C_eeprom.h>

#define MAXBYTES 2048/8         // it's only 2Kbit
#define DEVICEADDRESS (0x50)   // the address of your EEPROM

I2C_eeprom eeprom(DEVICEADDRESS,MAXBYTES);

byte value;
byte adresa = 0x00;

void setup()
{
  Serial.begin(9600);
  Serial.println("*** Reading memory content: ***");
  
  Wire.begin();
  eeprom.begin();
  
  value = eeprom.readByte(adresa);
  Serial.print((char)value); 
 
  Serial.println("\nDone...");
}

void loop()
{
  // Nothing to do during loop
}