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

Atmega32 + zew. eeprom 24C16 na I2C wysyłanie tekstu

dawid512 04 Mar 2008 20:09 2248 12
REKLAMA
  • #1 4873572
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Witam serdecznie forumowiczów!

    Mam mały problem z magistrala I2C i zewnętrzną pamięcią 24C16.
    Komunikację mam opanowaną i jak narazie wiem jak wysłać i odebrać jakąś zmienną typu byte.

    Teraz sprawa się komplikuje gdyż chciałbym wysyłać jakiś tekst do pamięci ale zaznaczam bez używania jakiegoś gotowego programatora do pamieci gdyż tekst wysyłałbym za pomocą RS-232 np. z terminala a nie za kazdym razem wkladal kostke do programatora.

    Wie ktoś może jak to zrobić? Dodam że próbowałem już zamieniać zmienna typu byte na stringa ale kompilator wyrzuca mi bledy.

    A to jest program do wysyłania i odbierania znaków z zew. pamieci:
    
    
    $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 = Porta.7
    Config Sda = Porta.6
    
    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 = 174                                        'adres zapisu
    Const Addressr = 175                                        'adres odczytu
    
    Dim Adres As Byte , Value As Byte
    
    Cls
    cursor off
    
    Call Write_eeprom(1 , 123)                                  'Zapisz dane pod    (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 zapisu
        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 e
       I2cstart                                                      'powtórz start
       I2cwbyte Addressr                                        'adres odczytu
       I2crbyte Value , Nack                                    'odczytane dane(koniec odczytu)
       I2cstop                                                  'stop
    End Sub
    
    


    Pozdrawiam Dawid.
  • REKLAMA
  • Pomocny post
    #2 4874235
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    dawid512 napisał:
    ...Wie ktoś może jak to zrobić? Dodam że próbowałem już zamieniać zmienna typu byte na stringa ale kompilator wyrzuca mi bledy...

    Sposobów na to , jest nie mniej niż ze setka.Możesz "wycinać" po jednej literce ze stringa , możesz "naddeklarować"(Overlay) stringa tablicą typu byte , użyć Mid i ... t.d.
    Np.
    
    Dim S As String * 10
    Dim Addr As Word
    Dim Bb As Byte
    
    S = "Piotr"
    
    Addr = Varptr(s)
    Bb = Inp(addr)
    I2cwbyte Bb        'literka "P" powędruje do eepromu
    '...
    

    Reszta należy do Ciebie :)

    Piotrek
  • REKLAMA
  • #3 4874778
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Dziękuje za podpowiedź :) ale wpisywanie literka po literce to jednak masa kodu :(. Wyodrębnianie poprzez mid i val też jest żmudne a może ta tablica o której wspomniałeś? Jak to zrealizowac?
  • REKLAMA
  • #4 4875358
    Fyszo
    Poziom 37  
    Posty: 3987
    Pomógł: 223
    Ocena: 115
    Ale wszystko w pętli... jaka masa kodu?
  • #5 4875644
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    dawid512 napisał:
    ... a może ta tablica o której wspomniałeś? Jak to zrealizowac?

    Bardzo prosto.
    
    Dim S As String * 10
    Dim Sb(11) As Byte At S Overlay
    

    Teraz tablica Sb , zajmuje ten sam obszar pamięci co string S.
    Mam nadzieję , że potrafisz wysłać do eepromu kolejne elementy tablicy :?:
    I pamiętaj o zerze na końcu łańcucha S :!:

    Piotrek
  • REKLAMA
  • #6 4876583
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Zrobiłem tak :
    
    Dim S As String * 10
    Dim Sb(11) As Byte At S Overlay
    
    S = "1234567890"
    
    Value = Sb(1)
    
    Cls
    
    Locate 1 , 1
    Lcd "Zapisuje dane"
    
    Call Write_eeprom(1 , Value)                                'Zapisz dane pod adresem(adres, dane)
    
    Wait 2
    
    
    Call Read_eeprom(1 , Value) : Locate 1 , 1 : Lcd Value      'Odczytaj je
    
    Cls
    Locate 1 , 1 : Lcd "odczytalem: " ; Value


    ale na wyswietlaczu pojawia sie liczba 49 :( ale dlaczego?
  • #7 4876845
    Fyszo
    Poziom 37  
    Posty: 3987
    Pomógł: 223
    Ocena: 115
    To zero na końcu stringa to nie znak '0' tylko liczba 0 (null). (to do przykładu który był i najwidoczniej zniknął)
  • #8 4876875
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    dawid512 napisał:
    ...ale na wyswietlaczu pojawia sie liczba 49 :( ale dlaczego?

    Do eepromu zapisałeś kod ASCII znaku "1" , więc na wyświetlacz musisz to wysłać jako kod ASCII , czyli Lcd Chr(Value).Nieznajomość typów zmiennych - ot co ;)

    Piotrek

    PS
    A z tym zerem na końcu łańcucha , jest tak jak napisał Fyszo
  • #9 4877855
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Zrobiłem tak:
    
    Dim S As String * 10
    Dim Sb(11) As Byte At S Overlay
    
    S = "1234567890"
    
    Value = Sb(1)
    
    Cls
    
    Locate 1 , 1
    Lcd "Zapisuje dane"
    
    Call Write_eeprom(1 , Value)                                'Zapisz dane pod adresem(adres, dane)
    
    Wait 2
    
    
    Call Read_eeprom(1 , Value)                                 'Odczytaj je
    
    Cls
    Locate 1 , 1 : Lcd "odczytalem: " ; Chr(value)


    Tylko teraz nie wiem jak zrobić żeby wpisywało mi po kolei każdy znak ze zmiennej S do eepromu a potem wyswietlilo mi caly napis ze zmiennej S na wyswietlaczu zamiast wyswietlania literka po literce.

    A z tym zerem to chodzi o to zeby wysylac znak po znaku do eepromu w sumie 10 znakow a potem wyslac jeszce sam bajt o wartsci zero? W ten sposob?
  • Pomocny post
    #10 4878293
    Fyszo
    Poziom 37  
    Posty: 3987
    Pomógł: 223
    Ocena: 115
    Z tym zerem jest tak, że jak tworzysz zmienna typu string (null-terminated) to ma ona automatycznie zakończenie w postaci 0 na końcu. Lecz jeśli zrobisz tablicę znaków i chcesz uzywać jako stringa to musisz dodać 0 na końcu (żeby było kompatybilne ze stringiem). Czyli każdy string = text+0 a tablica bedzie u ciebie tylko text, dlatego aby swobodnie przenosić stringa do tablicy i odwrotnie musisz w tablicy dokładać 0 na końcu - dla zgodności. W większości przypadków można to pominąć, ale trzeba o tym ciągle pamiętać, że za pomocą tablicy nie dopisaliśmy 0 w epromie, nie mozna tego wczytać jako stringa (albo pamiętać o dodaniu 0).
  • #11 4879783
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Teraz już rozumiem :) ale czy sposob ktory podalem do wysylania tego zera jest poprawny?

    Jeszcze odnosnie mojego poprzedniego postu: jak zrobic cos w rodzaju inkrementacji danych z tablicy tzn nie chodzi mi tutaj o zwiekszanie wartosci jakiejs danej z tablicy tylko o automatyczne wgrywanie danych do eepromu z kolejnych elementow tablicy. Prosto mowiac jest jakas petla np for lub do loop w ktorej za kazdym razem zostaje wyslany nastepny znak z tablicy az do momentu gdy w tablicy zabraknie znakow albo okreslimy ilosc z gory .

    Value = Sb(1) 


    Najprosciej mowiac chce zwiekszac te jedynke w nawiasie. A moze wystarczy zwykle incr obok niej?

    Przepraszam ze pisze lopatologicznie ale chce to dobrze wam wyjasnic i sam zrozumiec z tego jak najwiecej.
  • Pomocny post
    #12 4880508
    Fyszo
    Poziom 37  
    Posty: 3987
    Pomógł: 223
    Ocena: 115
    Po prostu zamiast tej '1' w nawiasach wstaw zmienna ('pozycja') i zwiększając 'pozycje' zmieniasz sobie kolejne znaki. To wszystko w pętli aż do napotkania s(pozycja)=0. Niestety nie napisze ci kodu bo karierę z basiciem zakonczyłem na c64-basic i dos-qbasic dosyć dawno temu. Aha, w każdym innym języku string z założenia jest tablicą znaków i tam nie trzeba się bawić w przerzucanie znaków string<>tablica.
  • #13 4880665
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Wielki dzięki :) że też na to nie wpadłem... tylko nie bardzo wiem o co chodzi tutaj: s(pozycja)=0. Kiedy to co napisales jest rowne zero? A moze lepiej bedzie jak po wyslaniu np. 10 znakow z tablicy wyzeruje pozycje?

    Mam jeszce jedno pytanko: mam pamiec 24C16. Zastanawiam sie ile takich pojedynczych znakow z tablicy moge w niej umiescic i czy kazdy znak musze wysylac na nastepny adres zaczynajc od 1?

    Przykład:

    Call Write_eeprom(1 , Value)
    Call Write_eeprom(2 , Value)
    Call Write_eeprom(3 , Value)
    


    Dodano po 44 [sekundy]:

    Zrobiłem cos takiego:

    
    
    $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 = Porta.7
    Config Sda = Porta.6
    
    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 = 174                                        'adres zapisu
    Const Addressr = 175                                        'adres odczytu
    
    Dim Adres As Byte , Value As Byte
    Dim Pozycja As Byte
    Dim I As Byte
    Dim S As String * 10
    Dim Sb(11) As Byte At S Overlay
    
    I = 1
    Pozycja = 1
    S = "123456789a"
    
    Sb(11) = 0
    
    
    For I = 1 To 10
    
    Value = Sb(pozycja)
    
    Cursor Off
    Cls
    Locate 1 , 1
    Lcd "Zapisuje dane"
    
    Call Write_eeprom(1 , Value)                                'Zapisz dane pod adresem(adres, dane)
    Wait 2
    
    Call Read_eeprom(1 , Value)                                 'Odczytaj je
    
    Cls
    Locate 1 , 1 : Lcd "odczytalem: " ; Chr(value)
    Wait 2
    Incr Pozycja
    Next I
    
    
    End
    
    
    
    
    'Zapis
    Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
        I2cstart                                                'start
        I2cwbyte Addressw                                       'adres zapisu eepromu
        I2cwbyte Adres                                          'adres komorki
        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 eepromu
       I2cwbyte Adres                                           'adres komorki
       I2cstart                                                 'powtórz start
       I2cwbyte Addressr                                        'adres odczytu
       I2crbyte Value , Nack                                    'odczytane dane
       I2cstop                                                  'stop
    End Sub


    Program wyswietla na wyswietlaczu po kolei to co mialem w stringu S.
    Odnosnie mojego poprzedniego postu: czy wraz z inkrementowaniem pozycji mam tez inkrementowac adres pod ktory wysylam dane z tablicy?
    Jesli jest tak jak mysle to ile max moze wynosic wartosc inkrementowanego adresu? Oczywiscie pomijajac to ze jest to bajt czyli max 255.

Podsumowanie tematu

✨ Dyskusja dotyczy problemu zapisu i odczytu tekstu do zewnętrznej pamięci EEPROM 24C16 za pomocą mikrokontrolera Atmega32 i magistrali I2C. Użytkownik opanował podstawową komunikację bajtową, ale ma trudności z przesyłaniem całych łańcuchów znaków (stringów) bez użycia programatora, chcąc wysyłać dane przez RS-232 z terminala. Zaproponowano wykorzystanie nakładania (overlay) tablicy bajtów na zmienną typu string, co pozwala na dostęp do poszczególnych znaków jako bajtów. Wskazano, że zapis i odczyt pojedynczych znaków ASCII wymaga konwersji na kod ASCII przy wyświetlaniu (np. funkcja Chr()). Omówiono znaczenie zakończenia łańcucha znakiem null (0) dla poprawnego odczytu stringów z EEPROM. Zaproponowano implementację pętli, która iteruje po kolejnych elementach tablicy znaków, wysyłając je do pamięci EEPROM aż do napotkania znaku null lub określonej długości. Poruszono także kwestie adresowania kolejnych bajtów w pamięci EEPROM, zaczynając od adresu 1 i inkrementując adres dla każdego znaku. Przykładowy kod w BASCOM-AVR pokazuje deklaracje, konfigurację portów I2C, LCD oraz funkcje zapisu i odczytu bajtów z EEPROM.
Wygenerowane przez model językowy.
REKLAMA