Forum: Mikrocontroller und Digitale Elektronik Attiny1614 I²C Master


von MosKiller (Gast)


Lesenswert?

Hallo Techniker,

ich habe irgendwie ein Problem wo ich nicht mehr weiter komme.
Ich habe einen Attiny1614 im Einsatz. Dieser soll einen TC74 I²C 
Temperatursensor auslesen.

Irgendwie klappt bei mir kein I²C, ich habe keine Ahnung warum. Nach 
Datenblatt müsste es klappen wie ich das sehe.

Hat jmd. einen Rat für mich?


Momentan steht nichts im Programm, außer das er per I²C Lesen soll und 
dann das Ergebnis via Uart an den PC sendet. Uart klappt, da liegt das 
Problem def. nicht!

Ich rufe in der Main einfach die TC74_readTemp(void) auf mit einem Cast 
auf int8_t vorher. Auf dem Osci sehe ich auch nicht, das wirklich was 
gesendet wird. Da kommt einmal was und dann die ganze Zeit nichts mehr. 
Beide Leitungen Idle.


Prozessor läuft auf intermen Takt 20Mhz.



Das ist meine i2c.h
1
#define TW_WRITE  0    
2
#define TW_READ    1  
3
          
4
uint16_t timeout_cnt;
5
6
7
inline void i2c_init(uint32_t BAUD_RATE)
8
{
9
  TWI0.MBAUD = ((F_CPU / BAUD_RATE) / 2);
10
  TWI0.MCTRLA = (TWI_ENABLE_bm | TWI_TIMEOUT_DISABLED_gc);
11
  TWI0.MSTATUS = (0 << TWI_BUSSTATE0_bp);
12
}
13
inline void i2c_start(uint8_t slaveAddr, uint8_t _readMode)
14
{
15
  TWI0.MADDR = ((slaveAddr<<1) | _readMode);
16
17
  while (!(TWI0.MSTATUS & TWI_WIF_bm));
18
}
19
inline void i2c_send(uint8_t DataByte)
20
{
21
  TWI0.MDATA = DataByte;
22
23
  while (!(TWI0.MSTATUS & TWI_WIF_bm));
24
}
25
inline uint8_t i2c_receive(uint8_t ack)
26
{
27
  if (ack)  TWI0.MCTRLB |= TWI_ACKACT_ACK_gc;
28
29
  //while (!(TWI0.MSTATUS & TWI_RIF_bm));
30
        
31
  return TWI0.MDATA;
32
}
33
34
35
int8_t TC74_readTemp(void)
36
{
37
  int8_t temp = 0;
38
  
39
  i2c_start(0b01001000, TW_WRITE);
40
  i2c_send(0x00);
41
42
  i2c_start(0b01001000, TW_READ);
43
  temp = (int8_t)i2c_receive(0);
44
45
  return (temp);
46
}

von Stefan F. (Gast)


Lesenswert?

Brauchst du gar kein STOP Signal?

von MosKiller (Gast)


Lesenswert?

Stefanus F. schrieb:
> Brauchst du gar kein STOP Signal?

So wie ich das verstanden habe, macht der das automatisch nach dem 
lesen?!
Wunderte mich auch alles, ich finde das I²C recht friemelich beim neuen 
Tiny.

von Stefan F. (Gast)


Lesenswert?

> So wie ich das verstanden habe, macht der das automatisch
> nach dem lesen?!

Ich habe gerade mal das Datenblatt überflogen. Dort habe ich keinen 
Hinweis gefunden, dass das STOP Signal automatisch gesendet wird. Ich 
wüsste auch nicht wie das funktionieren soll, da der Master ja keine 
Ahnung hat, wie viele Bytes du lesen willst oder ob du nach dem Lesen 
eine Repeated-Start Condition senden willst.

I²C war in meinen Augen schon immer friemelig, auf allen 
Mikrocontrollern. Bei STM32 ist es noch komplizierter, da läuft keiner 
ohne Workarounds.

von Ingo L. (corrtexx)


Lesenswert?

MosKiller schrieb:
> Auf dem Osci sehe ich auch nicht, das wirklich was
> gesendet wird.
Externe Pull-Ups sind vorhanden?

von MosKiller (Gast)


Lesenswert?

Ingo L. schrieb:
> MosKiller schrieb:
>> Auf dem Osci sehe ich auch nicht, das wirklich was
>> gesendet wird.
> Externe Pull-Ups sind vorhanden?

Ja sind da.

von MosKiller (Gast)


Lesenswert?

Stefanus F. schrieb:
>> So wie ich das verstanden habe, macht der das automatisch
>> nach dem lesen?!
>
> Ich habe gerade mal das Datenblatt überflogen. Dort habe ich keinen
> Hinweis gefunden, dass das STOP Signal automatisch gesendet wird. Ich
> wüsste auch nicht wie das funktionieren soll, da der Master ja keine
> Ahnung hat, wie viele Bytes du lesen willst oder ob du nach dem Lesen
> eine Repeated-Start Condition senden willst.
>
> I²C war in meinen Augen schon immer friemelig, auf allen
> Mikrocontrollern. Bei STM32 ist es noch komplizierter, da läuft keiner
> ohne Workarounds.

Wie mache ich denn dann das Stop bit? Also ich finde das sehr 
undurchsichtig bei dem Tiny, habe da meine Probleme mit.

Uart hingegen ging problemlos komischerweise.

von Stefan F. (Gast)


Lesenswert?

> Wie mache ich denn dann das Stop bit?

Suche mal ein Tutorial. Ich habe diesen µC noch nie benutzt, deswegen 
kann da kaum was gutes bei herauskommen, wenn ich mir jetzt nur auf 
Basis des Datenblattes etwas aus den Fingern sauge und das nicht einmal 
teste.

von MosKiller (Gast)


Lesenswert?

Ich habe jetzt nochmal etwas rumgedoktort.
Irgendwie ist das seltsam. Also Stop kann man setzen, nach dem Lesen 
(wenn man ACK = 0 (NACK) hat, also nichts weiter mehr lesen möchte, 
macht der das Stop wirklich selber. Trzd. habe ich es manuell nochmal 
reingefügt.

Aber wo das eigentliche Problem liegt (keine Ahnung warum):
Das hintereinander senden, also erst Leseregister vom Slave setzen, 
danach auslesen (wie ich das beim Mega sonst auch gemacht habe), 
funktioniert hier nicht. Keine Ahnung warum, ob man da noch was 
einstellen muss. Kein Plan.

Ich mache es jetzt so, ich setze den Pointer vom TC74 einmal auf das 
Ausleseregister am Anfang, danach kann ich dauerhaft auslesen, das 
klappt.


Anbei mal mein Code, kann bestimmt jmd. noch gebrauchen/erweitern. 
Feedback habe ich nicht drin (Busfehler), brauche ich bei der Anwendung 
nicht. Ist nur der Temperatursensor am Bus dran.

1
#define TW_WRITE  0    
2
#define TW_READ    1  
3
4
5
inline void i2c_init(uint32_t BAUD_RATE)
6
{
7
  TWI0.MBAUD = ((F_CPU / BAUD_RATE) / 2);
8
  TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc;
9
  TWI0.MCTRLA = (TWI_ENABLE_bm | TWI_TIMEOUT_DISABLED_gc | TWI_QCEN_bm);
10
}
11
inline void i2c_start(uint8_t slaveAddr, uint8_t _readMode)
12
{
13
  TWI0.MADDR = (slaveAddr | _readMode);
14
}
15
inline void i2c_stop(void)
16
{
17
  TWI0.MCTRLB |= (1<<TWI_ACKACT_bp);    // Set acknowledge action to NACK
18
  TWI0.MCTRLB |= (TWI_MCMD_gm);      //Triggers Master to execute acknowledge action (NACK), succeeded by issuing STOP condition
19
}
20
inline void i2c_send(uint8_t DataByte)
21
{
22
  TWI0.MDATA = DataByte;
23
}
24
inline uint8_t i2c_receive(uint8_t ack)
25
{
26
  if (ack)  TWI0.MCTRLB &= ~(1<<TWI_ACKACT_bp);
27
  else    TWI0.MCTRLB |= (1<<TWI_ACKACT_bp);
28
    
29
  return TWI0.MDATA;
30
}
31
32
33
//Optional
34
int8_t TC74_readTemp(void)
35
{
36
  int8_t temp = 0;
37
38
   i2c_start(0b10010000, TW_READ);
39
   temp = (int8_t)i2c_receive(0);
40
  i2c_stop();  
41
42
  return (temp);
43
}
44
45
inline void TC74_setReadReg(void)
46
{
47
  i2c_start(0b10010000, TW_WRITE);
48
  i2c_send(0x00);
49
  i2c_stop();
50
}

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.