Operácie

Zbernica i2c: EEPROM Terminál: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Opis WriteProtect
StudentMIPS (diskusia | príspevky)
Pridany algorytmus a program
Riadok 31: Riadok 31:
=== Algoritmus a program ===
=== Algoritmus a program ===


Algoritmus programu využíva toto a toto, základné funkcie sú takéto a voláma ich tuto...
Script sa skláda z viacerých časti:
Výpis kódu je nižšie...


Výber rozmeru EEPROM pamäte. Použité EEPROM vyrobca ponúka v dvoch variáciach 32Kib a 64 Kib. Mikroprocessor nevie si zistiť tento rozmer bez prepisania pamäte, teda to mu musí povedať používateľ. Reťazec načítany z scanf sa začne porovnávať, či jeho prvý symbol sa zhoduje s možnosťami vyberu alebo nie.


<tabs>
<tabs>
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="Vyber rozmeru EEPROM"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#include <avr/io.h>


int main(void)
  while(!isOptionChosen) {
{
    printf("\nChoose your EEPROM size:\n1) 32Kibit (4KiByte)\n2) 64Kibit (8KiByte)\nOption:");
   unsigned int measuredValue;
    clearInput();
    scanf("%s", uartInput);
    if(uartInput[0] == '1') {
      isEepromLarge = 0;
      isOptionChosen = 1;
    } else if(uartInput[0] == '2') {
      isEepromLarge = 1;
      isOptionChosen = 1;
    } else {
      printf("\nNot a valid answer.\n");
      isOptionChosen = 0;
    }
   }
 
</syntaxhighlight ></tab>
</tabs>
 
Hlavný interface programu funguje podobne, ale je spravený cez switch case namiesto if else. Ako je vidieť, rozmery EEPROM sú dinamické a menia sa on-the-go posunutím čisla o jeden bit isEepromLarge, ktorý sme zadavali predtým. Čítanie a zápis riadkov sú oddelnými funkciami aby sa nemisiel kód písať viackrat. Na ošetrenie situácii ked sa očakáva číslo, ale uživateľ zadá iné symboly, používa sa čistenie bufferu.
 
<tabs>
<tab name="Hlavny interface"><syntaxhighlight  lang="c++" style="background: LightYellow;">


   while (1)
   while(!exitChosen){
  {
    printf("\nChoose an option:\n1)Read a line\n2)Write a line\n3)Read all\n4)Exit\nOption:");
     /*  relax  */ 
    clearInput();
    scanf("%s", uartInput);
    printf("\n");
 
    switch (uartInput[0]) {
      case '1':
        lineAddress = 0;
        while(1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
          printf("\nChoose a line to read [1-%d]:", (128 << isEepromLarge));
          scanf("%d", &lineAddress);
          while (getchar() != '\n' && !feof(stdin));
          if (1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
            printf("\nNot a valid answer.\n");
            while (getchar() != '\n' && !feof(stdin));
          }
        }
        printf("\n");
        readLine();
        break;
 
      case '2':
        lineAddress = 0;
        while(1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
          printf("\nChoose a line to write [1-%d]:", (128 << isEepromLarge));
          scanf("%d", &lineAddress);
          if (1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
            printf("\nNot a valid answer.\n");
            while (getchar() != '\n' && !feof(stdin));
          }
        }
        printf("\nEnter text (max 32 characters):\n");
        clearInput();
        while (getchar() != '\n' && !feof(stdin));
        scanf("%32[^\n]", uartInput);
        writeLine();
        break;
 
      case '3':
        for(i = 1; i <= (128 << isEepromLarge); i++) {
          lineAddress = i;
          readLine();
        }
        break;
 
      case '4':
        exitChosen = 1;
        printf("\nGoodbye!\n");
        break;
 
      default:
        printf("\nNot a valid answer.\n\n");
        while (getchar() != '\n' && !feof(stdin));
        break;
     }
   }
   }


   return(0);
</syntaxhighlight ></tab>
</tabs>
 
Funkcie čítania a zápisu prepočitávajú user-friendly čislo riadku na reálnu adresu pamäte. Jedným príkazom vieme poslať na I2C linku iba 8 bitov, ale adresa je 16 bitová, teda musíme rozdeliť ju na dva príkazy. Na urychlenie processu čítania dát, môžeme čítať viac bajtov za sebou ak počet je menší 32, na konci musíme poslať Nak príkaz. 
 
<tabs>
<tab name="Funkcie citania a zapisu"><syntaxhighlight  lang="c++" style="background: LightYellow;">
 
void readLine(void) {
  uint16_t memAddr = (lineAddress - 1) * 32;
 
  i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);
  i2c_write(memAddr >> 8);
  i2c_write(memAddr & 0b11111111);
 
   i2c_rep_start( (EEPROM_ADDR << 1) | I2C_READ );
 
  for(k = 0; k < 32; k++) {
    if(k < 31)
      uartInput[k] = i2c_readAck();
    else
      uartInput[k] = i2c_readNak();
  }
 
  i2c_stop();
 
  uartInput[32] = '\0';
  printf("Line %3d: [%32s]\n", lineAddress, uartInput);
}
}


</syntaxhighlight ></tab>
void writeLine(void) {
<tab name="filename.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
  uint16_t memAddr = (lineAddress - 1) * 32;
#include <avr/io.h>


void adc_init(void);                                   // A/D converter initialization
  i2c_start_wait((EEPROM_ADDR << 1) | I2C_WRITE);
  i2c_write(memAddr >> 8);
  i2c_write(memAddr & 0b11111111);
 
  for(k = 0; k < 32; k++) {
    if(uartInput[k] == '\0') break;
    i2c_write(uartInput[k]);
  }
  i2c_stop();
  printf("Line %3d written successfully!\n", lineAddress);
}


unsigned int adc_read(char a_pin);
</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
</tabs>
</tabs>


Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'':
Zdrojový kód: [[Médiá:EgorBukhtiiarov2026.zip|zdrojaky.zip]]
 
Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]]


=== Overenie ===
=== Overenie ===
Riadok 73: Riadok 178:


'''Video:'''
'''Video:'''
<center><youtube>D0UnqGm_miA</youtube></center>
<center><youtube>SDEE0DPeq-A </youtube></center>


== Čo by som urobil inak ==
== Čo by som urobil inak ==

Verzia z 22:51, 8. jún 2026

Záverečný projekt predmetu MIPS / LS2026 - Egor Bukhtiiarov


Zadanie

Cieľom projektu je napisanie kodu, ktorý umožní čítanie a zápis textovych reťazcov z I2C EEPROM pomocou príkazov, posielaných cez UART.

Použitý EEPROM čip 24C64WP

Literatúra:


Pripojenie EEPROM

Použitý EEPROM ako aj iné I2C zariadenia sa pripájaju k mikrokontrolleru len dvoma vodičmi SDA pre data a SCK pre synchronizáciu časovania. Väčšina I2C sariadení majú možnosť zmeny adresy zariadenia, čo umožňujé aj použitý EEPROM.

Pre správne zapojenie datalinie SDA a SCL musia máť Pull-Up rezistory pripojené na napájacie napätie. Piny výberu adresy pripojíme na GND a tak dostaneme adresu zariadenia 000. Pin WriteControl pripojíme na GND aby neblokoval nám zápis dát.

Zapojenie EEPROM


Algoritmus a program

Script sa skláda z viacerých časti:

Výber rozmeru EEPROM pamäte. Použité EEPROM vyrobca ponúka v dvoch variáciach 32Kib a 64 Kib. Mikroprocessor nevie si zistiť tento rozmer bez prepisania pamäte, teda to mu musí povedať používateľ. Reťazec načítany z scanf sa začne porovnávať, či jeho prvý symbol sa zhoduje s možnosťami vyberu alebo nie.

  while(!isOptionChosen) {
    printf("\nChoose your EEPROM size:\n1) 32Kibit (4KiByte)\n2) 64Kibit (8KiByte)\nOption:");
    clearInput();
    scanf("%s", uartInput);
    if(uartInput[0] == '1') {
      isEepromLarge = 0;
      isOptionChosen = 1;
    } else if(uartInput[0] == '2') {
      isEepromLarge = 1;
      isOptionChosen = 1;
    } else {
      printf("\nNot a valid answer.\n");
      isOptionChosen = 0;
    }
  }

Hlavný interface programu funguje podobne, ale je spravený cez switch case namiesto if else. Ako je vidieť, rozmery EEPROM sú dinamické a menia sa on-the-go posunutím čisla o jeden bit isEepromLarge, ktorý sme zadavali predtým. Čítanie a zápis riadkov sú oddelnými funkciami aby sa nemisiel kód písať viackrat. Na ošetrenie situácii ked sa očakáva číslo, ale uživateľ zadá iné symboly, používa sa čistenie bufferu.

  while(!exitChosen){
    printf("\nChoose an option:\n1)Read a line\n2)Write a line\n3)Read all\n4)Exit\nOption:");
    clearInput();
    scanf("%s", uartInput);
    printf("\n");

    switch (uartInput[0]) {
      case '1':
        lineAddress = 0;
        while(1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
          printf("\nChoose a line to read [1-%d]:", (128 << isEepromLarge));
          scanf("%d", &lineAddress);
          while (getchar() != '\n' && !feof(stdin));
          if (1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
            printf("\nNot a valid answer.\n");
            while (getchar() != '\n' && !feof(stdin));
          }
        }
        printf("\n");
        readLine();
        break;

      case '2':
        lineAddress = 0;
        while(1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
          printf("\nChoose a line to write [1-%d]:", (128 << isEepromLarge));
          scanf("%d", &lineAddress);
          if (1 > lineAddress || lineAddress > (128 << isEepromLarge)) {
            printf("\nNot a valid answer.\n");
            while (getchar() != '\n' && !feof(stdin));
          }
        }
        printf("\nEnter text (max 32 characters):\n");
        clearInput();
        while (getchar() != '\n' && !feof(stdin));
        scanf("%32[^\n]", uartInput);
        writeLine();
        break;

      case '3':
        for(i = 1; i <= (128 << isEepromLarge); i++) {
          lineAddress = i;
          readLine();
        }
        break;

      case '4':
        exitChosen = 1;
        printf("\nGoodbye!\n");
        break;

      default:
        printf("\nNot a valid answer.\n\n");
        while (getchar() != '\n' && !feof(stdin));
        break;
    }
  }

Funkcie čítania a zápisu prepočitávajú user-friendly čislo riadku na reálnu adresu pamäte. Jedným príkazom vieme poslať na I2C linku iba 8 bitov, ale adresa je 16 bitová, teda musíme rozdeliť ju na dva príkazy. Na urychlenie processu čítania dát, môžeme čítať viac bajtov za sebou ak počet je menší 32, na konci musíme poslať Nak príkaz.

void readLine(void) {
  uint16_t memAddr = (lineAddress - 1) * 32;

  i2c_start_wait( (EEPROM_ADDR << 1) | I2C_WRITE);
  i2c_write(memAddr >> 8);
  i2c_write(memAddr & 0b11111111);

  i2c_rep_start( (EEPROM_ADDR << 1) | I2C_READ );

  for(k = 0; k < 32; k++) {
    if(k < 31)
      uartInput[k] = i2c_readAck();
    else
      uartInput[k] = i2c_readNak();
  }

  i2c_stop();

  uartInput[32] = '\0';
  printf("Line %3d: [%32s]\n", lineAddress, uartInput);
}

void writeLine(void) {
  uint16_t memAddr = (lineAddress - 1) * 32;

  i2c_start_wait((EEPROM_ADDR << 1) | I2C_WRITE);
  i2c_write(memAddr >> 8);
  i2c_write(memAddr & 0b11111111);

  for(k = 0; k < 32; k++) {
    if(uartInput[k] == '\0') break;
    i2c_write(uartInput[k]);
  }
  i2c_stop();
  printf("Line %3d written successfully!\n", lineAddress);
}

Zdrojový kód: zdrojaky.zip

Overenie

Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku hotového zariadenia.

Aplikácia.

Video:

Čo by som urobil inak

Zamyslite sa spätne nad problémom, ktorý ste riešili a napíšte, čo sa vám nepodarilo a nabudúce by ste spravili inak.


Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.