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 + PCF8583: Odczyt sekund przez I2C w C nie działa, wyświetla 0

slimak281 17 Sty 2007 15:27 6495 6
REKLAMA
  • #1 3453571
    slimak281
    Poziom 11  
    Posty: 86
    Pomógł: 2
    Ocena: 1
    Witam, mam problem z PCF, podlaczylem uklad wg schematu :
    ATmega8 + PCF8583: Odczyt sekund przez I2C w C nie działa, wyświetla 0

    Chce sie nauczyc programowo obslugiwac i2c, dlatego nie korzystam ze sprzetowego i2c ATmegi. przesylam moj program. Juz mnie szlag trafia, nie wiem gdzie mam blad. Chcialem odczytac z rejestru sekud jakas wartosc i nic nie dziala pokazuje mi 0 na wyswietlaczu.
    Dodam ze korzystam z wewnetrznego kwarcu 1MHz.
    
    // I2C
    #define I2CDir DDRB
    #define I2COut PORTB
    #define I2CIn  PINB
    //
    #define SDA PB7
    #define SCL PB6
    //
    #define SET_SDA I2COut |= (1 << SDA)
    #define CLR_SDA I2COut &= ~(1 << SDA)
    //
    #define SET_SCL I2COut |= (1 << SCL)
    #define CLR_SCL I2COut &= ~(1 << SCL)
    //
    #define SDA_OUT I2CDir |= (1 << SDA)
    #define SDA_IN  I2CDir &= ~(1 << SDA)
    //
    #define SCL_OUT I2CDir |= (1 << SCL)
    #define SCL_IN  I2CDir &= ~(1 << SDA)
    //
    #define GET_SDA (I2CIn & (1 << SDA))
    //
    #define ACK 0
    #define NOACK 1
    void delayI2c(void)
    {
       asm("nop");
       asm("nop");
       asm("nop");
       asm("nop");
       asm("nop");
    }
    
    void i2cstart(void)
    {
       SDA_OUT; //
       SCL_OUT; // ustawienie linii SDA i SCL w tryb wyjściowy
       SET_SDA; //
       SET_SCL; // ustawienie na liniach SDA i SCL stanu wysokiego
       delayI2c(); // opóźnienie
       CLR_SDA;
       delayI2c();
       CLR_SCL;
    }
    // funkcja generujaca sygnał stop
    
    void i2cstop(void)
    {
       SDA_OUT;
       CLR_SDA;
       delayI2c();
       SET_SCL;
       delayI2c();
       SET_SDA;
       delayI2c();
    }
    
    // funkcja wysyłająca bajt na szynę I2C
    void i2cwrite(unsigned char byte)
    {
        unsigned char i;
        SDA_OUT;CLR_SDA;
        for(i=0;i<8;i++)
    {
    	if(byte&0x80) 		//wyslanie jedynki
    	{
    		CLR_SCL;
    		SET_SDA;
    		delayI2c();
    		SET_SCL;
    		delayI2c();
    		CLR_SCL;
    		delayI2c();
    	}
    	else				//wyslanie zera
    	{
    		CLR_SCL;
    		CLR_SDA;
    		delayI2c();
    		SET_SCL;
    		delayI2c();
    		CLR_SCL;
    		//SET_SDA;
    		delayI2c();
    	}
    	byte=byte<<1;
    		//kolejny bit
    }
    	CLR_SCL;
    do
    {
    	SET_SCL;
    	SDA_IN;
    	delayI2c();
    	i=SDA;				//odczyt ACK
    	CLR_SCL;
    	delayI2c();
    }while(!i);	//			
    
    }
    	
    // funkcja odczytujaca bajt z szyny I2C
    unsigned char i2cread(unsigned char ack)
    {
    	unsigned char i, byte=0;
    	{
    	for(i=0;i<8;i++)
    	{
    		SDA_IN;
    		SET_SCL;
    		delayI2c();
    		byte=byte|GET_SDA;
    		CLR_SCL;
    		delayI2c();
    		if(i<7) byte=(byte<<1)&0xfe;
    	}
    	SDA_OUT;
    	SET_SDA;
    	delayI2c();
    	SET_SCL;
    	delayI2c();
    	CLR_SCL;
    	
    	return byte;
    	}
    }
    
    void i2czapis(unsigned char byte,char d)
    {
     
     	i2cstart();
    	i2cwrite(0xA0);
    	i2cwrite(byte);
    	i2cwrite(d);
    	i2cstop();
      
      	
    }
    
    unsigned char i2codczyt(unsigned char byte)
    {
       unsigned char t ;
    
    	i2cstart();
    	
    	i2cwrite(0xA0);
    	i2cwrite(byte);
    	//i2cstop();
    	i2cstart();
    	i2cwrite(0xA1);
    	t= i2cread(0);
    	i2cstop();
        return (t);
      //	-----------------------------
    }
    
    void sekundy(unsigned char s)
    {
    	char j;
    	j=s&0x0f;
    	lcd_xy(1,2);
    	lcd_xy(1,3);
    	write_char(j+48);
    }
    int main (void)
    {
    unsigned char tm;
    lcd_init();
    lcd_xy(0,0);
    write_text("T=");
    UART_init();   
     while(1)
    {
    	i2cstart();
    	i2cwrite(0xA0);
    	i2cwrite(0x02); 
     	i2cstart();
    	i2cwrite(0xA1);
    	tm= i2cread(0);
     	i2cstop();
    	sekundy(tm);
    }
    }
    
    


    Bardzo prosze o pomoc
  • REKLAMA
  • #2 3454845
    j_saw
    Poziom 14  
    Posty: 67
    Pomógł: 2
    Ocena: 59
    Z tego co pamiętam to źle go podłączyłeś - kondensator ma być pomiędzy pinem "1" a "8" czyli Vcc a Ty go podłączyłeś do masy

    Co do procedur to nie sprawdzałem bo wcześniej jest błąd.

    JS
  • REKLAMA
  • #3 3455836
    Samuraj
    Poziom 35  
    Posty: 2792
    Pomógł: 286
    Ocena: 619
    Złe podłączenie kondensatora spowoduje tylko że zegar będzie leciał szybciej albo wolniej juz nie pamiętam, co nie zmienia faktu że coś powinno się dać odczytać.
    Proponuje odczytać inne komórki, nie zaglądałem do pdf'a ale może te co czytasz to jest rok albo godzina.
  • REKLAMA
  • #4 3459030
    slimak281
    Poziom 11  
    Posty: 86
    Pomógł: 2
    Ocena: 1
    j_saw napisał:
    kondensator ma być pomiędzy pinem "1" a "8" czyli Vcc a Ty go podłączyłeś do masyJS


    Poprawilem tak jak piszesz Ale dale tak samo pokazuje 0 cally czas ;/, Dziekuje J_saw za program, zaraz przerobie i sprawdze, jak cos to bede pisal. Dzieki jeszcze raz
  • #5 3459073
    lukasb9
    Poziom 28  
    Posty: 1421
    Pomógł: 56
    Ocena: 70
    prosze to procedura napisana w C pod atmege16 działa na 100% - w DIY jest mój zegar który z nia pracuje ten sam RTC, procedura odczytuje sekundy minuty godziny

    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> procedury obsługi I2C <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    void i2cdelay (void)
    {
    for(z=0;z<5;z++)
    asm("nop");
    }
    //////////////////////////////////////////////////////////////////////////////
    void bitstartu (void)
    {DDRA&=0b11111011; //ustaw linie SDA
    i2cdelay();
    DDRA&=0b11101111; //ustaw linie SCL
    i2cdelay();
    DDRA|=0b00000100; //zeruj linie SDA
    i2cdelay();
    DDRA|=0b00010000; //zeruj linie SCL
    i2cdelay();}
    /////////////////////////////////////////////////////////////////////////////
    void bitstopu (void)
    {DDRA|=0b00000100; //zeruj linie SDA
    i2cdelay();
    DDRA&=0b11101111; //ustaw linie SCL
    i2cdelay();
    DDRA&=0b11111011; //ustaw linie SDA
    i2cdelay();}
    /////////////////////////////////////////////////////////////////////////////
    unsigned char zapiszB_I2C (unsigned char dana)
    {


    for(i=0;i<8;i++)
    {
    if (dana&0x80)
    {DDRA&=0b11111011; //ustaw linie SDA
    i2cdelay();}
    else
    {DDRA|=0b00000100; //zeruj linie SDA
    i2cdelay();}

    i2cdelay();
    DDRA&=0b11101111; //ustaw linie SCL
    i2cdelay();
    DDRA|=0b00010000; //zeruj linie SCL
    i2cdelay();
    dana<<=1;
    }

    DDRA&=0b11111011; //ustaw linie SDA
    i2cdelay();
    DDRA&=0b11101111; //ustaw linie SCL
    i2cdelay();
    while (bit_is_clear(PINA,PA4))//?????????

    i2cdelay();
    i=bit_is_set(PINA,PA2);
    DDRA|=0b00010000; //zeruj linie SCL
    i2cdelay();
    return i;
    }
    /////////////////////////////////////////////////////////////////////////////
    unsigned char czytajB_I2C(unsigned char ack)
    {
    unsigned char dana=0,i;
    for(i=0;i<8;i++)
    {DDRA|=0b00010000; //zeruj linie SCL
    i2cdelay();
    DDRA&=0b11101111; //ustaw linie SCL
    i2cdelay();
    dana<<=1;
    dana|=(bit_is_set(PINA,PA2))?1:0;}

    DDRA|=0b00010000; //zeruj linie SCL
    i2cdelay();
    if(ack)
    {DDRA|=0b00000100;} //zeruj linie SDA
    else
    {DDRA&=0b11111011;} //ustaw linie SDA

    i2cdelay();
    DDRA&=0b11101111; //ustaw linie SCL
    while (bit_is_clear(PINA,PA4))
    {}
    i2cdelay();
    DDRA|=0b00010000; //zeruj linie SCL
    DDRA&=0b11111011; //ustaw linie SDA
    return dana;
    }
    /////////////////////////////////////////////////////////////////////////////
    void odI2C(unsigned char adrI2C,unsigned char adrdane)
    {
    bitstartu(); //odbieranie danych z RTC
    zapiszB_I2C(adrI2C);
    zapiszB_I2C(adrdane);
    bitstartu();
    zapiszB_I2C(adrI2C+1);

    temp=czytajB_I2C(1);
    tablicaczasu[5]=temp;
    tablicaczasu[5]&=0b00001111;
    tablicaczasu[4]=temp;
    tablicaczasu[4]>>=4;

    temp=czytajB_I2C(1);
    tablicaczasu[3]=temp;
    tablicaczasu[3]&=0b00001111;
    tablicaczasu[2]=temp;
    tablicaczasu[2]>>=4;

    temp=czytajB_I2C(0);
    tablicaczasu[1]=temp;
    tablicaczasu[1]&=0b00001111;
    tablicaczasu[0]=temp;
    tablicaczasu[0]>>=4;

    bitstopu();


    }
    /////////////////////////////////////////////////////////////////////////////








    http://www.lucaslab.grandhost.pl/MAGISTRALA_I2C.htm - tutaj troche lepiej opracowane lepiej skomentowane :)
  • REKLAMA
  • #6 9260552
    extremist
    Poziom 1  
    Posty: 1
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Here is my version of PCF8583 interfacing with Atmega and WH1602
  • #7 9544248
    humiuser
    Poziom 1  
    Posty: 1
    extremist,

    how many buttons you have and where they are connected?

Podsumowanie tematu

LABEL_AI_GENERATED
Problem dotyczy odczytu sekund z układu PCF8583 za pomocą interfejsu I2C realizowanego programowo na mikrokontrolerze ATmega8 z wewnętrznym kwarcem 1 MHz. Użytkownik zgłasza, że odczytywana wartość sekund zawsze wynosi 0, mimo poprawnego podłączenia według schematu. W dyskusji zwrócono uwagę na błędne podłączenie kondensatora między pinami zasilania układu PCF8583 (kondensator powinien być między pinem 1 a 8, czyli Vcc, a nie do masy), co może wpływać na działanie zegara RTC. Jednakże nawet po poprawieniu kondensatora problem z odczytem sekund pozostaje. Zaproponowano sprawdzenie odczytu innych rejestrów, np. minut lub godzin, aby wykluczyć błędy adresacji rejestrów. Jeden z uczestników udostępnił działającą procedurę obsługi I2C w języku C dla mikrokontrolera ATmega16 i układu PCF8583, która poprawnie odczytuje sekundy, minuty i godziny, sugerując porównanie i adaptację kodu. W dyskusji pojawiły się także przykładowe implementacje sterowania LCD oraz definicje pinów I2C, co może pomóc w debugowaniu i poprawnym odczycie danych z RTC.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA