logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Solved][ATMega8] Komunikacja z EEPROM przez I2C

KubeqZ 24 Lip 2010 19:18 2273 2
REKLAMA
  • #1 8326006
    KubeqZ
    Poziom 16  
    Witam, jak w temacie mam z tym problem..otóż napisałem, bazując na dostępnych w internecie przykładach obsługę i2c w komunikacji z eepromem 24LC1025, wysyłam mu pewną liczbę a następnie ją odczytuję i wyświetlam na LCD. Niestety, komunikacja I2C nie działa - wiem to gdyż zamienienie miejscami linii SDA i SCL nie zmieniło niczego w zachowaniu programu..

    edit: zamieszczam przebiegi SDA i SCL jakie zarejestrowałem analizatorem stanów logicznych : klik!

    oto kod :
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <util/delay.h>
    #include <hd44780.c>
    
    //---------/ DEFINICJA NUMERÓW PORTÓW SDA I SCL /-------------- 
    
    #define SDA 0
    #define SCL 1
    
    #define SDA_PORT PORTB
    #define SCL_PORT PORTB
    
    //-------------/ USTAWIANIE PORTÓW NA WEJŚCIE/WYJŚCIE /-------------------- 
    #define SDA_DDR DDRB
    #define SCL_DDR DDRB
    
    #define SCL_PIN PINB
    #define SDA_PIN PINB
    
    //-------------/ NADAWANIE SYGNAŁU NA SDA /-------------------- 
    #define SET_SDA SDA_PORT |= (1<<SDA) //ustawia stan wysoki na lini SDA
    #define CLR_SDA SDA_PORT &= ~(1<<SDA) //ustawia stan niski na lini SDA
    
    //-------------/ NADAWANIE SYGNAŁU NA SCL /-------------------- 
    #define SET_SCL     SCL_PORT |= (1<<SCL) //ustawia stan wysoki na lini SCL
    #define CLR_SCL 	SCL_PORT &= ~(1<<SCL) //ustawia stan niski na lini SCL
    
    //-------------/ USTAWIANIE SDA JAKO WE/WYJ /------------------ 
    #define SDA_OUT SDA_DDR |= (1 << SDA)        // Ustawienie SDA jako wyjście
    #define SDA_IN  SDA_DDR &= ~(1 << SDA)       // Ustawienie SDA jako wejście 
    
    //-------------/ USTAWIENIE SCL JAKO WE/WYJ /------------------ 
    #define SCL_OUT SCL_DDR |= (1 << SCL)        // Ustawienie SCL jako wyjście
    #define SCL_IN  SCL_DDR &= ~(1 << SCL)       // Ustawienie SCL jako wejście 
    
    #define GET_SDA (SDA_PIN & (1 << SDA)) 
    
    void delay(void)
    {
    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); 
    }
    
    //------------/ BIT STARTU NA MAGISTRALI I2C /----------------- 
    void i2c_start(void)
    {
    
      SDA_OUT;
      SCL_OUT;
      SET_SDA;            // i2c start bit sequence
      SET_SCL;
      delay();
      CLR_SDA;
      delay();
      CLR_SCL;
    }
    
    //------------/ BIT STOPU NA MAGISTRALI I2C /----------------- 
    void i2c_stop(void)
    {
      CLR_SDA;             // i2c stop bit sequence
      delay();
      SET_SCL;
      delay();
      SET_SDA;
      delay();
    }
    
    //------------/ FUNKCJA WYSYŁAJĄCA BAJT NA SZYNE I2C/---------
    
    char i2c_write(unsigned char x)
    {
    
       unsigned char ack;
       SDA_OUT;
       for(char i=0;i<8;i++)
       {
          CLR_SCL;
          if(x&0x80) //sprawdza czy aktualny bit do wysylki jest rowny 1 czy 0
          {
             SET_SDA; //jesli jeden to wysyla jeden
             delay();
             SET_SCL;
             delay();
             CLR_SCL;
             delay();
             CLR_SDA;
          }
          else
          {
             SET_SCL; //jesli 0 to tylko tykniecie zegara
             delay();
             CLR_SCL;
             delay();
          }
          x = x<<1;
       }
       SDA_IN; //uwolnienie linii SDA
       delay();
       SET_SCL;
       delay();
       ack = GET_SDA; //sprawdzenie stanu SDA
       CLR_SCL;
       CLR_SDA;
       SDA_OUT;
       if(ack)          // Sprawdzenie bitu ACK
       {
          return 1;
       }
       
       return 0;
    } 
    
    //------------/ FUNKCJA ODCZYTUJĄCA BAJT Z SZYNY I2C/---------
    
    unsigned char i2c_read()
    {
    unsigned char count = 8, bufor = 0;          // Ustawia licznik i bufor danych
    
    SDA_IN;                                      // Ustawia PORT B na wejście
    SET_SDA;                                     // Ustawia "1' na PORT B
    do
    {
    bufor = bufor << 1;                          // Przesuwa dane buforu o 1                               
    SET_SCL;                                     // Ustawia "1" na PORT D
    delay();                                     // Opóźnienie
    if(GET_SDA) bufor++;                        // Jeżeli na szynie jest odbierana "1" to inkrementuje bufor
    CLR_SCL;                                     // Ustawia "0" na PORT D
    } while (--count);
    delay();                                // Opóźnienie
    SDA_OUT;
    CLR_SDA;
    SET_SCL;                                     
    delay();
    CLR_SCL;
    return (bufor);                              // Zwraca wartość z pamięci
    } 
    
    int main(void)
    {
    unsigned char txt;
    LCD_Initalize();
    
    LCD_Clear();
    LCD_WriteText("I2C test");
    
    _delay_ms(500);
    
    LCD_Clear();
    LCD_WriteText("ZAPIS");
    _delay_ms(500);
    
    
    LCD_Clear();
    LCD_WriteText("ODCZYT");
    _delay_ms(500);
    i2c_start();
    i2c_write(0xA0); //wysyłanie adresu + bit Write
    i2c_write(0);
    i2c_write(0);
    i2c_write(100);
    delay();
    i2c_stop();
    
    delay();
    delay();
    
    i2c_start();
    i2c_write(0xA0);
    i2c_write(0);
    i2c_write(0);
    i2c_start();
    i2c_write(0xA1);
    txt = i2c_read();
    i2c_stop();
    
    
    LCD_Clear();
    LCD_WriteText(txt);
    
    
    }


    Z góry dziękuję za pomoc ;)
  • REKLAMA
  • #3 8332639
    KubeqZ
    Poziom 16  
    Tyle że ja chcę to zrobić programowo, bez użycia sprzętowego TWI..

    Dodano po 16 [minuty]:

    Problem rozwiązany, wystarczyło dłużej poczekać na zapis do eepromu..
    Zamieszczam poprawny kod, może komuś się przyda ;)

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <util/delay.h>
    #include <hd44780.c>
    
    //---------/ DEFINICJA NUMERÓW PORTÓW SDA I SCL /-------------- 
    
    #define SDA 0
    #define SCL 1
    
    #define SDA_PORT PORTB
    #define SCL_PORT PORTB
    
    //-------------/ USTAWIANIE PORTÓW NA WEJŚCIE/WYJŚCIE /-------------------- 
    #define SDA_DDR DDRB
    #define SCL_DDR DDRB
    
    #define SCL_PIN PINB
    #define SDA_PIN PINB
    
    //-------------/ NADAWANIE SYGNAŁU NA SDA /-------------------- 
    #define SET_SDA SDA_PORT |= (1<<SDA) //ustawia stan wysoki na lini SDA
    #define CLR_SDA SDA_PORT &= ~(1<<SDA) //ustawia stan niski na lini SDA
    
    //-------------/ NADAWANIE SYGNAŁU NA SCL /-------------------- 
    #define SET_SCL     SCL_PORT |= (1<<SCL) //ustawia stan wysoki na lini SCL
    #define CLR_SCL 	SCL_PORT &= ~(1<<SCL) //ustawia stan niski na lini SCL
    
    //-------------/ USTAWIANIE SDA JAKO WE/WYJ /------------------ 
    #define SDA_OUT SDA_DDR |= (1 << SDA)        // Ustawienie SDA jako wyjście
    #define SDA_IN  SDA_DDR &= ~(1 << SDA)       // Ustawienie SDA jako wejście 
    
    //-------------/ USTAWIENIE SCL JAKO WE/WYJ /------------------ 
    #define SCL_OUT SCL_DDR |= (1 << SCL)        // Ustawienie SCL jako wyjście
    #define SCL_IN  SCL_DDR &= ~(1 << SCL)       // Ustawienie SCL jako wejście 
    
    #define GET_SDA (SDA_PIN & (1 << SDA)) 
    #define ACK 0
    #define NOACK 1
    void delay(void)
    {
    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); 
    }
    
    //------------/ BIT STARTU NA MAGISTRALI I2C /----------------- 
    void i2c_start(void)
    {
    
      SDA_OUT;
      SCL_OUT;
      SET_SDA;            // i2c start bit sequence
      SET_SCL;
      delay();
      CLR_SDA;
      delay();
      CLR_SCL;
    }
    
    //------------/ BIT STOPU NA MAGISTRALI I2C /----------------- 
    void i2c_stop(void)
    {
      CLR_SDA;             // i2c stop bit sequence
      delay();
      SET_SCL;
      delay();
      SET_SDA;
      delay();
    }
    
    //------------/ FUNKCJA WYSYŁAJĄCA BAJT NA SZYNE I2C/---------
    
    char i2c_write(unsigned char x)
    {
    
       unsigned char ack;
       SDA_OUT;
       for(char i=0;i<8;i++)
       {
          CLR_SCL;
          if(x&0x80) //sprawdza czy aktualny bit do wysylki jest rowny 1 czy 0
          {
             SET_SDA; //jesli jeden to wysyla jeden
             delay();
             SET_SCL;
             delay();
             CLR_SCL;
             delay();
             CLR_SDA;
          }
          else
          {
             SET_SCL; //jesli 0 to tylko tykniecie zegara
             delay();
             CLR_SCL;
             delay();
          }
          x = x<<1;
       }
       SDA_IN; //uwolnienie linii SDA
       delay();
       SET_SCL;
       delay();
       ack = GET_SDA; //sprawdzenie stanu SDA
       CLR_SCL;
       CLR_SDA;
       SDA_OUT;
       if(ack)          // Sprawdzenie bitu ACK
       {
          return 1;
       }
       
       return 0;
    } 
    
    //------------/ FUNKCJA ODCZYTUJĄCA BAJT Z SZYNY I2C/---------
    
    unsigned char i2c_read()
    {
    unsigned char count = 8, bufor = 0;          // Ustawia licznik i bufor danych
    
    SDA_IN;                                      // Ustawia PORT B na wejście
    SET_SDA;                                     // Ustawia "1' na PORT B
    do
    {
    bufor = bufor << 1;                          // Przesuwa dane buforu o 1                               
    SET_SCL;                                     // Ustawia "1" na PORT D
    delay();                                     // Opóźnienie
    if(GET_SDA) bufor++;                        // Jeżeli na szynie jest odbierana "1" to inkrementuje bufor
    CLR_SCL;                                     // Ustawia "0" na PORT D
    } while (--count);
    delay();                                // Opóźnienie
    SDA_OUT;
    CLR_SDA;
    SET_SCL;                                     
    delay();
    CLR_SCL;
    return (bufor);                              // Zwraca wartość z pamięci
    } 
    
    int main(void)
    {
    unsigned char txt;
    char text[8];
    LCD_Initalize();
    
    LCD_Clear();
    LCD_WriteText("I2C test");
    
    _delay_ms(500);
    
    LCD_Clear();
    LCD_WriteText("ZAPIS");
    _delay_ms(500);
    
    
    LCD_Clear();
    LCD_WriteText("ODCZYT");
    _delay_ms(500);
    i2c_start();
    i2c_write(0xA0); //wysyłanie adresu + bit Write
    i2c_write(0);
    i2c_write(0);
    i2c_write(100);
    delay();
    i2c_stop();
    
    _delay_ms(10); //czekamy aż zapisze, powinno wystarczyć 5ms ale nie zaszkodzi więcej
    
    i2c_start();
    i2c_write(0xA0);
    i2c_write(0);
    i2c_write(0);
    i2c_start();
    i2c_write(0xA1);
    txt = i2c_read();
    i2c_stop();
    
    itoa(txt, text, 10);
    LCD_Clear();
    LCD_WriteText(text);
    
    
    }
REKLAMA