Forum: Mikrocontroller und Digitale Elektronik TWI Problem mit Timer0 Atmega8


von Roman (Gast)


Lesenswert?

Hallo zusammen,

Ich versuche einen Beschleunigungssensor mit TWI Schnittstelle 
auszulesen.
Ich will die Ergebnisse via UART im 50Hz Takt an den PC schicken.
Dazu nutze ich den Timer0 und eine if-Bedingung, etwa so:
1
#define timer0 TCNT0
2
3
uint8_t address = 0x1D;  //Adresse des Sensors
4
I2C Bus(100000);         //Instanz meiner TWI Klasse (100kHz Bitrate)
5
MMA8452Q Sensor(Bus);    //Instanz meiner Sensor Klasse
6
int Data[3];          //Speicher für Sensordaten
7
8
int main()
9
{
10
  init_timer0();
11
  init_UART();
12
  Sensor.init();
13
  while(1)
14
  {
15
  if(timer0 - 156 >= 0)  //50Hz Schleife
16
  {
17
    timer0 = 0;
18
    Sensor.update_state();  //hol Daten vom Sensor
19
    Sensor.get_state(Data); //speicher Daten in pointer
20
21
    UART_String("\r");
22
    for(int i = 0;i<3;i++)  //Ausgabe der Werte via UART
23
    {
24
      UART_int(Data[i]);
25
      UART_String("  ");
26
    }
27
28
29
  }
30
31
  }
32
33
34
  return 0;
35
}

Der Controller bleibt aber in einer while Schleife meiner TWI_Start 
Funktion hängen. Dieses Problem habe ich aber nur, wenn ich den Timer0 
benutze um meinen Code im 50 Hz Takt auszuführen. Wenn ich also im 
obigen Code die Bedingung:
1
if(timer0 - 156 >= 0)  //50Hz loop
weglasse, dann klappt alles prima.
Was für einen Zusammenhang gibt es denn zwischen dem TWI und Timer0?
Hier noch die TWI_Start Funktion, wo der Controller hängen bleibt:
1
uint8_t I2C::TWIM_Start (uint8_t address, uint8_t TWIM_Type)
2
{
3
  uint8_t    twst;
4
  /*
5
  ** Send START condition
6
  */
7
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
8
  /*
9
  ** Wait until transmission completed
10
  */
11
    while (!(TWCR & (1<<TWINT))){} !!!!!!hier bleibt der Controller hängen!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12
  /*
13
  ** Check value of TWI Status Register. Mask prescaler bits.
14
  */
15
    twst = TWSR & 0xF8;
16
    //UART_String("\n\rStatus:\n\r");
17
    //UART_int8(twst);
18
    //UART_String("\n\r");
19
    if ((twst != TWI_START) && (twst != TWI_REP_START)) return FALSE;
20
  /*
21
  ** Send device address
22
  */
23
    TWDR = (address<<1) + TWIM_Type;
24
    TWCR = (1<<TWINT)|(1<<TWEN);
25
  /*
26
  ** Wait until transmission completed and ACK/NACK has been received
27
  */
28
    while (!(TWCR & (1<<TWINT))){}
29
  /*
30
  ** Check value of TWI Status Register. Mask prescaler bits.
31
  */
32
    twst = TWSR & 0xF8;
33
    if ((twst != TWI_MTX_ADR_ACK) && (twst != TWI_MRX_ADR_ACK)) return FALSE;
34
35
    return TRUE;
36
}

Ich kann mir im Moment wirklich nicht vorstellen an was das Problem 
liegen könnte, hat jemand von euch eine Idee?

Liebe Grüsse,
Roman

von Karl H. (kbuchegg)


Lesenswert?

Roman schrieb:

> Was für einen Zusammenhang gibt es denn zwischen dem TWI und Timer0?

Keinen.

> Ich kann mir im Moment wirklich nicht vorstellen an was das Problem
> liegen könnte, hat jemand von euch eine Idee?

Zeig doch mal deine Timer Initialisierung.
Irgendwelche Interrupts freigegeben, für die es keine ISR gibt?

von Roman (Gast)


Lesenswert?

1
#include "TIMER.h"
2
#include <avr/io.h>
3
4
void init_timer0()
5
{
6
  TCCR0 |= (1<<CS02)|(1<<CS00);              //1024 prescaler
7
}

Nein, ich benutze sonst nirgends Interrupts.

von Nils N. (hagbard)


Lesenswert?

Hast du PullUps an den TWI Leitungen?
Sonst bleibt er gerne an der beschriebenen Bedingung hängen.
1
while (!(TWCR & (1<<TWINT))){} !!!!!!hier bleibt der Controller hängen!!!!!

Ich sehe auch nirgendwo ein sei() um die Interrupts einzuschalten.
Dann funktioniert das
1
if(timer0 - 156 >= 0)  //50Hz loop
nicht.

Nur so als Ideen. Hab mir den Code nicht so genau angesehen.

von Cyblord -. (cyblord)


Lesenswert?

Nils Nachname schrieb:

> Ich sehe auch nirgendwo ein sei() um die Interrupts einzuschalten.
> Dann funktioniert das
>
1
> if(timer0 - 156 >= 0)  //50Hz loop
2
>
> nicht.

Warum soll das ohne Interrupts nicht funktionieren?

von Karl H. (kbuchegg)


Lesenswert?

Nils Nachname schrieb:
> Hast du PullUps an den TWI Leitungen?

Gute Idee das zu kontrollieren.


> Ich sehe auch nirgendwo ein sei() um die Interrupts einzuschalten.
> Dann funktioniert das
>
1
> if(timer0 - 156 >= 0)  //50Hz loop
2
>
> nicht.

Doch. Tut es. Und zwar wegen
1
#define timer0 TCNT0

(persönliche halte ich das für keine gute Idee, aber ok.)

von Nils N. (hagbard)


Lesenswert?

Karl Heinz schrieb:
> Doch. Tut es. Und zwar wegen#define timer0 TCNT0
>
> (persönliche halte ich das für keine gute Idee, aber ok.)

Ach ja richtig, er benutzt ja gar keinen Overflow IRQ, sondern direkt 
den Zählerwert.
Dann ist es aber komisch, dass es ohne die if-Bedingung funktionieren 
soll.
Wie weit zählt denn der Timer?
Vielleicht wird die Bedingung nie wahr?!

von Roman (Gast)


Lesenswert?

Nils Nachname schrieb:
> Hast du PullUps an den TWI Leitungen?

Ja habe ich (10kOhm). Das TWI funktioniert ohne die if Anweisung auch 
immer problemlos.

Nils Nachname schrieb:
> Ich sehe auch nirgendwo ein sei() um die Interrupts einzuschalten.
> Dann funktioniert das if(timer0 - 156 >= 0)  //50Hz loop
> nicht.

Ok, habe ich etwas verpasst? Ich aktiviere den Timer0 und lasse ihn 
einfach hochzählen und wenn er grösser gleich 156 ist, dann setze ich 
ihn wieder auf null. Wofür brauche ich Interrupts???

von Roman (Gast)


Lesenswert?

Nils Nachname schrieb:
> Wie weit zählt denn der Timer?
> Vielleicht wird die Bedingung nie wahr?!

In die Schleife geht er, ich gebe nämlich in der TWI-Start Funktion in 
der while schleife immer einen satz via UART aus, aus diesem Grund sehe 
ich, dass er dort hängen bleibt.

von Nils N. (hagbard)


Lesenswert?

Ja, habe mich mit dem Timer vertan.
Dann habe ich leider spontan keine Idee.

von Roman (Gast)


Lesenswert?

Ich hatte mit dem gleichen Sensor schon mal ein ähnliches Problem, bei 
dem der Controller in der selben while Schleife hängen geblieben ist.
Das Problem trat dann auf, wenn man vom Sensor Daten über das TWI 
gelesen hat.
Die NACK Funktion (not acknowledge) muss man als Master anscheinend 
nicht nach dem letzen empfangenen Byte aufrufen, sondern schon nach dem 
zweitletzen Byte.
Für mich macht das wenig Sinn und ich verstehe es auch nicht.
Aber wenn man es nicht so macht, dann steckt der Controller genau wieder 
in der Schleife.
Hat jemand von euch schonmal das gleiche Problem gehabt?

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.