Skocz do zawartości

Komunikacja zegara DS1307 z AtMega88 - problem z ustawieniem zegara i pobraniem czasu


Pomocna odpowiedź

Cześć, 

Jako że to mój pierwszy post tutaj nie bijcie 😄 Mam zerowe doświadczenie w C i małe w innych językach więc pewnie to czego szukam jest banalne... Do rzeczy. 

Robię swój pierwszy projekt na AtMega88PA, którego częścią jest wyświetlacz 2x16 i zegar czasu rzeczywistego DS1307. Oba urządzenia podłączone są przez i2c do procka (wyświetlacz poprzez extender) i wyświetlacz udało mi się zmusić do pracy - czyli komunikacja i2c działa. Schemat podłączenia w załączniku. Połączenie sprawdzone. Bateria po odłączeniu programatora daje 1 mikroamper do układu więc zakładam że zegar podtrzymuje swoje działanie. 

Po ustawieniu zegara jakiś czas temu (zanim zaprogramowałem wyświetlacz) udało mi się wyprowadzić sekundnik na diodę - time.sec%2 powodowało zmianę stanu LED'a i ten ładnie mrygał w odstępie sekundowym.  Zegar ustawilem nastepujacym kodem: 

	RTC_Init();
    rtc_t rtc;

    rtc.hour = 0x10; //  10:40:20 am
    rtc.min =  0x40;
    rtc.sec =  0x00;
    rtc.date = 0x01; //1st Jan 2016
    rtc.month = 0x01;
    rtc.year = 0x16;
    rtc.weekDay = 5; // Friday: 5th day of week considering monday as first day.

    RTC_SetDateTime(&rtc);  //  10:40:20 am, 1st Jan 2016

Do projektu dodałem parę urządzeń, zaprogramowałem wyświetlacz. Schody zaczęły się gdy próbuję wyprowadzić stan zegara na ekran. Pojawia się takie coś: 

https://youtu.be/qWDivu2OPvA 

main.c

int main(void) {
	// tutaj inicjacja wyswietlacza, we/wy - nieistotne
    rtc_t time;
    lcd_led(0);
    char i;
  	RTC_Init();

	while(1){
		RTC_GetDateTime(&time); // metoda do poboru danych z zegara
	    lcd_gotoxy(0,0); // ustaw kursor na punkt 0 w zegarze

	    i = (char)time.sec; // mapowanie zmiennej sekundowej do znaku - 
		lcd_puts(&i);     // metoda wyswietlajaca znaki na wyswietlaczu
    }
}

Clock.c

#include "twi.h"
#include <avr/io.h>
#include <util/delay.h>

#define Clock_Read   0xD1  // bit odczytu
#define Clock_Write  0xD0  // bit zapisu

typedef struct
{
  uint8_t sec;
  uint8_t min;
  uint8_t hour;
  uint8_t weekDay;
  uint8_t date;
  uint8_t month;
  uint8_t year;
}rtc_t;

void RTC_Init(void)
{
    twi_init();                             // Initialize the I2c module.
    twi_start();                            // Start I2C communication

    twi_write(Clock_Write);        // Connect to DS1307 by sending its ID on I2c Bus
    twi_write(0x07);              // Select the Ds1307 ControlRegister to configure Ds1307

    twi_write(0x00);                        // Write 0x00 to Control register to disable SQW-Out

    twi_stop();                             // Stop I2C communication after initializing DS1307
}

void RTC_SetDateTime(rtc_t *rtc)
{
    twi_start();                          // Start I2C communication

    twi_write(Clock_Write);      // connect to DS1307 by sending its ID on I2c Bus
    twi_write(0x00); // Request sec RAM address at 00H

    twi_write(rtc->sec);                    // Write sec from RAM address 00H
    twi_write(rtc->min);                    // Write min from RAM address 01H
    twi_write(rtc->hour);                   // Write hour from RAM address 02H
    twi_write(rtc->weekDay);                // Write weekDay on RAM address 03H
    twi_write(rtc->date);                    // Write date on RAM address 04H
    twi_write(rtc->month);                    // Write month on RAM address 05H
    twi_write(rtc->year);                    // Write year on RAM address 06h

    twi_stop();                              // Stop I2C communication after Setting the Date
}

void RTC_GetDateTime(rtc_t *rtc)
{
    twi_start();                            // Start I2C communication

    twi_write(Clock_Read);        // connect to DS1307 by sending its ID on I2c Bus
    twi_write(0x00); // Request Sec RAM address at 00H

    twi_stop();                                // Stop I2C communication after selecting Sec Register

    twi_start();                            // Start I2C communication
    twi_write(Clock_Read);            // connect to DS1307(Read mode) by sending its ID

    rtc->sec = twi_read(1);                // read second and return Positive ACK
    rtc->min = twi_read(1);                 // read minute and return Positive ACK
    rtc->hour= twi_read(1);               // read hour and return Negative/No ACK
    rtc->weekDay = twi_read(1);           // read weekDay and return Positive ACK
    rtc->date= twi_read(1);              // read Date and return Positive ACK
    rtc->month=twi_read(1);            // read Month and return Positive ACK
    rtc->year =twi_read(0);             // read Year and return Negative/No ACK

    twi_stop();                              // Stop I2C communication after reading the Date
}

twi.c

#include "twi.h"
#include <avr/io.h>
#include <util/delay.h>

// procedura inicjalizacji TWI
void twi_init(void)
{
	/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
	TWSR = 0;                         /* no prescaler */
	TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */

}/* twi_init */

// procedura transmisji sygnału START
void twi_start(void)
{
	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
}

// procedura transmisji sygnału STOP
void twi_stop(void)
{
	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
	while ((TWCR & (1 << TWSTO)));
}

// procedura transmisji bajtu danych
void twi_write(char data)
{
	TWDR = data;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
}

//procedura odczytu bajtu danych
char twi_read(char ack)
{
	TWCR = ack ? ((1 << TWINT) | (1 << TWEN) | (1 << TWEA)) : ((1 << TWINT) | (1 << TWEN));
	while (!(TWCR & (1 << TWINT)));
	return TWDR;
}

Gdy próbuję bezpośrednio wyświetlić zmienną time.sec kompilator ostrzega o niezgodności znaków. Gdy spróbowałem wyświetlić 'time.sec' na wyświetlacz pojawiły się dodatkowe 4 znaki z lewej strony - w sumie było ich 7, dwa ostatnie takie same jak na filmie a reszta kompletnie randomowa. 

Bit odczytu i zapisu wziąłem z dokumentacji urządzenia. 

Moje podejrzenie jest takie że zmienna którą wprowadzam do funkcji RTC_SetDateTime nie jest zmieniana przez tą funkcję. Próbowałem napisać podobną funkcję zwracającą całą strukturę, ale nie udało mi się to. Moja zmienna 'time' jest globalna i jak wrzucam ją do funkcji to moim zdaniem powinna być przez tą funkcję nadpisywana. Nie widzę sensu dodania tabeli int'ów do funkcji a potem jej wyprowadzenia bo czuje że to się skończy tak samo - mogę się mylić.

Dajcie proszę jakąś wskazówkę dla mniej doświadczonego bo już nie wiem co mogę jeszcze zrobić.

schemat i2c.png

Doniczkav2.zip

Edytowano przez se7en941
EDIT: Dorzucam spakowany projekt, będzie łatwiej szukać w kodzie
Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.