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

Jak wysłać bajt do EEPROM 24C04 I2C w C na At89C2051 z zegarem 16MHz?

flapo213 17 Gru 2005 16:01 2113 7
REKLAMA
  • #1 2092056
    flapo213
    Poziom 21  
    Posty: 566
    Pomógł: 35
    Ocena: 10
    Słuchajcie mam taki problem nie mogę w języku C dojść ładu z procedurą wysyłającą bajt do pamięci 24C04. Procesor taktuje zegarem 16MHz. W Bascomie wszystko pięknie śmiga a w C nie i nie wiem dlaczego. Poniżej zamieszczam procedury pomóżcie bo już 2-gi dzień siedzę.

    #include <reg51.h>


    sbit dioda1 = P3^3;
    sbit scl = P1^3;
    sbit sda = P1^4;

    #define nop() ACC++

    void delayi2c(void)
    {
    nop();
    nop();
    }

    void i2c_start(void) //Inicjacja magistrali Start I2C
    {
    sda=scl=1;
    delayi2c();
    sda=0;
    delayi2c();
    scl=0;
    }

    bit i2c_stop(void) //Wysłanie sekwencji Stop na I2C
    {
    sda=0;
    delayi2c();
    scl=1;
    delayi2c();
    sda=1;
    delayi2c();
    return (~sda);
    }

    bit i2c_send(unsigned char byte) //Wysylanie bitu na magistralę I2C
    {
    unsigned char bitcount=9;
    bit temp;

    do
    {
    scl=0;
    sda=byte&0x80;
    byte=(byte<<1)+1;
    delayi2c();
    scl=1;
    delayi2c();
    }while(--bitcount);
    temp=sda;
    scl=0;
    return(temp);
    }

    void main(void)

    {
    dioda1=0;
    i2c_start();
    i2c_send(0xA0);
    i2c_send(0x01);
    i2c_send(0x08);

    i2c_stop();
    delayms(20);
    if(g==0)
    {
    dioda1=1;
    delays(6);
    dioda1=0;
    delays(3);
    }
    while(1);
    }

    Natomiast procedura w Bascomie jest ok


    $regfile = "89C2051.dat"

    $crystal = 16000000
    P1 = 0
    P3 = 0

    Config 1wire = P3.4

    Config Scl = P1.3

    Config Sda = P1.4



    Do

    I2cstart
    I2cwbyte 160
    I2cwbyte 3
    I2cwbyte 24
    I2cstop
    Waitms 10

    Loop

    Pomóżcie bo już analizowałem na wszystkie sposoby i nie wiem co może być, czasy ustawiałem itd
  • REKLAMA
  • #2 2092575
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 240
    A mógłbyś napisać co znaczy że "nie śmiga"?
  • REKLAMA
  • #3 2093098
    flapo213
    Poziom 21  
    Posty: 566
    Pomógł: 35
    Ocena: 10
    Sprawa ma się tak, próbuję wpisać w którąś komórkę pamięci jakąś daną i program w baskomie to robi natomiast ten fragment który zamieściłem w jezyku C niestety nie działa, próbowałem nawet dawać po każdej procedurze g=i2c_send() dawać instrukcję sprawdzającą poprawność przesyłu i za każdym razem bit acknowledge jest 0 czyli ok, dla sprawdzenia dałem raz adres różny od A0 czyli np B0 i potwierdzenia nie było. Więc gdzieś popełniam jak sądzę czeski błąd jakąś głupawkę w C obracam się dosyć nieźle ale dopiero od niedawna programuję w tym języku 8051 i AVR. Proszę pomóżcie gdzie się czepić i szukać bo nóżki procka już są takie sobie. Pozdrawiam
  • #4 2093538
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 240
    Mam kilka sugestii:
    - czy aby nie za szybko wysyłasz (2 nop`y to może być za mało).
    - po co po przesunięcie bitów dodajesz 1? (to tak z ciekawości).
  • REKLAMA
  • #5 2093669
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    elektryk napisał:
    Mam kilka sugestii:
    - czy aby nie za szybko wysyłasz (2 nop`y to może być za mało).
    - po co po przesunięcie bitów dodajesz 1? (to tak z ciekawości).

    Tez się na tą "1" zastanawiałem i doszedłem do wniosku , że to na potrzeby 9-go bitu , by napewno był "1" , co umożliwi "wykrycie" ACK slave'a.Tak mi sie wydaje , a nawet jestem tego pewien ;)

    Piotrek
  • #6 2093762
    Nemo
    Poziom 31  
    Posty: 2078
    Pomógł: 9
    Ocena: 72
    Musisz wytaktować 9 cykl zegarowy i zanim odczytasz bit, ustawić port w 89C2051 na "1". Inaczej nigdy nie odczytasz bitu ACK.

    Czyli po nadaniu 8 bitu sprowadzasz SCK do 0, potem ustawiasz SDA na "H" (1) i znów SCK na 1, wtedy odczytujesz ACK (najlepiej instrukcją JB, bo wyjdzie gdy na SDA będzie 0) i jedziesz dalej. :)

    A, przy odczycie pamiętaj o powtórzonym starcie!

    Co do szybkości nie obawiałbym się za bardzo. Przy 24MHz pamiątki śmigają u mnie bez żadnych opóźnień. No, ale to są 24C512...

    Pozdrawiam.
  • #7 2093793
    flapo213
    Poziom 21  
    Posty: 566
    Pomógł: 35
    Ocena: 10
    9 bit i to dodanie 1 jest tak ja słusznie zauważono do wykrycia bitu ACK. Natiomiast z "nop-ami" to próbowałem kilka kombinacji, to 2 to 4 to 6 to nawet 11 i efek dalej ten sam. Ja odczytuje pamięć to jedynie same FF widzę i nic więcej. Już nie wiem gdzie moge błądzić. Próbowałem nawet dać zamieast 9 to 8 na bitcounter i nic nic, efekt dalej ten sam. Analizowałem w symulatorze przebiegi po kolei rysowałem wykresy i niby wszystko się zgadza ze standardem opisywanym w specyfikacji I2C i pamięci 24C04. Może ktoś ma jakieś przetesotowane procedury. Nie wiem gdzie szukać błędu bo we wszystkich 3 instrukcjach i2c_send Potwierdzenie Ack jest 0 czyli tak jakby pamięć dobrze reagowała a efektu nie widać. Dzięki za zainteresowanie, no pierwszy raz w programowaniu napotykam takie trudności nawet napisałem program w asemblerze tak jak uczyli na studiach i zdziwice się też działa jak program w bascomie tylko z c mam problemy. Już brak mi pomysłów.
  • REKLAMA
  • #8 2094661
    flapo213
    Poziom 21  
    Posty: 566
    Pomógł: 35
    Ocena: 10
    Problem rozwiązano. W baskomie na początku zerowałem obydwa porty, a na jednej nóżce kiedyś podpiołem do nóżki wp któreś wyprowadzenie procesora i to blokowało zapis potwierdzenia były ale nie mógł zapisać bo na wp było 1. Pamiętajcie o wp żeby albo wisiało w powietrzu albo dajcie na nie 0. Pozdrawiam i dzięki

Podsumowanie tematu

✨ Problem dotyczył wysyłania bajtu do pamięci EEPROM 24C04 przez magistralę I2C za pomocą mikrokontrolera At89C2051 taktowanego zegarem 16 MHz w języku C. Autor miał działający kod w Bascomie, lecz implementacja w C nie zapisywała danych poprawnie, mimo że bit potwierdzenia ACK był odczytywany jako prawidłowy (0). Dyskusja zwróciła uwagę na kilka aspektów: konieczność odpowiedniego taktowania sygnałów (opóźnienia), prawidłowe ustawienie linii SDA na "1" podczas odczytu 9. bitu (ACK), oraz poprawne generowanie sygnału start i stop na magistrali I2C. Kluczowym rozwiązaniem okazało się zwrócenie uwagi na linię WP (Write Protect) pamięci 24C04, która była podłączona do pinu procesora i blokowała zapis, mimo że potwierdzenie ACK było obecne. Po odłączeniu lub ustawieniu WP na 0 zapis danych zaczął działać poprawnie. Wskazano także, że dodawanie "1" po przesunięciu bitów w funkcji wysyłania jest celowe, by zapewnić 9. bit do wykrycia ACK. Opóźnienia w postaci kilku instrukcji nop nie były krytyczne, a problem leżał w sprzętowym podłączeniu linii WP.
Wygenerowane przez model językowy.
REKLAMA