Piszę obsługę zegara PCF8583. W moim programie występują jakieś błędy, i nie wiem jak je rozwiązać. Proszę o pomoc.
Poniżej zamieszczam kod do obsługi I2C (TWI), i zegara PCF8583.
W wyniku działania programu dostaję dziwne wyniki na wyświetlaczu.
Kod:
Na wyświetlacz idzie otrzymana liczba bez przekształceń.
Szukałem i przerabiałem już tematy o PCF8583, przerobiłem też kod ale dalej mi ten zegar nie działa jak powinien, już od tygodnia nad tym siedzę. Proszę o pomoc, wskazówki.
Poniżej zamieszczam kod do obsługi I2C (TWI), i zegara PCF8583.
W wyniku działania programu dostaję dziwne wyniki na wyświetlaczu.
Kod:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#define ACK 1
#define NOACK 0
#define PCF8583 1
static void i2cInit(void)
{
TWSR = 0;
TWBR = 6;
}
static void i2cStart(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
}
static void i2cStop(void)
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
while ((TWCR & (1<<TWSTO)));
}
static void i2cWrite(char data)
{
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
}
static char i2cRead(char ack)
{
TWCR = ack ? ((1 << TWINT) | (1 << TWEN) | (1 << TWEA)) : ((1 << TWINT) | (1 << TWEN)) ;
while (!(TWCR & (1<<TWINT)));
return TWDR;
}
static volatile uint8_t PCF8583_status;
static volatile uint8_t PCF8583_alarm;
static uint8_t bcd2bin(uint8_t bcd)
{
return (10*(bcd>>4) + (bcd&0x0f));
}
static uint8_t bin2bcd(uint8_t bin)
{
return ( ( ( bin / 10 ) << 4) | ( bin % 10 ) );
}
static uint8_t PCF8583_read(uint8_t address)
{
uint8_t a;
a = (PCF8583_A0 << 1) | 0xa0; // tu musiałem zmienić na 0x50 nie wiem
// czemu 0xa0 nie działa
i2cStart();
i2cWrite(a);
i2cWrite(address);
i2cStart();
i2cWrite(a | 1); // tu mam i2cWrite(a); też nie wiem
// dlaczego i2cWrite(a | 1); nie działa
a = i2cRead(NOACK);
i2cStop();
return a;
}
static void PCF8583_write(uint8_t address,uint8_t data)
{
i2cStart();
i2cWrite((PCF8583_A0 << 1) | 0xa0); // tu musiałem zmienić na 0x50 nie wiem
// czemu 0xa0 nie dział
i2cWrite(address);
i2cWrite(data);
i2cStop();
}
static uint8_t PCF8583_read_bcd(uint8_t address)
{
return bcd2bin(PCF8583_read(address));
}
static void PCF8583_write_bcd(uint8_t address,uint8_t data)
{
PCF8583_write(address,bin2bcd(data));
}
static uint8_t PCF8583_get_status(void)
{
PCF8583_status = PCF8583_read(0);
PCF8583_alarm = (PCF8583_status & 2);
return PCF8583_status;
}
static void PCF8583_init(void)
{
PCF8583_status=0;
PCF8583_alarm=0;
PCF8583_write(0, 0);
PCF8583_write(4, PCF8583_read(4) & 0x3f);
PCF8583_write(8, 0x90);
}
static void PCF8583_stop(void)
{
PCF8583_get_status();
PCF8583_status |= 0x80;
PCF8583_write(0, PCF8583_status);
}
static void PCF8583_start(void)
{
PCF8583_get_status();
PCF8583_status &= 0x7f;
PCF8583_write(0, PCF8583_status);
}
static void PCF8583_hold_off(void)
{
PCF8583_get_status();
PCF8583_status &= 0xbf;
PCF8583_write(0, PCF8583_status);
}
static void PCF8583_hold_on(void)
{
PCF8583_get_status();
PCF8583_status |= 0x40;
PCF8583_write(0, PCF8583_status);
}
static void PCF8583_alarm_off(void)
{
PCF8583_get_status();
PCF8583_status &= 0xfb;
PCF8583_write(0, PCF8583_status);
}
static void PCF8583_alarm_on(void)
{
PCF8583_get_status();
PCF8583_status |= 0x04;
PCF8583_write(0, PCF8583_status);
}
static void PCF8583_write_word(uint8_t address,uint16_t data)
{
PCF8583_write(address, (uint8_t)(data & 0xff));
PCF8583_write(++address, (uint8_t)(data >> 8));
}
static void PCF8583_write_date(uint8_t address,uint8_t day,uint16_t year)
{
PCF8583_write(address, bin2bcd(day) | ( ( (uint8_t)year & 0x03) << 6 ) );
}
static void PCF8583_get_time(uint8_t *hour,uint8_t *min,uint8_t *sec,uint8_t *hsec)
{
PCF8583_hold_on();
*hsec=PCF8583_read_bcd(1);
*sec=PCF8583_read_bcd(2);
*min=PCF8583_read_bcd(3);
*hour=PCF8583_read_bcd(4);
PCF8583_hold_off();
}
static void PCF8583_get_time_bcd(uint8_t *hour,uint8_t *min,uint8_t *sec,uint8_t *hsec)
{
PCF8583_hold_on();
*hsec=PCF8583_read(1);
*sec=PCF8583_read(2);
*min=PCF8583_read(3);
*hour=PCF8583_read(4) & 0b00111111;
PCF8583_hold_off();
}
static void PCF8583_set_time(uint8_t hour,uint8_t min,uint8_t sec,uint8_t hsec)
{
PCF8583_stop();
PCF8583_write_bcd(1,hsec);
PCF8583_write_bcd(2,sec);
PCF8583_write_bcd(3,min);
PCF8583_write_bcd(4,hour);
PCF8583_start();
}
static void PCF8583_get_date(uint8_t *day,uint8_t *month,uint16_t *year)
{
uint8_t dy;
uint16_t y1;
PCF8583_hold_on();
dy = PCF8583_read(5);
*month = bcd2bin(PCF8583_read(6) & 0x1f);
PCF8583_hold_off();
*day = bcd2bin(dy & 0x3f);
dy >>= 6;
y1 = PCF8583_read(16) | ( (uint16_t)PCF8583_read(17) << 8);
if ( ( (uint8_t) y1 & 3 ) != dy )
PCF8583_write_word(16, ++y1);
*year = y1;
}
static void PCF8583_set_date(uint8_t day,uint8_t month,uint16_t year)
{
PCF8583_write_word(16, year);
PCF8583_stop();
PCF8583_write_date(5, day, year);
PCF8583_write_bcd(6, month);
PCF8583_start();
}
static void PCF8583_get_alarm_time(uint8_t *hour, uint8_t *min, uint8_t *sec, uint8_t *hsec)
{
*hsec=PCF8583_read_bcd(0x9);
*sec=PCF8583_read_bcd(0xa);
*min=PCF8583_read_bcd(0xb);
*hour=PCF8583_read_bcd(0xc);
}
static void PCF8583_set_alarm_time(uint8_t hour, uint8_t min, uint8_t sec, uint8_t hsec)
{
PCF8583_write_bcd(0x9, hsec);
PCF8583_write_bcd(0xa, sec);
PCF8583_write_bcd(0xb, min);
PCF8583_write_bcd(0xc, hour);
}
static void PCF8583_get_alarm_date(uint8_t *day, uint8_t *month)
{
*day = bcd2bin( PCF8583_read(0xd) & 0x3f );
*month = bcd2bin( PCF8583_read(0xe) & 0x1f );
}
static void PCF8583_set_alarm_date (uint8_t day, uint8_t month )
{
PCF8583_write_date( 0xd, day, 0 );
PCF8583_write_bcd( 0xe, month );
}
uint8_t godz, min, sek, hsek;
uint8_t dzien, miesiac;
uint16_t rok;
// w funkcji main są tylko fragmenty programy
int main ( void )
{
i2cInit();
PCF8583_init();
PCF8583_set_time( 10, 11, 31, 0 );
PCF8583_set_date( 16, 11, 2010 );
while(1)
{
PCF8583_get_time( &godz, &min, &sek, &hsek );
PCF8583_get_date( &dzien, &miesiac, &rok );
};
return 0;
}
Na wyświetlacz idzie otrzymana liczba bez przekształceń.
Szukałem i przerabiałem już tematy o PCF8583, przerobiłem też kod ale dalej mi ten zegar nie działa jak powinien, już od tygodnia nad tym siedzę. Proszę o pomoc, wskazówki.