Forum: Mikrocontroller und Digitale Elektronik DS1302 nur alle 2s gültiges Signal?


von enhape (Gast)


Lesenswert?

Hallo zusammen,

ich habe keine Ideen mehr. Vielleicht könnt ihr mir helfen? Ich möchte 
einfach nur mit einem Mega32 die Sekunden aus dem DS1302 auslesen. Das 
gelingt mir allerdings nur alle 2s korrekt. Was mache ich falsch? Bin 
dankbar für jede Antwort!

Gruß

enhape

Anbei der Code, gefolgt von der ds1302.h (dankend aus dem Forum bezogen)

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

#include "ds1302.h"


#ifndef F_CPU
#define F_CPU 1000000
#endif




// Prototypen
uint8_t Read_DS1302(uint8_t);




int main()
{

  //Ports initialisieren:
    DDRC = 0xFF; // Port C auf Ausgang

  uint8_t temp2;


  //RTC initialisieren
   RTC_Init();


    while (1)
    {
    _delay_ms(1);
    temp2 = Read_DS1302(0x81);
    PORTC = ~temp2;
  }
}


//**************************************
// Write
//**************************************
void Write( char cmd )
{

  uint8_t n;

  RTC_DATA_LINE_IS_OUTPUT();
  _delay_ms(1);
  for (n = 0; n < 8; n++)
  {
    if (CheckBit(cmd,n))
    {
    RTC_DATA_HIGH();
    }
  else
  {
      RTC_DATA_LOW();
    }
  _delay_ms(1);
  RTC_CLK_HIGH();
    _delay_ms(1);
  RTC_CLK_LOW();
  _delay_ms(1);
  }
  RTC_DATA_LINE_IS_INPUT();
}

//**************************************
// Write_DS1302
//**************************************
void Write_DS1302( uint8_t cmd, uint8_t data )
{
  RTC_RESET_HIGH();
  Write(cmd);
  Write(data);
  RTC_RESET_LOW();
}

//***************************************
// Read
//***************************************
uint8_t Read( void )
{

   uint8_t n, d, data;
   data = 0x00;


   for(n = 0; n < 8; n++)
   {
     d = CHECK_RTC_DATA();
     data = (data >> 1);
     if (d)
   {
       data |= 0x80;
   }
   _delay_ms(1);
     RTC_CLK_HIGH();
     _delay_ms(1);
     RTC_CLK_LOW();
     _delay_ms(1);
   }
   return data;
}

//***************************************
// Read_DS1302
//***************************************
uint8_t Read_DS1302(uint8_t cmd)
{
  uint8_t data;
  RTC_RESET_HIGH();
  _delay_ms(1);
  Write(cmd);
  _delay_ms(1);
  data = Read();
  _delay_ms(1);;
  RTC_RESET_LOW();
  _delay_ms(1);;
  return data;
}




//*************************
// RTC_Init         (called from Main-Init)
//*************************
void RTC_Init(void )
{ uint8_t data;

  RTC_RESET_LOW();

  RTC_DATA_LINE_IS_INPUT();
  NOP();
  NOP();
  RTC_CLK_LOW();
  NOP();
  NOP();

  Write_DS1302(CONTROL_REGISTER, UNPROTECT);
  data = Read_DS1302( 0x81);
  if (CheckBit(data,7))               // if bit 7 is high, Clock is 
stopped
  {  Write_DS1302( 0x80, 0x00);
  }
  Write_DS1302(CONTROL_REGISTER, PROTECT);

}



////////////////////////////////////////////////////////////////////////
//ds1302.h:


#ifndef  _RTC_H
#define  _RTC_H 1

#define BYTE  unsigned char
#define TRUE                 (BYTE)1
#define FALSE                (BYTE)0
#define NOP()      asm("nop")

#define SetBit(ADRESS,B)         ((ADRESS) |=  (1<<(B)))
#define ClearBit(ADRESS,B)       ((ADRESS) &= ~(1<<(B)))
#define CheckBit(ADRESS,B)       (BYTE)((ADRESS) &   (1<<(B)))
#define ToggleBit(ADDRESS,BIT)   ((ADDRESS) ^= (1<<BIT))

//=================================================
// je nachdem, an welchem Port DS1302 haengt,
// muessen diese Werte angepasst werden
#define RTC_CLK             0
#define RTC_DATA            1
#define RTC_RES             2

#define RTC_CLK_LOW()             ClearBit(PORTA,RTC_CLK)
#define RTC_CLK_HIGH()            SetBit(PORTA,RTC_CLK)
#define RTC_DATA_LOW()            ClearBit(PORTA,RTC_DATA)
#define RTC_DATA_HIGH()           SetBit(PORTA,RTC_DATA)
#define CHECK_RTC_DATA()          CheckBit(PINA,RTC_DATA)
#define RTC_RESET_LOW()           ClearBit(PORTA,RTC_RES)
#define RTC_RESET_HIGH()          SetBit(PORTA,RTC_RES)
#define RTC_DATA_LINE_IS_OUTPUT() SetBit(DDRA,   RTC_DATA)
#define RTC_DATA_LINE_IS_INPUT()  ClearBit(DDRA, RTC_DATA)
// Ende der Anpassung
//=================================================

#define RTC_RAM   1
#define RTC_CLOCK 0

#define RTC_SEC   0
#define RTC_MIN   1
#define RTC_HRS   2
#define RTC_DAY   3
#define RTC_MONTH 4
#define RTC_DOW   5          // day of week (1 = Mon)
#define RTC_YEAR  6


#define CONTROL_REGISTER 0x8E
#define PROTECT   0x80
#define UNPROTECT 0x00

void RTC_Init(void );
void RTC_SetTime( void );
void RTC_GetTime( void );
void RTC_Unprotect( void );
void RTC_Protect( void );
BYTE RTC_Ctrl( void );
#endif

von M. P. (phpmysqlfreak)


Lesenswert?

Kleiner Tipp:

"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

Das könnte unter Umständen zu besseren Antworten führen. Ein 
hochgeladener Quelltext kann auch mit Syntax-Hervorhebung angezeigt 
werden.

Zu kontruktiven Behebung des Problems kann ich dir aber aufgrund meiner 
Unkenntnis des DS1302 leider keine weitere Auskunft geben. - Ein 
RTC-Chip steht aber schon fast ganz oben auf meiner "To-Learn"-Liste ;)

Gruß, Marcel

von Sascha W. (sascha-w)


Lesenswert?

sag doch erst mal was genau nicht geht wenn's nicht geht!
I2C-Start, DS1302 adressieren, Adresse setzen, Byte lesen?

Also ich hab die DS1302 schon des öfteren eingesetzt und diesbezüglich 
noch keine Probleme gehabt.

Sascha

von enhape (Gast)


Lesenswert?

Hallo Sascha, hallo Marcel,

danke für die Antworten,

habe gedacht, wenn Code gleich mit im Text steht wäre es 
"verführerischer" ihn anzuschauen...

zum 2 Sekunden-Problem. Der µController schickt an den DS1302 den 
Steuerbefehl 0x81. Ohne Burst-Mode. Ich wollte klein anfangen und erst 
einmal nur die Sekunden auslesen. Als Ausgabe dienen 8 Dioden an Port C. 
Egal, ob ich 300ms zw. den Abfragen warte oder nur 30, ich bekomme immer 
nur ein "sinnvolles" Ergebnis in den Sekunden 1, 3, 5, 7 usw. In den 
dazwischen liegenden Zeiten bekomme ich kein Ergebnis. Habe keine Ahnung 
was das sein kann.

Sascha, vielleicht kannst du mir ein Code-Beispiel von dir zusenden, 
welches bei dir 100%ig funktioniert?

viele Grüße
enhape

von Sascha W. (sascha-w)


Angehängte Dateien:

Lesenswert?

Hallo,

wie du evl. gemerkt hast hab ich da was verwechselt und habe an die 
DS1307 gedacht - dashalb I2C! Aber auch die DS1302 hab ich schon 
verwendet - siehe Anhang. Contoller war ein 90S8515 mit 8MHz. Die Port 
und Registerdefinitionen musst du entsprechend festlegen.


Sascha

von enhape (Gast)


Lesenswert?

Hallo Sascha,

danke für den code. In Assembler habe ich leider überhaupt keine Ahnung.


Hat jemand eventuell ein funktionierendes Beispiel in c? Oder konnte 
jemand einen ähnlichen "2s-Effekt" beobachten? Bin über jede Antwort 
äußerst dankbar.

viele Grüße
enhape

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.