Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATMEGA][BASCOM] problem z eepromem 24c16 na I2C

28 Mar 2009 15:52 3683 9
  • Poziom 9  
    Mam następujący problem, cały dzień szukam po necie materiałów na temat obsługi eemproma 24c16 po I2C, udało mi się napisać/przerobić programik ale sprzęt nie działa prawidłowo.

    Dane zapisane do eeproma i odczytane bywają różne, wnioskujętak na podstawie tego co mi wyświetla na LCD, niektóre liczby są takie same, niektóre inne. Na dodatek po zresetowaniu te liczby się zmieniają, czyli jak dla wpisanej 2 do pamięci wyświetliło 0 , to później np. wyświetli 1 (po resecie).

    Dodatkowe informacje: jesli chodzi o adres to znalazłem informację, że nóżki A0 A1 i A2 pozostają niepodłączone dla tego eeproma, próbowałem na podłączonych i niepodłączonych...
    Podłączone są rezystory podciągające na liniach SCL i SDA 4,7k.

    Program mikrokontrolera (używam ATMEGA32):


    Code:

    $regfile = "m32def.dat"                                     'informuje kompilator o pliku
           'dyrektyw mikrokontrolera
    $crystal = 16000000                                         'informuje kompilator
           'o częstotliwości oscylatora
           'taktującego mikrokontroler
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2
           Config Scl = Portc.1                                 'konfigurowanie linii SCL
    Config Sda = Portc.0
    Dim D_w As Byte , D_r As Byte

    Cls
    Cursor Off

                                          'assign the SDA line to PORTD.1

    D_w = 0
    Do
    '********** write byte to EEPROM ***************************************************
    I2cstart                                                    'generate start
    I2cwbyte &B1010_0000                                        'send device address
    I2cwbyte 0                                                  'H adress of EEPROM
    I2cwbyte 0                                                  'L adress of EEPROM
    I2cwbyte D_w                                                'data to EEPROM
    I2cstop                                                     'stop condition
    Waitms 100

    '********** read byte from EEPROM **************************************************
    I2cstart                                                    'generate start
    I2cwbyte &B1010_0000                                        'send device adsress
    I2cwbyte 0                                                  'H address of EEPROM
    I2cwbyte 0                                                  'L address of EEPROM
    I2cstart                                                    'repeated start
    I2cwbyte &B1010_0001                                        'slave address (read)
    I2crbyte D_r , Nack                                         'read byte from EEPROM
    I2cstop
    Waitms 100                                                  'generate stop
    Cls
    Lcd "D_w= "
    Lcd D_w                                                     'show byte on LCD
    Lowerline
    Lcd "D_r= "
    Lcd D_r
    Waitms 1000
    Incr D_w
    Loop
    End
  • Poziom 32  
    Podaje sprawdzony program do obsługi tej pamięci:
    Code:

    $regfile = "m32def.dat"
    $crystal = 8000000


    Config Lcdbus = 4
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Pb.4 , Db5 = Pb.5 , Db6 = Pb.6 , Db7 = Pb.7 , E = Pb.3 , Rs = Pb.2


    Config Scl = Portc.0
    Config Sda = Portc.1

    Declare Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
    Declare Sub Read_eeprom(byval Adres As Byte , Value As Byte)

    Const Addressw = 160                                        'adres zapisu
    Const Addressr = 161                                        'adres odczytu

    Dim Adres As Byte , Value As Byte


    Cls

    Call Write_eeprom(1 , 4)                                    'Zapisz dane pod adresem(adres, dane)


    Call Read_eeprom(1 , Value) : Locate 1 , 1 : Lcd Value      'Odczytaj je



    'Zapis
    Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
        I2cstart                                                'start
        I2cwbyte Addressw                                       'adres pamieci
        I2cwbyte Adres                                          'adres
        I2cwbyte Value                                          'wartosc do wyslania
        I2cstop                                                 'stop
        Waitms 10                                               'czekaj 10ms
    End Sub


    'Odczyt
    Sub Read_eeprom(byval Adres As Byte , Value As Byte)
       I2cstart                                                 'start
       I2cwbyte Addressw                                        'adres zapisu
       I2cwbyte Adres                                           'adres
       I2cstart                                                 'powtórz start
       I2cwbyte Addressr                                        'adres odczytu
       I2crbyte Value , Nack                                    'odczytane dane
       I2cstop                                                  'stop
    End Sub
  • Poziom 38  
    Spróbuj z Instrukcją CONFIG I2CDELAY
  • Poziom 9  
    Cytat:
    I2cwbyte &B1010_0000


    To zapis binarny dopuszczalny przez BASCOM (spotkałem w kilku przykładach), można też oczywiście zapisać adres szesnastkowo i dziesiętnie (160).
    Rozumiem Twoje zdziwienie, bo sam tak zareagowałem... ale kompiluje się bez problemu.

    Poniżej zameszczam zmodyfikowany program... jednak też nie działa prawidłowo... niektóre liczby wyświetlane nie zgadzają się

    Wydaje mi się, że są jakieś przekłamania przy odczycie

    Większość wyświetlanych cyfr się zgadza, ale czasami wyświetla: 96 i 64, 4 i 0, 5 i 4, itp.

    Próbowałem również z opcją config i2cdelay ale nie pomaga, odkomentowanie dwóch linii i podanie tam prędkości/zmiana też nie pomaga.

    Może ktoś ma możliwość sprawdzenia tego na własnym sprzęcie??

    Code:
    $regfile = "m32def.dat"
    
    $crystal = 16000000

    $baud = 19200
    $hwstack = 70
    $swstack = 70
    $framesize = 60

    '$lib "I2C_TWI.LBX" 'Setting up i2c hardware bus
    'Config Twi = 400000                                         'Hardware i2c bus speed
    Config I2cdelay = 5
    Config Scl = Portc.0
    Config Sda = Portc.1

    Config Lcdbus = 4
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Pc.4 , Db5 = Pc.5 , Db6 = Pc.6 , Db7 = Pc.7 , E = Pc.3 , Rs = Pc.2




    Declare Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
    Declare Sub Read_eeprom(byval Adres As Byte , Value As Byte)

    Const Addressw = 160                                        'adres zapisu
    Const Addressr = 161                                        'adres odczytu

    Dim Adres As Byte , Value As Byte , A As Byte
    A = 0
    Cls
    Lcd "startujemy"
    Waitms 1000
    Do
    Cls

    Call Write_eeprom(1 , A) 'Zapisz dane pod adresem(adres, dane)
    Lcd A

    Call Read_eeprom(1 , Value) 'Odczytaj je
    Lowerline
    Lcd Value
    Waitms 1000
    Incr A
    Loop


    'Zapis
    Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
        I2cstart                                                'start
        I2cwbyte Addressw                                       'adres pamieci
        I2cwbyte Adres                                          'adres
        I2cwbyte Value                                          'wartosc do wyslania
        I2cstop                                                 'stop
        Waitms 1000                                             'czekaj 1000ms
    End Sub


    'Odczyt
    Sub Read_eeprom(byval Adres As Byte , Value As Byte)
       I2cstart                                                 'start
       I2cwbyte Addressw                                        'adres zapisu
       I2cwbyte Adres                                           'adres
       I2cstart                                                 'powtórz start
       I2cwbyte Addressr                                        'adres odczytu
       I2crbyte Value , Nack                                    'odczytane dane
       I2cstop                                                  'stop
    End Sub
  • Poziom 32  
    U mnie działa dobrze. Na pewno masz te 16MHz? Jakie masz rezystory podciągające?
  • Poziom 9  
    rezystory są zamontowane w płytce i są to 4,7k

    jeszcze jedna uwaga:
    zrobiłem przeróbkę i ustawiłem wartość A=4 i zakomentowałem Incr A

    czyli wysyła cały czas 4 i odczytuje z pamięci.

    Wyniki:
    co jakiś czas otrzymuję w wyniku: 4 i 0,
    może moje 16MHz ma jakiśwpływ... ale nie jestem w stanie go wymontować z tej płytki i wymienić.

    Pisałeś że działa u Ciebie. A wgrałeś mój program?? Czy testowałeś tylko na tym, który raz wysyła i wyświewtla i kończy?

    I jeszcze pytanie do pinów A0,A1,A2 podłączone masz do masy czy pozostawione wolne?? Bo u mnie to i tak nic nie zmienia,a nie wiem jak ma być prawidłowo (widziałem w jakiśnotach i przykładach, że te linie pozostawiano niepodłączone)
  • Poziom 32  
    Testowałem twój program. Piny A0,A1,A2 mają być nie podłączone. Pytając o 16MHz miałem na myśli czy fuse bity dobrze ustawione.
  • Poziom 9  
    jeszcze nie wgłębiałem się dokładnie w fuse-bity, nie znam sięw tej tematyce jeszcze

    raczej są wporządku, płytkę kupiłem razem z atmegą która miała je już ustawione poza tym wszystko inne chodziło po 1wire czy PCF8574 po I2C

    Co do programu to zrobiłem zmianę i teraz działą OK:

    Code:

    Const Addressw = 162                                        'adres zapisu
    Const Addressr = 163


    zmieniłem adresy na kolejną stronę, 24C16 ma łacznie 8 stron tzn. z adresami zapisu: 160, 162, 164,... itd.

    Nie wiem tylko dlaczego z adresem 160 chodzi źle? Może z kością coś nie tak

    Dodano po 2 [godziny] 28 [minuty]:

    najprawdopodobniej błąd pojawiał się dlatego, że nie nadążał z odczytem po I2C, więc dodałem opóźnienia waitms 30 (dla waitms 10 wystąpił błąd), i teraz działa OK

    Code:

    Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
        I2cstart                                                'start
    ...............
    ...............
    ...............                                       'wartosc do wyslania
        I2cstop                                                 'stop
        Waitms 30                                               'czekaj 1000ms
    End Sub


    'Odczyt
    Sub Read_eeprom(byval Adres As Byte , Value2 As Byte)
       I2cstart                                                 'start
    ....................
    ...................
    ....................                                   'odczytane dane
       I2cstop
       Waitms 30                                                'stop
    End Sub
  • Poziom 26  
    Moim zdaniem tylko opóźnienie przy zapisie powinno wystarczyć i to mniejsze np. 10ms. Przy odczycie bez opóźnienia lub dużo mniejsze 1...5ms.