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

[atmega8][c] - komunikacja z 24C16

herszt 03 Paź 2011 11:01 1647 5
REKLAMA
  • #1 9988140
    herszt
    Poziom 18  
    Witam,

    mam problem z komunikacją z 24C16 po TWI. Podczas zapisu do niego program mi się wiesza, a odczyt daje same FF. Od strony sprzętowej wygląda to następująco:
    *24C16:
    - A0,A1,A2,WP podpięte do GND.
    *ATMEGA:
    - obie linie TWI podciągnięte do +5V przez 4,7k.

    Wszystko zasilane z +5V.

    Kod wygląda następująco:

    mytwi.c
    [syntax=c]
    #include <util/twi.h>
    #include <avr/io.h>
    #include "mydelay.h"
    #include "mytwi.h"
    #include "myusart.h"
    
    
    void TWIStart( void )
    {
    	TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
    	while (!(TWCR&(1<<TWINT)));
    }
    
    void TWIStop( void )
    {
    	TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
    	while ((TWCR&(1<<TWSTO)));
    }
    
    void TWIWriteByte( unsigned char ucData )
    {
    	TWDR=ucData;
    	TWCR=(1<<TWINT)|(1<<TWEN);
    	while (!(TWCR&(1<<TWINT)));
    }
    
    unsigned char TWIReadByte( unsigned char ucAck )
    {
    	TWCR=(1<<TWINT)|(ucAck<<TWEA)|(1<<TWEN);
    	while (!(TWCR&(1<<TWINT)));
    	return TWDR;
    }
    
    void EEPROMWriteData( unsigned char ucChipAddress, unsigned char ucAddress, unsigned char ucData )
    {
    	TWIStart();
    	TWIWriteByte(ucAddress);
    	TWIWriteByte(ucData);
    	TWIStop();
    	delay_ms(15);
    }
    
    unsigned char EEPROMReadData ( unsigned char ucChipAddress, unsigned char ucAddress )
    {
    	unsigned char ucReadData;
    
    	TWIStart();
    	TWIWriteByte(ucChipAddress);
    	TWIWriteByte(ucAddress);
    	TWIStart();
    	TWIWriteByte(ucChipAddress + 1);
    	ucReadData=TWIReadByte(0);
    	TWIStop();
    	
    	return ucReadData;
    }
    [/syntax]


    main.c
    [syntax=c]
    #define F_CPU 11059200UL
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
    
    #include "libs/mydelay.h"
    #include "libs/myusart.h"
    #include "libs/mytwi.h"
    
    #define sbi(add,bit) add |= _BV(bit);
    #define cbi(add,bit) add &= ~_BV(bit);
    
    char temp1=0,temp2=0;
    char bufor[40];
    
    void zapiszDoPamieci( void )
    {
    	writeTextUSART("Zapisuje do pamieci...\n\r");
    
    	wdt_enable(WDTO_2S);
    	EEPROMWriteData(0xA0, 10,'a');
    	EEPROMWriteData(0xA0, 11,'b');
    	wdt_disable();
    }
    
    void odczytajZPamieci( void )
    {
    	writeTextUSART("Odczytuje z pamieci...\n\r");
    	wdt_enable(WDTO_2S);
    	temp1=EEPROMReadData(0xA0, 10);
    	temp2=EEPROMReadData(0xA0, 11);
    	wdt_disable();
    	
    	sprintf(bufor,"Odczytalem: %02X %02X\n\r",temp1, temp2);
    	writeTextUSART(bufor);
    }
    
    int main( void )
    {
    	wdt_disable();
    	USART_Init(MYUBRR);
    	
    	sei();
    	
    	unsigned char wybor;
    
     while(1)
     {	
    	writeTextUSART("-----------------------------------------------------\n\r");
    	writeTextUSART("a - zapis do pamieci\n\r");
    	writeTextUSART("b - odczyt z pamieci\n\r");
    	writeTextUSART("-----------------------------------------------------\n\r");
    	
    	wybor=US_RX();
    	sprintf(bufor, "Wybrales: %c\n\r", wybor);
    	writeTextUSART(bufor);
    	writeTextUSART("-----------------------------------------------------\n\r");
     
    	if (wybor=='a')
    	{
    		zapiszDoPamieci();
    	}
    	else if (wybor=='b')
    	{
    		odczytajZPamieci();
    	}
     }
    
    }
    [/syntax]


    może gdzieś popełniłem błąd? Przy zapisie specjalnie dorzuciłem watchdog'a bo tam się program wiesza - więc układ sam się resetował. Zauważyłem też, że podczas zapisu (gdy program jest już zawieszony) linia SCL pozostaje w stanie niskim jeśli to ma jakieś znaczenie.

    z góry dzięki
    pozdrawiam
    herszt
  • REKLAMA
  • #2 9988832
    GienekS
    Poziom 32  
    Kiedyś napisałem coś takiego ale dla eeprom 32
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • Pomocny post
    #3 9989439
    Andrzej__S
    Poziom 28  
    Nie zauważyłem w Twoim kodzie, żebyś ustawiał rejestr TWBR i/lub bity TWPS, więc po resecie będą one miały wartość domyślną, czyli 0. Dla takiego ustawienia, przy częstotliwości taktowania procesora 11,0592MHz, uzyskasz na linii SCL częstotliwość taktowania równą 691,2kHz, co jest wartością zbyt wysoką. Maksymalna dopuszczalna częstotliwość np. dla 24C16 Atmela to 400kHz, ale uzyskasz to raczej na niezbyt długich i niezakłóconych liniach SDA i SCL. Przy tak wysokiej prędkości transmisji może też być konieczne zmniejszenie rezystancji pull-up.
    Nie analizowałem dokładnie całości kodu, więc nie wiem, czy to jedyny błąd. Zacznij może od ustawienia prawidłowej prędkości transmisji (proponowałbym na początek zacząć poniżej 100kHz, a jak zacznie wszystko działać zawsze możesz spróbować zwiększyć).
  • REKLAMA
  • Pomocny post
    #4 9992286
    GienekS
    Poziom 32  
    Mam takie
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Chyba zaczynałem od 255 i doszedłem do 0. Zawsze możesz zwolnić tą magistralę. Ja mam kwarc 7,38MHz a EEPROM przy procesorze i oporniki 4k7 do VCC
  • REKLAMA
  • #5 9992944
    Andrzej__S
    Poziom 28  
    Przepraszam kolego GienekS, zauważyłem, że przedstawiłeś tylko fragment kodu. Nie napisałem tego jednoznacznie, ale moja odpowiedź dotyczyła kodu autora tematu (on przedstawił zdaje się cały kod i nie ma tam ustawienia prędkości transmisji).
  • #6 9993530
    herszt
    Poziom 18  
    Witam,

    faktycznie po zmianie prędkości wszystko działa jak powinno.

    dzięki za pomoc
    pozdrawiam
    herszt
REKLAMA