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)
Pridane Overenie, Co by som urobil inak
 
(Jedna medziľahlá úprava od rovnakého používateľa nie je zobrazená.)
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(!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;
    }
  }
 
</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);


   while (1)
   i2c_rep_start( (EEPROM_ADDR << 1) | I2C_READ );
   {
 
     /*  relax  */ 
   for(k = 0; k < 32; k++) {
     if(k < 31)
      uartInput[k] = i2c_readAck();
    else
      uartInput[k] = i2c_readNak();
   }
   }


   return(0);
   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 ===


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.
Pripojil som EEPROM k mikroprocessoru pomocou uvedených schém. Na zariadení fizicky nič sa nemení, teda do videa prikládam len prácu s UART terminálom.
Na konci uvádzame fotku hotového zariadenia.  


[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
[[Súbor:Arduino-24C64WP-nometa.png|400px|thumb|center|Aplikácia.]]


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


== Čo by som urobil inak ==
== Č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.  
Rád by som sa dozvediel ako sa majú robiť podobné ConsoleUI lebo vidím, že môj kód je viac if-else, než niečo čo by málo štrukturu. Ešte by som chiel nájsť lepší spôsob práci s user-input hodnotami, teraz to vyzerá chaotické.  
 


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


[[Category:AVR]] [[Category:MIPS]]
[[Category:AVR]] [[Category:MIPS]]

Aktuálna revízia z 23:08, 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

Pripojil som EEPROM k mikroprocessoru pomocou uvedených schém. Na zariadení fizicky nič sa nemení, teda do videa prikládam len prácu s UART terminálom.

Aplikácia.

Video:

Čo by som urobil inak

Rád by som sa dozvediel ako sa majú robiť podobné ConsoleUI lebo vidím, že môj kód je viac if-else, než niečo čo by málo štrukturu. Ešte by som chiel nájsť lepší spôsob práci s user-input hodnotami, teraz to vyzerá chaotické.