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
i2c.h
i2c.c
może jeszcze funkcja setrtc()
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?
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?