Operácie

Zbernica i2c: EEPROM: Rozdiel medzi revíziami

Z SensorWiki

(3. Zápis)
Riadok 46: Riadok 46:
 
[[Súbor:i2c_address.png|400px|center]]
 
[[Súbor:i2c_address.png|400px|center]]
  
== '''Software''' ==
+
 
 +
 
 +
 
 +
 
 +
=== 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/
 
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/
 
'''1. Inicializácia'''
 
  
 
Najprv je potrebné zbernicu inicializovať:
 
Najprv je potrebné zbernicu inicializovať:
Riadok 60: Riadok 62:
 
</source>
 
</source>
  
'''
 
2. Čítanie z A/D prevodníka'''
 
  
Potom môžeme prečítať hodnotu na analógovom vstupe č. 3, na ktorom je pripojený trimer:
 
  
<div style='text-align: center;'>
 
[[File:MIPS_8591_ReadValue.png]]<br>
 
''Postupnosť pre čítanie hodnoty z obvodu 8591.''
 
</div>
 
  
<source lang="c">
+
=== 4. Zápis ===
/*    value = AnlogRead-From-PCF8591(channel);  */
 
  
        i2c_start( PCF8591_ADDR << 1 | I2C_WRITE);        // set device address and write mode
+
[[Súbor:i2c_write.png|600px|center]]
        i2c_write(channel);                              // which channel want to read
 
        i2c_stop();
 
        i2c_rep_start(PCF8591_ADDR << 1 | I2C_READ);      // repeated start for reading
 
        i2c_readAck();                                    // read dummy byte
 
value = i2c_readNak();                                    // read Analog value
 
        i2c_stop();
 
</source>
 
  
 +
Zápis je jednoduchší, preto ním začneme:
  
'''3. Zápis na analógový výstup'''
+
<source lang="c">
  
A napokon prečítanú hodnotu zapíšeme na analógový výstup, takže zmenu priamo uvidíme na pripojenej zelenej LED dióde.
+
      // zapis hodnotu  0x41 ('A') to EEPROM address 00 (Byte Write)
  
<div style='text-align: center;'>
+
    i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);     // set device address and write mode
[[File:MIPS_8591_WriteValue.png]]<br>
+
    i2c_write(0x00);                                     // write address = 0
''Postupnosť pre zápis hodnoty do obvodu 8591.''
+
    i2c_write(0x41);                                     // write value 0x41 to EEPROM
</div>
+
    i2c_stop();                                         // set stop conditon = release bus
 
 
<source lang="c">
 
/*    AnalogWrite-To-PCF8591(value);  */
 
 
        i2c_start((PCF8591_ADDR << 1 | I2C_WRITE));       // set device address and write mode
 
        i2c_write(CONTROL BYTE);                         // set analog output active
 
        i2c_write(value);                                 // write the required Analog Output value (0-255)
 
        ...                                              // multiple write possible
 
        i2c_stop();                                       // set stop conditon = release bus                      
 
  
 
</source>
 
</source>
  
Program je samozrejme vhodné doplniť o zobrazovanie veličín buď na LCD displeji, alebo v termináli cez sériové rozhranie.  
+
             
 +
<div style='text-align: center;'>
 +
[[File:EEPROM_ReadValue.png]]<br>
 +
''Postupnosť pre čítanie hodnoty z EEPROM pamäte.''
 +
</div>
  
Pri vytváraní riadiaceho slova by vám mal napomôcť tento obrázok z datasheetu:
 
  
 
<div style='text-align: center;'>
 
<div style='text-align: center;'>
[[File:MIPS_8591_Register.png|500px]]<br>
+
[[File:EEPROM_WriteValue.png]]<br>
''Obsadenie riadiaceho registra obvodu 8591.''
+
''Postupnosť pre zápis hodnoty do obvodu 8591.''
 
</div>
 
</div>
  
  
=== 3. Zápis ===
 
  
[[Súbor:i2c_write.png|600px|center]]
 
  
=== 4. Čítanie ===
+
=== 5. Čítanie ===
  
 
[[Súbor:i2c_read.png|600px|center]]
 
[[Súbor:i2c_read.png|600px|center]]
Riadok 123: Riadok 103:
 
[[Súbor:i2c_readRandom.png|400px|center]]
 
[[Súbor:i2c_readRandom.png|400px|center]]
  
 
+
 
 
 
 
 
 
 
 
 
 
 
 
  
 
<source lang="c">
 
<source lang="c">
  
#include <avr/interrupt.h>  
+
  /* Precitame hodnotu zapisanu v predchadzajucom kroku z EEPROM addresy 0  */
#include <stdlib.h>
 
#include <avr/io.h>
 
#include <util/delay.h>
 
#include <util/twi.h>
 
#include <stdio.h>
 
  
//#include "lcd.h"
+
    i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);    // set device address and write mode
#include "Uart_ch.h"
+
 +
    i2c_write(0x00);                        // write address = 5
 +
    i2c_rep_start(Dev24C02+I2C_READ);      // set device address and read mode
  
unsigned char RD_EEprom(unsigned char adr_RAM);
+
    val = i2c_readNak();                   // read one byte from EEPROM
void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo);
+
    i2c_stop();
void obsluha_Stav_Aut_I2C(void);
 
  
 +
    for(;;);
  
 +
</source>
  
#define ADR_IC_WR 0xA0  // EEPROM Adresa IC+WR
+
Program je samozrejme vhodné doplniť o zobrazenie prečítanej hodnoty v termináli cez sériové rozhranie.  
#define ADR_IC_RD 0xA1  // EEPROM Adresa IC+RD
 
 
 
 
 
 
 
volatile  unsigned char buffer_I2C[10]; // buffer pre obsluhu I2C
 
 
 
 
 
 
 
 
 
 
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();
 
 
 
}
 
 
 
 
 
 
 
unsigned char RD_EEprom(unsigned char adr_RAM)
 
{
 
// nastavenie globalnych premennych
 
 
 
buffer_I2C[0]=ADR_IC_RD; // Adr obvodu + rd
 
buffer_I2C[1]=adr_RAM;     // Sem vrati obsah z nastavenej adresy 24LC04
 
 
 
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition
 
// 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
 
    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
 
  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
 
  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
 
      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:
 
  TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
 
return; // tento riadok v preruseni vypadne
 
  break;
 
}
 
}
 
goto nav; // toto v preruseni vypadne
 
}
 
 
 
 
 
 
 
 
 
int main(void)
 
{ unsigned char znak;
 
 
 
unsigned int i=0;
 
unsigned char poc_adresa_EEPROM=0;
 
 
 
 
 
 
inituart(); // inicializacia UARTU                      // inicializacia v 4-bitovom rezime
 
                   
 
 
 
//  sei();                    // Enable ALL interrupts                     
 
 
 
// ini I2C
 
 
 
 
  TWCR =  _BV(TWEN); /* send start condition */
 
  TWBR = 72; // fi2c= fosc/(16 +2(preddelic=00=> 1)(<TWBR>)) = 100kHz
 
  TWSR=1;
 
}
 
 
 
 
 
// TODO: to USART
 
/* ************************************************************ */
 
 
 
stdout = &mystdout_Uart;
 
 
 
 
 
printf("Nastavenie adresy EEPROM = %02x \n\r",poc_adresa_EEPROM);
 
WR_EEprom(ADR_IC_WR,poc_adresa_EEPROM);
 
 
 
 
 
printf("\n\r\rVypis EEPROM: \n\r");
 
 
 
// vypisme prvych 10 znakov
 
    while (i<10) //256)// kapacita pamate 256 znakov, bytov,
 
{
 
znak = RD_EEprom(ADR_IC_RD); // obsah adresneho citaca EEPROM sa automaticky inkrementuje
 
if(znak==0xff)i=256; // vymazane pametove miesto
 
{
 
printf("  %02d %02x %c\r",i++,znak,znak);
 
}
 
       
 
}
 
 
for(;;);  // a cakam napr. na  "RESET"
 
 
}
 
</source>
 
  
  
 
[[Category:DVPS]][[Category:AVR]][[Category:MMP]][[Category:I2C]][[Category:MIPS]]
 
[[Category:DVPS]][[Category:AVR]][[Category:MMP]][[Category:I2C]][[Category:MIPS]]

Verzia zo dňa a času 19:05, 13. apríl 2023

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.

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

I2c write.png

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);     // set device address and write mode
     i2c_write(0x00);                                     // write address = 0
     i2c_write(0x41);                                     // write value 0x41 to EEPROM
     i2c_stop();                                          // set stop conditon = release bus


Súbor:EEPROM ReadValue.png
Postupnosť pre čítanie hodnoty z EEPROM pamäte.


Súbor:EEPROM WriteValue.png
Postupnosť pre zápis hodnoty do obvodu 8591.



5. Čítanie

I2c read.png
I2c readRandom.png


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

     i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);     // set device address and write mode
 
     i2c_write(0x00);                        // write address = 5
     i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode

     val = i2c_readNak();                    // read one byte from EEPROM
     i2c_stop();

     for(;;);

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