I2C läuft nicht richtig

  • 1
  • 2
  • Page 1 of 2
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

I2C läuft nicht richtig

 · 
Posted: 21.05.2011 - 01:33  ·  #1
Hallo Leute,

ich habe da ein kleines Problem, entweder habe ich hier einen Denkfehler und sehe vor lauter Bäumen den Wald nicht mehr, aber im Moment weiss ich nicht weiter.

Ich habe einen kleinen Dallas 1307 I2C RTC-Chip. der mit TWI_BR100 laufen sollte,
eigentlich hab ich schon mit AVRco den PCA9555 und auch den RTC 8564 Chip am laufen gehabt.

Aber mit den DS1307 beisse ich mir die Zähne aus, ich frage in meinem Programm alle 205.000 Zyklen den DS1307 ab (ich brauche die Zeit ja nicht ms genau), somit spare ich mir Rechenleistung für was wichtigeres.

Dabei ist mir aufgefallen, das aus irgendeinen Grund nur alle 10-15x das I2C Telegramm wirklich an den DS1307 gesendet wird. Das deckt sich auch mit meiner Osci-Anzeige und dem Logic-Analyser.
Die Leitung IDat und ICLK sind mit 10k auf 5v gezogen.

Ich vermute wohl einen Fehler in meiner DEFINE, bis jetzt hatte ich immer nur den SOFT-I2C genutzt, bei diesem Board möchte ich aber den OnBoard I2C nutzen, vieleicht habe ich deswegen einen Denkfehler. Hier mal einen Teil des CODE's, vieleicht hat Jemand von euch einen Tip oder sieht meinen Fehler auf Anhieb:

Code

program PVS_I2C;
{$NOSHADOW}
{ $WG}                     {global Warnings off}

Device = mega1280, VCC=5;
{ $BOOTRST $0F000}         {Reset Jump to $0F000}

Define_Fuses
  Override_Fuses;
  NoteBook       =  E;
  LockBits0      =  [];
  FuseBits0      =  [];
  FuseBits1      = [SPIEN, JTAGEN, OCDEN];
  ProgMode       =  JTAG;
  
Import SysTick, SerPort, {SwitchPort1,} I2Cport, TickTimer, TWImaster, SysLEDblink, {SPIdriver,} ADCPort {, SPIdriver1};


From System Import LongWord;


Define
  ProcClock      = 16000000;       {Hertz}
  SysTick        = 10;             {msec}
  StackSize      = $0064, iData;
  FrameSize      = $0064, iData;
//  SPIorder       = MSB;
//  SPIcpol        = 1;
//  SPIcpha        = 1;
//  SPIpresc       = 1; // presc = 0..3 -> 4/16/64/128
//  SPI_SS         = true; //  use SS pin as chipselect
//  SPImode        = 0; // 0, 1, 2, 3
  SerPort        = 57600, Stop1;    {Baud, StopBits|Parity}
  RxBuffer       = 8, iData;
  TxBuffer       = 8, iData;
  I2Cport        = PortD;
  I2Cdat         = 1;
  I2Cclk         = 0;
  TWIpresc       = TWI_BR100;
  TickTimer      = Timer1;
  SysLEDblink    = 50;
  SysLedPort     = @BlinkRam, $00; // byte-var, polarity (*4*)
  ADCchans       = 8, iData, int2;        // = [n], iData; = [m,n], iData;
  ADCpresc       = 128;
//  SPIdriver1 = PortC, 0, 1, 2, 3; // SCK, MOSI, MISO, SS
//  SPIorder1 = MSB;
//  SPIcpol1 = 1;
//  SPIcpha1 = 1;



Implementation

{$IDATA}

{--------------------------------------------------------------}
{ Type Declarations }

type
TimeBlock    = record
                 ok       : boolean;
                 sekunde  : byte;
                 minute   : byte;
                 stunde   : byte;
                 tag      : byte;
                 wochentag: byte;
                 monat    : byte;
                 jahr     : byte;
                 strzeit  : string[8];
                 strdatum : string[10];
                 strtag   : string[3];
               end;

// IO Handler
//
IOHandler =   record
                 Input      :  array[0..2] of InputData; // Input
                 Output     :  array[0..2] of OutputData; // Output
                 InLinie    :  array[1..8] of InputLinie; // Alarmlinie
                 LinieX     : integer;  //AktuellerAbfragezähler
               end; // Ende Record

// Onboard IO's
//
InputDataBoard =    record
                      RunStop     : InputPin;
                      SoftReset   : InputPin;
                      ServTast    : InputPin;
                      MMCInsert   : InputPin;
                    end; // Ende Record

{--------------------------------------------------------------}
{ Const Declarations }
const
 // Wochentage
  wDayArr  : array[0..6] of string[2] = ('SO', 'MO', 'DI', 'MI', 'DO', 'FR', 'SA');

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
// Output
   OUT_LED_ERR [@PortH, 2 ] : bit;
   OUT_LED_RUN [@PortH, 3 ] : bit;
   OUT_LED_COM [@PortH, 4 ] : bit;
   OUT_LED_OK  [@PortH, 5 ] : bit;

// Input
   IN_RUNSTOP           [@PINJ, 3 ] : bit;
   IN_SOFTRESET         [@PINJ, 4 ] : bit;
   IN_SERVTAST          [@PIND, 4 ] : bit;
   IN_MMCINSERT         [@PINB, 4 ] : bit;

// Standard VAR
  sel            : byte;
  y              : integer;
  x              : integer;
  wert           : integer;
  check          : boolean;
  Elapsed        : boolean;
  w              : byte;
  idx, i         : byte;
  BLINK          : boolean;
  ZeitBlock      : TimeBlock; // Datum Zeitblock
  UhrZyklus     : longint;
  LinieZyklus   : integer; //Abfragezyklus Alarmline
  OKZyklus      : integer;
  COMZyklus      : integer;
  strBuffer     : string[15];
  intBuffer     : integer;
  byteBuffer    : Byte;
  IO_Reg    : IOHandler; // IO Registerhandler
  IO_Board      : InputDataBoard;

// Sysstatusvariablen
SysRUN  : boolean;



{--------------------------------------------------------------}
{ functions }

procedure UhrZeit;
var
 buffer : byte;
begin
UhrZyklus:=UhrZyklus+1;
//nur alle 205000mal abfragen
 if UhrZyklus >= 205000 then
  UhrZyklus:=0;
  
  // Prüfe ob RTC schon überprüft wurde
  if not(ZeitBlock.ok) then
     ZeitBlock.ok:= TWIstat(DS1307);
      if ZeitBlock.ok then
        WriteLn(serout, 'Uhr vorhanden.');
       TWIout(DS1307, 00);             // prepare read register 0
        TWIinp(DS1307, ZeitBlock.sekunde);
         buffer:= ZeitBlock.sekunde;
          if not( buffer.7 )  then                                // low voltage bit set??
           TWIout(DS1307, 00, 00);
               TWIout(DS1307, 00, 00);                       // write to register 0, set run mode
               TWIout(DS1307, 01, 00);                       // write to register 1, no ints
               TWIout(DS1307, 02, 00);                       // write to register 2, reset seconds
               TWIout(DS1307, 03, $12);                      // write to register 3, reset minutes
               TWIout(DS1307, 04, $19);                      // write to register 4, set 18hrs
               TWIout(DS1307, 05, $18);                      // write to register 5, set day 19
               TWIout(DS1307, 06, 04);                       // write to register 6, set thursday
               TWIout(DS1307, 07, $06);                      // write to register 7, set june
               TWIout(DS1307, 08, 09);                       // write to register 8, set year 2003

        endif;
      endif;
  else // Uhr ist vorhanden und läuft
    WriteLn(serout, 'Uhr läuft schon ?.');
    TWIout(DS1307, 00);                             // prepare read register 0 = seconds
    TWIinp(DS1307, ZeitBlock.sekunde);
    ZeitBlock.sekunde:= ZeitBlock.sekunde and $7F;
    
    TWIinp(DS1307, ZeitBlock.minute);
    ZeitBlock.minute:= ZeitBlock.minute and $7F;
    
    TWIinp(DS1307, ZeitBlock.stunde);
    ZeitBlock.stunde:= ZeitBlock.stunde and $3F;
    
    TWIinp(DS1307, ZeitBlock.wochentag);
    ZeitBlock.wochentag:= ZeitBlock.wochentag and $07;

    TWIinp(DS1307, ZeitBlock.tag);
    ZeitBlock.tag:= ZeitBlock.tag and $3F;

    TWIinp(DS1307, ZeitBlock.monat);
    ZeitBlock.monat:= ZeitBlock.monat and $1F;
    
    TWIinp(DS1307, ZeitBlock.jahr);
    
    // Erzeuge die Strings
     ZeitBlock.strzeit:= ByteToHex(ZeitBlock.stunde)+':'+ByteToHex(ZeitBlock.minute)+':'+ByteToHex(ZeitBlock.sekunde);
     ZeitBlock.strdatum:= ByteToHex(ZeitBlock.tag)+'.'+ByteToHex(ZeitBlock.monat)+'.20'+ByteToHex(ZeitBlock.jahr);
     ZeitBlock.strtag:= wDayArr[ZeitBlock.wochentag];

  endif;
     WriteLn(serout, 'DEBUG: Tag: '+ZeitBlock.strtag+'  Datum: '+ ZeitBlock.strdatum+' Zeit: '+ZeitBlock.strzeit );

 endif; // UhrZyklus
end;

procedure InitPorts;
begin
// OUT_LED_ERR
DDRH.2 := 1;        // Ausgang
PortH.2 := 0;       // schalte auf 0
// OUT_LED_RUN
DDRH.3 := 1;        // Ausgang
PortH.3 := 0;       // schalte auf 0
// OUT_LED_COM
DDRH.4 := 1;        // Ausgang
PortH.4 := 0;       // schalte auf 0
// OUT_LED_OK
DDRH.5 := 1;        // Ausgang
PortH.5 := 0;       // schalte auf 0

// IN_RUNSTOP
DDRJ.3 := 0;        // Eingang
PortJ.3 := 1;       // Pullup EIN
// IN_SOFTRESET
DDRJ.4 := 0;        // Eingang
PortJ.4 := 1;       // Pullup EIN
// IN_TAST1
DDRD.4 := 0;        // Eingang
PortD.4 := 1;       // Pullup EIN
//IN_MMCINSERT
DDRB.4 := 0;        // Eingang
PortB.4 := 1;       // Pullup EIN

end InitPorts;


{--------------------------------------------------------------}
{ Main Program }
{$IDATA}

begin
 // Bootvorgang...
  InitPorts;
   EnableInts;
  mDelay(400);
 WriteLn(serout, 'DEBUG: Systemboot abgeschlossen....');

mDelay(400); // Warte bis Eingangszustand ok und in Ruhe
 
// Zustand im RUN ? dann setze System in den Status SysRUN
   SysRUN:= IO_Board.RunStop.IBit;
    OUT_LED_RUN := not IO_Board.RunStop.IBit; // Schalte RUN LED entsprechend EIN/AUS

// Achtung ab hier LOOP!
loop

ReadInputOnboard; // Lese OnBoard IO's

// RunStop Auswertung
if (IO_Board.RunStop.IBitR or IO_Board.RunStop.IBitF) then // Flanke auswerten und Umschaltung
  OUT_LED_RUN := not IO_Board.RunStop.IBit;
   SysRUN:= IO_Board.RunStop.IBit;
endif;


// wenn System im RUN Zustand läuft es weiter
if SysRUN then
  OKLED; //Status LED
   UhrZeit; // RTC Uhrzeit holen



   endif; // Ende wenn kein RUN Zustand
  endloop; // Zyklus-Ende
end PVS_I2C.



Gruss
Thorsten
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 23.05.2011 - 12:22  ·  #2
Hat keiner eine Idee wegen den DEFINE?

Code

  I2Cport        = PortD; 
  I2Cdat         = 1; 
  I2Cclk         = 0; 
  TWIpresc       = TWI_BR100;


Gruß
Thorsten
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2133
Registered: 03 / 2003
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 23.05.2011 - 15:23  ·  #3
hallo thorsten,

leider nein, außer .....

- mach mal zwischen dem OUT und dem IN eine pause rein.
- du hast im import longword drin - ist das egal daß es longint auch gibt ? könnte es sein, daß der deine var uhrzykus als longword sieht und vorzeichenbedingt da was falsch läuft ?

hab so ein bauteil nicht in betrieb sonst wüßte ich es sicherlich :D

gruss
harry
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 23.05.2011 - 15:37  ·  #4
Hallo Thorsten,

Sie importieren I2Cport und TWImaster gleichzeitig. Macht wenig Sinn wenn nur das TWI benutzt wird. Die TWI Pins sind auf bestimmte Port Pins fixiert. Ein Port define dafür ist nicht notwendig, ebensowenig eine Initialisierung dieser Pins beim TWI!

rolf
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 25.05.2011 - 23:43  ·  #5
Hallo Rolf.

Quote by rh

Sie importieren I2Cport und TWImaster gleichzeitig. Macht wenig Sinn wenn nur das TWI benutzt wird. Die TWI Pins sind auf bestimmte Port Pins fixiert. Ein Port define dafür ist nicht notwendig, ebensowenig eine Initialisierung dieser Pins beim TWI!


OK, das sehe ich ja ein, hatte es auch mit und ohne "Port Define" probiert, aber leider mit dem selben Problem. Ich habe jetzt mal ein kleines Projekt in WinAVR-C erstellt.
Ärgerlicherweise läuft es da ohne Probleme, also kann ich die Hardware als Fehlerquelle ausschließen.

@Harry; Das mit den Pausenzeiten hat auch nichts gebracht.
Ok, Longint ist zwar vorzeichenbehaftet, aber das wird ja erst ab der Zahl "2147483647" wichtig, bis dahin dürfte es keinen Unterschied machen. Aber ich teste das nochmal mit einen kürzeren Zyklus und benutze da mal nur ein WORD 65535. Vieleicht kommt da das Übel her, beim handling mit dem LONGINT.

Gruss
Thorsten
mc-electronic
Benutzer
Avatar
Gender: n/a
Location: Sauerland NRW
Posts: 372
Registered: 03 / 2008
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 26.05.2011 - 09:47  ·  #6
Hallo Thorsten,

habe mal über Deine Routinen drübergesehen, da finde ich grundsätzlich nichts falsches. Andererseits: TWI und I2C unter AVRco läuft eigentlich zuverlässig.
Was mir auffällt:
1. Frame ist $64. Könnte knapp sein, würde ich versuchsweise höher setzen ($200).
2. 10 k Pullup ist vielleicht etwas schwach, ich verwende 3k3.
3. MUSS das so sein, mit TWI und I2C? Ich bevorzuge I2CSoft, das läuft m.E. stabiler und man hat mehr Einstellmöglichkeiten.
4. Entrümple doch mal das Testprogramm, mach nur die UHRZEIT Abfrage im Loop und ein mDelay(1000) und sonst nichts. Dann muß ja jede Sekunde eine TWI-Abfrage kommen. Laß das mal mit der UhrZyklus Abfrage weg.

Und dann noch eine Anmerkung zum Dallas 1307: Ich weiß jetzt nicht, wo Deine Batterie-Pufferspannung herkommt. Der Dallas arbeitet da mit 3,5 V. Ich verwende einen ISL1208 (ist glaube ich Pinkompatibel), der kann bis 5 V Pufferspannung, dann kann man gut mit einem GoldCap arbeiten, der mit 5V geladen wird und spart sich die Lithium-Batterie. Der chip ist klasse und funktioniert bei mir sehr zuverlässig.

Gruß, Michael
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 26.05.2011 - 12:24  ·  #7
Hallo Michael.
Quote by mc-electronic

habe mal über Deine Routinen drübergesehen, da finde ich grundsätzlich nichts falsches. Andererseits: TWI und I2C unter AVRco läuft eigentlich zuverlässig.
Was mir auffällt:
1. Frame ist $64. Könnte knapp sein, würde ich versuchsweise höher setzen ($200).
2. 10 k Pullup ist vielleicht etwas schwach, ich verwende 3k3.
3. MUSS das so sein, mit TWI und I2C? Ich bevorzuge I2CSoft, das läuft m.E. stabiler und man hat mehr Einstellmöglichkeiten.
4. Entrümple doch mal das Testprogramm, mach nur die UHRZEIT Abfrage im Loop und ein mDelay(1000) und sonst nichts. Dann muß ja jede Sekunde eine TWI-Abfrage kommen. Laß das mal mit der UhrZyklus Abfrage weg.

Und dann noch eine Anmerkung zum Dallas 1307: Ich weiß jetzt nicht, wo Deine Batterie-Pufferspannung herkommt. Der Dallas arbeitet da mit 3,5 V. Ich verwende einen ISL1208 (ist glaube ich Pinkompatibel), der kann bis 5 V Pufferspannung, dann kann man gut mit einem GoldCap arbeiten, der mit 5V geladen wird und spart sich die Lithium-Batterie. Der chip ist klasse und funktioniert bei mir sehr zuverlässig.

Gruß, Michael


OK, das mit den 10K könnte ich mal testen, aber mit dem C-Programm läuft es ja. Die 10K habe ich deswegen gewählt, da im normalbetrieb eine Huckepack-Karte auf diese Leiterplatte gesteckt wird, dort befinden sich nochmal 10K Pullup, somit sollte das ganze im Normalbetrieb auf 5k laufen.

Ich habe eine kleine Batterie am DS laufen, die tests die ich mit den Goldcap hatte waren zu kurz, mehr als 3-4 Tage habe ich nicht hinbekommen, danach war das Datum usw. weg :(
Ich brauche die Uhrzeit und das Datum für Logbuchfunktionen, diese müssen stimmen, auch wenn die Anlage mal ein paar Tage abgeschaltet wird.

Weiterhin habe ich so meine Bedenken bei den Goldcap wegen der Lebendsdauer, mit jedem entladen wird doch die Kondensator-Schicht beschädigt. Die Batterien halten einige Jahre und
können von der Wartungsfirma leicht getauscht werden. Oder hast Du bessere Erfahrungen mit den Goldcaps (Lebendsdauer und Erhaltungszeit)?

Mit dem kleinen Testprogramm habe ich schon angefangen, aber ich werde mal den I2CSoft testen mit einem mDelay und den FRAME auf $200. Mal sehen was ich Heute Abend hinbekomme :)

Ich danke Dir schon mal.

Gruss
Thorsten
mc-electronic
Benutzer
Avatar
Gender: n/a
Location: Sauerland NRW
Posts: 372
Registered: 03 / 2008
Subject:

Re: I2C läuft nicht richtig

 · 
Posted: 26.05.2011 - 13:16  ·  #8
Hallo Thorsten,

zur Erhaltungszeit mit Goldcap habe ich ausführlich gemessen und komme auf 13-14 Tage. Ich verwende einen 220 000 µF Goldcap, 5V von Reichelt, der kostet 80 Cent. Der Dallas braucht ja auch nur wenig Strom, der ISL etwas mehr, so um die 800 nA bei 5 V - dafür kann er bis 1,8V runter und man kann einen weiteren Spannungsbereich nutzen. Wenn die Spannung dann runter geht, zieht der Chip auch weniger Strom. Man bekommt also einer flacher werdende Entladekurve. Ich habe in der Grafik die Messungen dann abgebrochen, Uhrzeit und Datum waren noch immer da.
Beim Dallas 1307 den SQW/OUT Pin abschalten (wenn Du ihn nicht brauchst), das Signal braucht im Batteriebetrieb auch noch bis zu 50 % mehr Strom. Einen grossen Vorteil hat der Dallas übrigens wegen seines 56 Byte RAM, so etwas kann nützlich sein. Ich konnte den Dalls nicht nehmen, weil er nur 100 kHz am I2C kann, das war zu wenig.
Der GoldCap wird über eine Schottky(!)-Diode und einen 680 Ohm Widerstand aufgeladen, dann dauert eine Ladung >30 Minuten.
Zur Lebensdauer kann ich nichts sagen, keine Erfahrung. Allerdings wird ja nur entladen, wenn das Gerät aus ist.. Hat jemand im Forum Erfahrung mit GoldCaps und Lebensdauer und Temperaturbeständigkeit?!

Gruß, Michael
Attachments
I2C läuft nicht richtig
Filename: entladekurve.jpg
Filesize: 148.22 KB
Title:
Download counter: 138
  • 1
  • 2
  • Page 1 of 2
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 16 · Cache Hits: 15   141   156 · Page-Gen-Time: 0.036512s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI