Forum: Mikrocontroller und Digitale Elektronik Atxmega TWI Daten in Bausteinregister schreiben


von Andi M. (lesockz)


Angehängte Dateien:

Lesenswert?

Hallo,

ich arbeite zur Zeit an einem Projekt mit dem Atxmega 128A1. Mit diesem 
versuche ich einen Zooming ADC der Firma Semtech (SX8723) anzusteuern.
Dazu benutze ich die TWI Funktionen die Atmel in AVR1308 bereitstellt.

mit der Funktion
1
uint8_t TWI_MasterWriteRead(uint16 sx8723_Register, uint8_t write_bytes ,uint8_t read_bytes)

ist das Auslesen eines Registers auch kein Problem
es erfolgt mit der Funktion
1
TWI_MasterWriteRead(sx8723_Register, 1,1)

 in der Reihenfolge

[Adresse Baustein][Register Adresse][D-Ack][Adresse Baustein][Antwort 
des SX][D-NACK]

soweit kein Problem ich schreibe das Register und lese nach der zweiten 
Adresse dessen Inhalt.

will ich jetzt jedoch Daten in ein Register des SX schreiben habe ich 
mit den mitgelieferten Funktionen nur die Möglichkeit
1
TWI_MasterWriteRead(sx8723_Register, 2,0)

das heißt 2 Byte schreiben
sieht dann auf dem TWI Bus folgendermaßen aus

[Adresse Baustein][Register Adresse][D-Ack][Daten an den SX][D-ACK]

der Baustein benötigt aber zum Schreiben der Daten das Format

[Adresse Baustein][Ack][Register Adresse][D-Ack][Start][Adresse 
Baustein][Ack][Daten an den SX][ACK]

Habe noch zwei Bilder angehangen
Bild 1: so sieht meine Übertragung zur Zeit aus
Bild 2: So ist es beim SX vorgesehen
zip: AVR1308 Application Note

Die Funktion TWI_MasterWriteRead
sieht folgendermaßen aus:
1
bool TWI_MasterWriteRead(TWI_Master_t *twi,
2
                         uint8_t address,
3
                         uint8_t *writeData,
4
                         uint8_t bytesToWrite,
5
                         uint8_t bytesToRead)
6
{
7
  /*Parameter sanity check. */
8
  if (bytesToWrite > TWIM_WRITE_BUFFER_SIZE) {
9
    return false;
10
  }
11
  if (bytesToRead > TWIM_READ_BUFFER_SIZE) {
12
    return false;
13
  }
14
15
  /*Initiate transaction if bus is ready. */
16
  if (twi->status == TWIM_STATUS_READY) {
17
18
    twi->status = TWIM_STATUS_BUSY;
19
    twi->result = TWIM_RESULT_UNKNOWN;
20
21
    twi->address = address<<1;
22
23
    /* Fill write data buffer. */
24
    for (uint8_t bufferIndex=0; bufferIndex < bytesToWrite; bufferIndex++) {
25
      twi->writeData[bufferIndex] = writeData[bufferIndex];
26
    }
27
28
    twi->bytesToWrite = bytesToWrite;
29
    twi->bytesToRead = bytesToRead;
30
    twi->bytesWritten = 0;
31
    twi->bytesRead = 0;
32
33
    /* If write command, send the START condition + Address +
34
     * 'R/_W = 0'
35
     */
36
    if (twi->bytesToWrite > 0) {
37
      uint8_t writeAddress = twi->address & ~0x01;
38
      twi->interface->MASTER.ADDR = writeAddress;
39
    }
40
41
    /* If read command, send the START condition + Address +
42
     * 'R/_W = 1'
43
     */
44
    else if (twi->bytesToRead > 0) {
45
      uint8_t readAddress = twi->address | 0x01;
46
      twi->interface->MASTER.ADDR = readAddress;
47
    }
48
    return true;
49
  } else {
50
    return false;
51
  }
52
}

von Andi M. (lesockz)


Angehängte Dateien:

Lesenswert?

Hab jetzt eine "Lösung" gefunden

in dem ich den in der AppNote gegebenen Code für meinen Bedarf angepasst 
habe.
1
bool TWI_MasterWriteRegisterData(TWI_Master_t *twi,uint8_t address,uint8_t *writeRegister,uint8_t *writeData,uint8_t bytesToWrite)
2
{
3
  
4
  /*Parameter sanity check. */
5
  if (bytesToWrite > TWIM_WRITE_BUFFER_SIZE) {
6
    return false;
7
  }
8
9
  /*Initiate transaction if bus is ready. */
10
  if (twi->status == TWIM_STATUS_READY) {
11
12
    twi->status = TWIM_STATUS_BUSY;
13
    twi->result = TWIM_RESULT_UNKNOWN;
14
15
    twi->address = address<<1;
16
17
    /* Fill write data buffer. */
18
    for (uint8_t bufferIndex=0; bufferIndex < bytesToWrite; bufferIndex++) 
19
      {
20
        twi->writeData[bufferIndex] = writeRegister[bufferIndex];
21
      }
22
23
    twi->bytesToWrite = bytesToWrite;
24
    twi->bytesToRead = 0;
25
    twi->bytesWritten = 0;
26
    twi->bytesRead = 0;
27
28
    /* If write command, send the START condition + Address +
29
     * 'R/_W = 0'
30
     */
31
    if (twi->bytesToWrite > 0) 
32
    {
33
      uint8_t writeAddress = twi->address & ~0x01;
34
      twi->interface->MASTER.ADDR = writeAddress;
35
    }
36
  
37
    while (twi->status != TWIM_STATUS_READY)
38
    {}
39
40
    for (uint8_t bufferIndex=0; bufferIndex < bytesToWrite; bufferIndex++) 
41
    {
42
      twi->writeData[bufferIndex] = writeData[bufferIndex];
43
    }
44
45
    twi->bytesToWrite = bytesToWrite;
46
    twi->bytesToRead = 0;
47
    twi->bytesWritten = 0;
48
    twi->bytesRead = 0;
49
50
    if (twi->bytesToWrite > 0) 
51
    {
52
      uint8_t writeAddress = twi->address & ~0x01;
53
      twi->interface->MASTER.ADDR = writeAddress;
54
    }
55
    while (twi->status != TWIM_STATUS_READY)
56
    {}
57
    return true;
58
  } 
59
  else 
60
  {
61
    return false;
62
  }
63
}

Leider entspricht das noch nicht ganz dem im Datenblatt vom SX8723 
geforderten Aufbau, da nach dem Address Ack noch ein Start Kommando 
gesendet wird was eigentlich entfallen sollte. Hat jemand eine Idee wie 
ich das machen kann?
Im Anhang seht ihr die momentane Übertragung.

Gruß Andi

von Sauger (Gast)


Lesenswert?

Moin,

Andi M. schrieb:
> Dazu benutze ich die TWI Funktionen die Atmel in AVR1308 bereitstellt.

Andi M. schrieb:
> mit den mitgelieferten Funktionen nur die Möglichkeit :
> TWI_MasterWriteRead(sx8723_Register, 2,0)

Andi M. schrieb:
> zip: AVR1308 Application Note

dir ist schon klar das "Application Note" ein allgemeines Beispiel 
darstellt das zeigt dass es geht, aber nicht auf deine speziellen 
Bedürfnisse eingeht?

MfG

von Andi M. (lesockz)


Lesenswert?

ja das ist es aber es passte in dem Fall halt schon ziemlich gut zu dem 
was ich wollte. Bis auf den kleinen Unterschied und ich wollte jetzt 
wissen ob es so wie ich es angepasst hab vernünftig ist oder ob man es 
noch "schöner" machen kann.

bzw. wie ich das mit der Stop Kondition noch verhindern kann

von Dominik M. (lauso)


Lesenswert?

Wo ist das Problem?
Du rufst die Funktion zweimal auf.
Zuerst  rufst Du die TWI_MasterWriteRegisterData auf.
und schreibst Du die Slave Adresse und Memory Adresse.
Dann wird im nächsten Funktionsaufruf Slave Adresse und Data 
geschrieben.
Wenn ich das richtig sehe sollte das Klappen.

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.