Operácie

Zbernica i2c: EEPROM: Rozdiel medzi revíziami

Zo stránky SensorWiki

Balogh (diskusia | príspevky)
Bez shrnutí editace
Balogh (diskusia | príspevky)
 
(13 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:AVR]][[Category:MMP]][[Category:I2C]][[Category:MEMS]]
 
[[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



1. Schéma zapojenia


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



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

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.


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
}