TWISlave

Mario
Benutzer
Avatar
Gender: n/a
Age: 50
Posts: 15
Registered: 06 / 2012
Subject:

TWISlave

 · 
Posted: 19.11.2013 - 13:00  ·  #1
Hallo zusammen,
ich habe bei einem Projekt eine Master-Slave Kommunikation über TWI-Schnittstelle zwischen 2 mega128. Dabei ist mir aufgefallen, dass der TWIStat Befehl im Slave nicht korrekt abgearbeitet wird. Es gibt hierzu auch schon ein paar Beiträge die dieses Verhalten auch beschreiben.
Nach dem Senden eines TWIStat wird der anschließende Befehl im TWISlave nicht korrekt verarbeitet. Schickt man 2 TWIStats hintereinander gehts. Da dieses Verhalten, im Forum schon ein paar Mal thematisiert wurde, aber nie wirklich gelöst, habe ich mir 2 Mini-Programme geschrieben, TWIMaster und TWISlave um das ganze genauer anschauen zu können. Desweitern habe ich mir das Assembler-File des Slaves nochmals genau durchgeschaut. Folgende Variablen werden in der "State-machine" des TWISlaves verwendet:

_TWISLRES - LastTWIStatus
_TWISLRWPTR - Read/Write Pointer to RX/TX Buffer
TWIRXBUFFER - TWI Rx Buffer
TWITXBUFFER - TWI TX Buffer

Im TWI_Interrupt wird zuerst überprüft, ob kein Fehler bei der Übertragung vorlag, d.h. TWSR <> 0. Ist dies der Fall wird anschließend anhand des letzten TWIStatus (_TWISLRES) weiterverfahren.
Normalerweise ist dieses nach einem kompletten Read oder Write Befehl 0. In meinem Projekt kann ich über die serielle Schnittstelle die unterschiedlichen Werte der Variablen auslesen. Schicke ich vom Master ein TWIOut(I2CAdd,Addr,Data), dann steht anschließend im _TWISLRES =0. Wird allerdings ein TWIStat(I2CADD) gesendet steht nachher in _TWISLRES = $A0. Dies ist laut Datenblatt der Statuscode für eine gesendete Stop Condition.
Nach erneutem Senden des TWIStat(I2CAdd) steht dann wieder _TWISLRES =0 drin. Und so weiter und so fort.
Um das noch genauer untersuchen zu können, habe ich mich mit
interrupt TWSI;
an den Interrupt angehängt. Wie zu Erwarten werden bei einem TWIStat 2 Interrupts ausgelöst. Nach dem Empfang der Adresse und nach dem Erkennen der StopCondition. Dier Erkennung der Stop Condition müsste aber eigentlich die Statemachine wieder zurücksetzen, was sie aber nicht tut. Und zwar aus folgendem Grund:
- Beim ersten Interrupt ist _TWISLRES=0 und TWIStatus = $60.
Dies bedeutet laut Datenblatt "Own SLA+W has been received;ACK has been returned"
Damit wird am Ende des Interrupts _TWISLRES = $60 gesetzt.
- Beim zweiten Interrupt (Stop Condition) ist _TWISLRES = $60 und TWIStatus = $A0

LDS _ACCB, _TWISLRES
CPI _ACCB, 00h
BREQ SYSTEM._L0051
CPI _ACCB, 060h
BREQ SYSTEM._L0052

.....
SYSTEM._L0052:
LDS _ACCB, TWDR
STS _TWISLRWPTR, _ACCB

Da aber in der Statemachine in diesem Fall der aktuelle Status gar nicht abgefragt wird, wird einfach das Datenregister in den Pointer gelesen, obwohl gar keine Daten da sind. Eigentlich müsste mit der Stop Condition die Statemachine zurück- und _TWISLRES = 0 gesetzt werden. Aber in diesem Fall wird _TWISLRES = $A0 gesetzt.

Es fehlt im Prinzip also der Fall eines SLA+W (TWIStat) ohne dass Daten hinterherkommen.

Die beiden Mini-Programme habe ich angehängt.

Gruß Mario
Attachments
Filename: TWI_MasterSlave.zip
Filesize: 1.64 KB
Title:
Download counter: 33
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: TWISlave

 · 
Posted: 21.11.2013 - 11:19  ·  #2
Hi,

Bug ist jetzt beseitigt.

rolf
golf
Benutzer
Avatar
Gender:
Location: Donauwörth
Age: 71
Posts: 256
Registered: 11 / 2009
Subject:

Re: TWISlave

 · 
Posted: 30.11.2013 - 05:51  ·  #3
Hallo rh,

ich nutze in einigen Projekten den TWI-Slave Treiber. nach dem letzten Update bekomme ich nur "internal assembler error" .
Wenn ich als Device Mega8,Mega16 oder Mega32 eingebe, dann lässt sich das Programm compilieren. bei größeren Atmels kommen die Fehlermeldungen.

program TWISlave;
{$NOSHADOW}
{ $WG} {global Warnings off}
Device = mega2560, VCC = 3.3;
Import SysTick,TWIslave; //
Define
ProcClock = 16000000; {Hertz}
SysTick = 5; {msec}
StackSize = $0064, iData;
FrameSize = $0064, iData;
TWImode = HandShake; // Transparent ;
TWIbuffer = 32, iData; {buffer/packet size}
TWIaddr = 34; {default slave address}
Implementation
{ Main Program }
{$IDATA}

begin
EnableInts;
TWIsetGC (false);
TWIsetslaveAddr ($22);
TWISetRDY(true);

loop
if TWIGetRxStat then
case TWIGetCMD of
1: nop; |
endcase;
endif;
endloop;

end TWISlave.


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

Re: TWISlave

 · 
Posted: 30.11.2013 - 20:11  ·  #4
Hallo golf,
das ist ein Kreuz mit den Bugfixes. :angry5:
Wenn man nicht immer alle Eventualitäten austestet........
Update am Montag.

rolf
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   81   96 · Page-Gen-Time: 0.039185s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI