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

[C][tiny2313] PCF8583 - błąd zapisu/odczytu do układu

marti_ql 11 Maj 2009 14:05 1203 0
REKLAMA
  • #1 6516396
    marti_ql
    Poziom 10  
    Mam płytkę testową ZL11AVR (schemat w dokumentacji http://www.btc.pl/pdf/zl11avr.pdf)do której podłączyłem układ PCF8583 (pod wyprowadzenia na płytce SDA i SCL).
    Niestety po uruchomieniu program wyrzuca błędy zapisu/odczytu z układu.
    Gdzie tkwi błąd?

    Kawałek programu main.c
    
    int main(void)
    {
    	
    	//konfigurowanie portów
    	DDRD=0x00; 	
    	PORTD=0x04;   
    	DDRB=0xFF; 	
    	PORTB=0x03;  
    	char *tekst1=PSTR("Zegar PCF8583");
    	char *tekst2=PSTR(" Attiny2313");
    	unsigned char t;		
    
    	initlcd();
    	lcdxy(0,1);
    	writetext(tekst1);
    	lcdxy(1,1);
    	writetext(tekst2);
    	_delay_ms(tau*2000);
    	setrtc();
    	clearlcd();
    	// Chwilowe wyswietlenie czasu ustawionego w programie
    	time_lcd();
    	_delay_ms(tau*2000);
    	// odczyt godzin
    	i2c_read(rtc,0x04,1,&t);
    	czas[0]=(t&0x30)>>4;	//10h
    	czas[1]=t&0x0F;		//1h
    	// odczyt minut
    	i2c_read(rtc,0x03,1,&t);
    	czas[2]=(t&0xF0)>>4;	//10min
    	czas[3]=t&0x0F;		//1min
    	// odczyt sekund
    	i2c_read(rtc,0x02,1,&t);
    	czas[4]=(t&0xF0)>>4;	//10sek
    	czas[5]=t&0x0F;		//1sek
    	//odczyt dnia
    	i2c_read(rtc,0x05,1,&t);
    	czas[6]=(t&0x30)>>4;	//10day
    	czas[7]=t&0x0F;		//1day
    	// odczyt miesiaca
    	i2c_read(rtc,0x06,1,&t);
    	czas[8]=(t&0x10)>>4;	//10month
    	czas[9]=t&0x0F;		//1month
    	time_lcd();
    ...
    
    


    i2c.h

    
    #include <avr/io.h>
    
    #define I2CPORT PORTD 
    #define I2CPIN  PIND 
    #define I2CDDR  DDRD 
    #define SDA 	PD5
    #define SCL 	PD6
    
    #define SDA_IN bit_is_set(I2CPIN,SDA)
    #define SDA_OUT_0 I2CDDR|=_BV(SDA)
    #define SDA_OUT_1 I2CDDR&=~_BV(SDA)
    
    #define SCL_IN bit_is_set(I2CPIN,SCL)
    #define SCL_OUT_0 I2CDDR|=_BV(SCL)
    #define SCL_OUT_1 I2CDDR&=~_BV(SCL)
    #define I2CDEL 30
    
    unsigned char i2cbuf[9];     //bufor interfejsu I2C (dane z/do RTC)
    unsigned char *i2cpbuf;      //wskaźnik na bufor danych z RTC
    
    void i2c_start();
    void i2c_stop();                                      
    void i2c_delay(unsigned char p);                          
    unsigned char i2c_writebyte(unsigned char byte);                  
    unsigned char i2c_readbyte(unsigned char ack);                        
    void i2c_write(unsigned char devadr, unsigned char adr, unsigned char lenght, unsigned char *data);    
    void i2c_read(unsigned char devadr, unsigned char adr, unsigned char lenght, unsigned char *data); 
    void i2c_error(unsigned char err);
    


    i2c.c
    
    #include "i2c.h"
    #include "lcd.h"
    #include <avr/pgmspace.h>
    
    void i2c_delay(unsigned char p) 
    { 
    	do
    	{
    		asm("nop");
    	}
    	while(--p!=0);
    } 
    
    void i2c_start()
    {
    	SDA_OUT_1; i2c_delay(I2CDEL);
    	SCL_OUT_1; i2c_delay(I2CDEL);
    	SDA_OUT_0; i2c_delay(I2CDEL);
    	SCL_OUT_0; i2c_delay(I2CDEL);
    }
    
    void i2c_stop()
    {
    	SDA_OUT_0; i2c_delay(I2CDEL);
    	SCL_OUT_1; i2c_delay(I2CDEL);
    	SDA_OUT_1; i2c_delay(I2CDEL);
    }
    
    void i2c_error(unsigned char err)
    {
    	clearlcd();
    	switch(err)
    	{
    		case 1:
    			writetext(PSTR("ERR write dev"));
    			break;
    		case 2:
    			writetext(PSTR("ERR write adr"));
    			break;
    		case 3:
    			writetext(PSTR("ERR write data"));
    			break;
    		case 4:
    			writetext(PSTR("ERR read dev"));
    			break;
    		case 5:
    			writetext(PSTR("ERR read adr"));
    			break;
    		case 6:
    			writetext(PSTR("ERR read data"));
    			break;
    		default:
    			writetext(PSTR("Blad I2C - nieznany"));
    			break;
    	}
    	_delay_ms(1055);
    	clearlcd();
    }
    
    unsigned char i2c_writebyte(unsigned char byte) 
    { 
        unsigned char i,ack; 
        for (i=0;i<8;i++)
        { 
            if (byte&0x80)
    			SDA_OUT_1;
    		else
    			SDA_OUT_0; 
            i2c_delay(I2CDEL); 
            SCL_OUT_1; i2c_delay(I2CDEL); 
            SCL_OUT_0; i2c_delay(I2CDEL); 
            byte<<=1; 
        } 
        SDA_OUT_1; i2c_delay(I2CDEL); 
        SCL_OUT_1; i2c_delay(I2CDEL); 
        while(!SCL_IN);
    	i2c_delay(I2CDEL);
        ack=SDA_IN;
        SCL_OUT_0; i2c_delay(I2CDEL); 
        return ack;
    }
    
    
    unsigned char i2c_readbyte(unsigned char ack) 
    { 
        unsigned char i,byte=0; 
        for (i=0;i<8;i++)
        {
    		SCL_OUT_0; i2c_delay(I2CDEL);
    		SCL_OUT_1; i2c_delay(I2CDEL);
    		byte<<=1;
    		byte|=SDA_IN==1?1:0;
        } 
        if(ack)
        {
    		SDA_OUT_0;
        }
        else
        {
    		SDA_OUT_1;
        }
        i2c_delay(I2CDEL);
        SCL_OUT_1;
        while(!SCL_IN);
        i2c_delay(I2CDEL);
        SDA_OUT_1;
        SCL_OUT_0;
        return byte;
    }
    
    void i2c_write(unsigned char devadr, unsigned char adr, unsigned char lenght, unsigned char *data)
    {
    //	i2cpbuf=data;
    	i2c_start();
    	if(i2c_writebyte(devadr));
    	{
    		i2c_error(1);
    	}
    	if(i2c_writebyte(adr))
    	{
    		i2c_error(2);
    	}
    	for(;lenght!=0;lenght--)
    	{
    		if(i2c_writebyte(*data++))
    		{
    			i2c_error(3);
    		}
    	}
    	i2c_stop();
    }
    		
    void i2c_read(unsigned char devadr, unsigned char adr, unsigned char lenght, unsigned char *data)
    {
    	i2c_start();
    	if(i2c_writebyte(devadr))
    	{
    		i2c_error(4);
    	}
    	if(i2c_writebyte(adr))
    	{
    		i2c_error(5);
    	}
    	i2c_start();
    	if(i2c_writebyte(devadr+1))
    	{
    		i2c_error(6);
    	}
    	for(;lenght>1;lenght--)
    	{
    		*data++=i2c_readbyte(1);
    	}
    	*data++=i2c_readbyte(0);
    	i2c_stop();
    }
    


    może jeszcze funkcja setrtc()
    
    // Inicjalizacja RTC
    
    void setrtc()
    {
    	unsigned char tt;
    	tt=0x15;
    	i2c_write(rtc,2,1,&tt);
    	tt=0x20;
    	i2c_write(rtc,3,1,&tt);
    	tt=0x17;
    	i2c_write(rtc,4,1,&tt);
    	tt=0x10;
    	i2c_write(rtc,5,1,&tt);
    	tt=0x04;
    	i2c_write(rtc,6,1,&tt);
    	tt=0x01;
    	i2c_write(rtc,0,1,&tt); //start zegara	
    }
    


    Trochę pokombinowałem i pozmieniałem funkcje i2c_read (ma dwa argumenty o zwraca bajt danych) i i2c_write.
    Efekt to tylko jeden błąd - ERR write dev, czyli błąd zapisu adresu do I2C.

    PCF działa bo podaje przerwania na INT0.

    Jakby ktoś znalazł czas i znalazł błąd byłbym wdzięczny, bo jak na razie brak odzewu, czyżby nikomu nie chciało się przeglądać listing?
  • REKLAMA
REKLAMA