Forum: Mikrocontroller und Digitale Elektronik XMEGA & TWI -> Lese Problem


von Jan H. (janiiix3)


Lesenswert?

Moin Moin,

habt ihr ne Idee, wieso ich vom Slave nichts empfange? Senden klappt..
Ist was an der Lese Routine falsch?

Es handelt sich um einen I2C Touch Controller (QT2120 von ATMEL)..
Habe einen Pin als GPIO konfiguriert und dort ne LED angeschlossen. 
Diese kann ich an und aus schalten. Die ID lesen von dem Chip schlägt 
jedoch fehl.
1
uint8_t twi_read(TWI_t *twi, uint8_t slave_addr, uint8_t reg)
2
{
3
  uint8_t ret=0;
4
  
5
//   twi->MASTER.ADDR = (slave_addr<<1);
6
//   while(!(twi->MASTER.STATUS&TWI_MASTER_WIF_bm));
7
//  
8
//   twi->MASTER.ADDR = reg;
9
//   while(!(twi->MASTER.STATUS&TWI_MASTER_WIF_bm));
10
//  
11
//  
12
//   twi->MASTER.ADDR = ((slave_addr<<1)|0x01);
13
//   while(!(twi->MASTER.STATUS & TWI_MASTER_RIF_bm));
14
//  
15
//   ret = twi->MASTER.DATA;
16
//  
17
//   twi->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
18
19
20
  twi->MASTER.ADDR = slave_addr<<1 & ~0x01;
21
  while (!(twi->MASTER.STATUS & TWI_MASTER_WIF_bm) || (twi->MASTER.STATUS & TWI_SLAVE_RXACK_bm));
22
  twi->MASTER.DATA = reg;
23
  while (!(twi->MASTER.STATUS & TWI_MASTER_WIF_bm));
24
25
  twi->MASTER.ADDR = slave_addr | 0x01;
26
  while (!(twi->MASTER.STATUS & TWI_MASTER_RIF_bm));
27
  ret = twi->MASTER.DATA;
28
  TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
29
30
  return ret;
31
}

von Bastian W. (jackfrost)


Lesenswert?

Laut DB will der QT2120 nach senden der Slave und Mem. Adresse einen 
Stop und dann einen Start, und nicht einen weiteren Start.

Gruß JackFrost

von jim_quakenbush (Gast)


Lesenswert?

Bastian W. schrieb:
> und nicht einen weiteren Start.

Nicht ganz:

6.   The host must then send a STOP and a START condition followed by 
the
     slave address again but this time accompanied by the READ bit.


Note:

     Alternatively, instead of step 6, a repeated START can be sent so 
the
     host does not need to relinquish control of the bus.

von Bastian W. (jackfrost)


Lesenswert?

jim_quakenbush schrieb:
> Bastian W. schrieb:
>> und nicht einen weiteren Start.
>
> Nicht ganz:
>
> 6.   The host must then send a STOP and a START condition followed by
> the
>      slave address again but this time accompanied by the READ bit.
>
>
> Note:
>
>      Alternatively, instead of step 6, a repeated START can be sent so
> the
>      host does not need to relinquish control of the bus.


Ok die Anmerkung hab ich überlesen.
@TO

Kannst du nach dem lesen wieder schreiben , oder verlierst du danach die 
Abitration ?

Ich hab die TWI Register nicht im Kopf, hast du Automatik für ACK/NACK 
beim lesen an ? Hast du
Bei dem Byte das du gelesen hast ein NACK vor dem Stop gesendet ?

Gruß JackFrost

Hast du einen LA um zu schauen ob das alles richtig gesendet wird ?

von Fabian D. (Gast)


Lesenswert?

Bastian W. schrieb:
> Kannst du nach dem lesen wieder schreiben , oder verlierst du danach die
> Abitration ?

Ich toggle die LED an einem der GPIOS hin und her. Und danach lese ich. 
Das Schreiben klappt.

Bastian W. schrieb:
> ch hab die TWI Register nicht im Kopf, hast du Automatik für ACK/NACK
> beim lesen an ? Hast du Bei dem Byte das du gelesen hast ein NACK vor
> dem Stop gesendet ?

Ich habe oben im auskommentierten Teil, zum Schluss einen NACK gesendet. 
Hat leider auch nichts gebracht.

von jim_quakenbush (Gast)


Lesenswert?

Hast Du Pullups an SDA, SCL, CHANGE und RESET?

von Bastian W. (jackfrost)


Lesenswert?

Fabian D. schrieb:
> Ich toggle die LED an einem der GPIOS hin und her. Und danach lese ich.
> Das Schreiben klappt.

Das geht also auch dauerhaft, also nach dem ersten Zyklus lesen geht das 
schreiben wieder ohne Probleme ?

Mit der Funktion lese ich bei einem Atxmega E Daten aus einem FRAM mit 
aus.

Page_adress ist die Slave ID und Adress ist die Addresse der 
Speicherzelle.

Der Block mit dem PortC ist noch nicht dynamisch, da ich da noch keine 
Arbeit reingesteckt hatte. Btw. das ist von einem C++ Projekt. Wenn du 
also nicht TWIC nutzt musst du da noch den Port ändern.
1
void twi_read(TWI_t *twiname, uint8_t *readData,uint8_t page_adress, uint8_t Adress, uint8_t bytes)
2
{
3
  twiname->MASTER.CTRLC &= ~((1<<TWI_MASTER_ACKACT_bp));
4
  twiname->MASTER.ADDR = page_adress;
5
  while (!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
6
  if(twiname->MASTER.STATUS & (1<<TWI_MASTER_ARBLOST_bp))
7
  {
8
    twiname->MASTER.CTRLA = 0;
9
    PORTC.DIRSET = PIN1_bm;
10
    for(uint8_t i=0;i<9;i++)
11
    {
12
      PORTC.OUTSET = PIN1_bm;
13
      _delay_us(20);
14
      PORTC.OUTCLR = PIN1_bm;
15
      _delay_us(20);
16
    }
17
    PORTC.DIRCLR = PIN1_bm;
18
    twiname->MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
19
    twiname->MASTER.STATUS = TWI_MASTER_ARBLOST_bm | TWI_MASTER_BUSERR_bm;
20
    twiname->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
21
    twiname->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
22
    twiname->MASTER.ADDR = page_adress;
23
    while (!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
24
  }
25
  twiname->MASTER.DATA = Adress;
26
  while (!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
27
  page_adress |= 0x01;
28
  twiname->MASTER.ADDR = page_adress;
29
  for(volatile uint8_t j=0 ;j<bytes ;j++){
30
    
31
    while(!(twiname->MASTER.STATUS&TWI_MASTER_RIF_bm));
32
    if(j == (bytes-1))
33
    {
34
      twiname->MASTER.CTRLC = (1<<TWI_MASTER_ACKACT_bp) | TWI_MASTER_CMD_STOP_gc;
35
    }
36
    readData[j] = twiname->MASTER.DATA;
37
  }
38
}

Gruß JackFrost

von Jan H. (janiiix3)


Lesenswert?

@JackFrost
Wieso aktiviert man in der Lesefunktion ständig das Interface? Das ist 
doch total unnötig?!...

von Bastian W. (jackfrost)


Lesenswert?

Das ist nur der Fall wenn die Abitration nicht da ist. Wenn z.b. Ein 
Reset beim lesen kam, dann ist der Slave noch im Lesemodus und man kann 
keinen Start mehr senden.

Dann wir das TWI Modul deaktiviert und es werden 9 Pulse über SCL 
gesendet.
SDA bleibt dabei High. Damit kommt mit dem letzten Bit wieder ein NACK 
und der Slave legt keine Daten mehr auf SDA.

Gruß JackFrost

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.