AVR Unterprogramm

OP #3151570
Lesenswert?

Guten Abend,

Bin noch recht neu in AVR und bin gerade dabei den PCF 8574P über das 
TWI und einem ATmega 32 zu programmieren. Die Ansteuerung über das TWI 
ist mir bereits  gelungen, jedoch funktioniert das ganze mit 
Unterprogrammen nicht.
Folgendes Problem:

Schreibe ich den Code so funktioniert alles perfekt:
1
 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <util/twi.h>
5

6
int main(void)
7
{
8

9
  while(1)
10
  {
11
      TWBR = 0x01;
12
      TWSR = (0<<TWPS1) | (0<<TWPS0);
13
      TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
14
      while (!(TWCR & (1<<TWINT)));
15
      TWDR = 0x40;
16
      TWCR = (1<<TWINT)|(1<<TWEN);
17
      while (!(TWCR & (1<<TWINT)));
18
      TWDR = 0x00;
19
      TWCR = (1<<TWINT)|(1<<TWEN);
20
      while (!(TWCR & (1<<TWINT)));
21
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
22
  }
23
        return 0;
24
}

jetzt wollte ich das ganze in mehrere Unterprogramme packen:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <util/twi.h>
4

5
void TWI_begin(void)
6
{
7
  TWBR = 0x01;
8
  TWSR = (0<<TWPS1) | (0<<TWPS0);
9
}
10

11
void TWI_send_start(void)
12
{
13
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
14
  while(!(TWCR & (1 << TWINT)));
15
}
16

17
void TWI_send_address(unsigned char add)
18
{
19
  TWDR = add;
20
  TWCR = (1<<TWINT) | (1<<TWEN);
21
  while(!(TWCR & (1<<TWINT)));
22
}
23

24
void TWI_send_data(unsigned char dat)
25
{
26
  TWDR = dat;
27
  TWCR = (1<<TWINT) | (1<<TWEN);
28
  while(!(TWCR & (1<<TWINT)));
29
}
30

31
void TWI_send_stop(void)
32
{
33
  TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
34
}
35

36

37
int main(void)
38
{
39
  while(1)
40
  {
41
    TWI_begin();
42
    TWI_send_start();
43
    TWI_send_address(0x40);
44
    TWI_send_data(0x00);
45
    TWI_send_stop();
46
  }
47
  return 0;
48
}

Allerdings funktioniert dieses nicht und ich komme nicht auf den Fehler 
:(
Ich bitte um eure Hilfe
Gast #3151576
Lesenswert?

Analytisch ist es nicht besonders wertvoll nur festzustellen, das es 
nicht funktioniert. Wesentlich wertvoller wäre es zu beschreiben, was 
nicht funktioniert, an welcher_ Stelle im Code und _woran Du das genau 
bemerkst.
Gast #3151589
Lesenswert?

>anscheinend...

Bitte noch präziser. Welches Ereigniss bzw. das Ausbleiben welchen 
Ereignisses konkret vermittelt Dir den Anschein, das es dort hängen 
bleibt ?
Woran merkst Du das? Glaskugel, Pendel, Geomantie, Wahrsagerei? :-)
Gast #3151597
Lesenswert?

Braucht Dir nicht leid tun.

>Da das Programm an dieser Stelle nicht mehr weiterläuft und in dieser
>Schleife bleibt.

Aha. Und wie, auf welche Weise, mit welchen Mitteln stellst Du das fest?
Kartenlegen, Orakel, Innereien-Schau?
OP #3151605
Lesenswert?

Mit der Noobmethode, dass ich einfach ein LED einmal vor der Schleife 
und einmal nach der Schleife am Port D eingeschaltet habe und dabei 
bemerkt habe, dass der Befehl vor der Schleife ausgeführt wird, danach 
allerdings nicht mehr und auch im folgenden Programmteil wird nichts 
mehr ausgeführt.
Gast #3151613
Lesenswert?

>...dass ich einfach ein LED einmal vor der Schleife
>...und einmal nach der Schleife am Port D eingeschaltet habe

Gut. Das hätte schon mal ins erste Posting gehört, dann braucht man 
nicht erst nachzufragen.
Wir können nicht ohne Zauberei einzusetzen, einschätzen ob eine 
Behauptung auf konkreten Informationen beruht oder nur auf Annahmen.

Was hast Du an Werkzeugen? JTAG-Debugger? (z.B. JTAG-ICE MKII)

Spess hat ja schon das TWSR-Register erwähnt. Kannst Du feststellen, was 
darin steht? Etwa über den Debugger oder Ausgabe auf einen Port?
Hast Du die Beschreibung schon gelesen?
Gast #3151617
Lesenswert?

Es hängt auch davon ab, wie die Person einzuschätzen ist. Wenn Spess uns 
schreibt, das er in der while-Schleife hängen bleibt, dann glauben wir 
ihm das unbesehen (bis es ernste Anzeichen gibt, das es nicht so ist). 
Aber uns selbst und Unbekannten, glauben wir es erst wenn wir sicher 
sind und materielle Beweise dafür vorliegen.
Nimm das Nachbohren also nicht so schwer. Ist nichts persönliches. Rein 
geschäftlich. :-)
OP #3151618
Lesenswert?

Ok hätte mir klar sein sollen :)

Programmiert wird über den Prog-s von Atmel auf dem Atmel 
Evaluationboard.
Ich werden es versuchen jedoch dachte ich das es sich um einen 
Anfängerfehler handelt, da das Programm ohne Unterprogramme einwandfrei 
funktioniert hat und danach, wo ich es doch nur aufgeiteil habe nicht 
mehr.
Gast #3151622
Lesenswert?

Hi

>Wenn Spess uns schreibt, das er in der while-Schleife hängen bleibt, dann
>glauben wir ihm das unbesehen ....

Da ich notorischer Assemblerprogrammierer bin, wäre das eher ein 
Anzeichen geistiger Umnachtung.

MfG Spess
Gast #3151628
Lesenswert?

>... dachte ich das es sich um einen Anfängerfehler handelt ...

Nein, tut es wohl nicht. Sei beruhigt. Falls ich nichts übersehen habe, 
sollte der Code eigentlich genauso funktionieren. Du hast ja lediglich 
die Zeilen aus der While-Schleife in Funktionen gepackt.

Dieser "Prog S" ist mitnichten von Atmel sondern von DIAMEX. (Immer 
schön genau hingucken, gelle :-) )
Damit kannst Du leider nicht debuggen.

Es bleibt also nur, das TWSR-Register irgendwie auszugeben. Serielle 
Schnittstelle, Port, Display oder sonstwie.

Was hast Du an Messmitteln? Multimeter? Oszilloskop? Aber zur Not gehts 
auch mit ner LED.
OP #3151688
Lesenswert?

So habe jetzt das TWSR zu meinem Erstaunen erfolgreich ausgelesen und zu 
meiner Überraschung konnte ich keine Fehler entdecken.
Hab das Register mit 5 LED's ausgelesen.
Ich poste hier noch schnell den Code mit Ergebnissen:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <util/twi.h>
4

5
void TWI_begin(void)
6
{
7
  TWBR = 0x01;
8
  TWSR = (0<<TWPS1) | (0<<TWPS0);
9
}
10

11
void TWI_send_start(void)
12
{
13
  int x = 4;
14
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
15
  while(!(TWCR & (1 << TWINT)));
16
  for(int i=7; i>=3; i--)
17
  {
18
    PORTD |= ((TWSR>>i) & 0x01) << x;    //Ergebnis: 0b0000 1xxx --> 0x08 --> A START condition has been transmitted 
19
    x--;
20
  }
21
  _delay_ms(1000);
22
  PORTD = 0x00;
23
  _delay_ms(1000);
24
}
25

26
void TWI_send_address(unsigned char add)
27
{
28
  int x = 4;
29
  TWDR = add;
30
  TWCR = (1<<TWINT) | (1<<TWEN);
31
  while(!(TWCR & (1<<TWINT)));
32
  for(int i=7; i>=3; i--)
33
  {
34
    PORTD |= ((TWSR>>i) & 0x01) << x;    //Ergebnis: 0b0010 0xxx --> 0x20 --> SLA+W has been transmitted NOT ACK has been received
35
    x--;
36
  }
37
  _delay_ms(1000);
38
  PORTD = 0x00;
39
  _delay_ms(1000);
40
}
41

42
void TWI_send_data(unsigned char dat)
43
{
44
  int x = 4;
45
  TWDR = dat;
46
  TWCR = (1<<TWINT) | (1<<TWEN);
47
  while(!(TWCR & (1<<TWINT)));
48
  for(int i=7; i>=3; i--)
49
  {
50
    PORTD |= ((TWSR>>i) & 0x01) << x;    //Ergebnis: 0b0011 0xxx  --> 0x30 --> Data byte has been transmitted NOT ACK has been received
51
    x--;
52
  }
53
  _delay_ms(1000);
54
  PORTD = 0x00;
55
  _delay_ms(1000);
56
}
57

58
void TWI_send_stop(void)
59
{
60
  TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
61
}
62

63

64
int main(void)
65
{
66
  DDRD = 0xFF;
67
  while(1)
68
  {
69
    TWI_begin();
70
    TWI_send_start();
71
    TWI_send_address(0x40);
72
    TWI_send_data(0x00);
73
    TWI_send_stop();
74
  }
75
  return 0;
76
}

Ich konnte auch kein hängen an der Schleife entdecken.
Das Programm läuft ohne Probleme durch nur Funktioniert es nicht :(
Defekt am Portexpander ist auszuschließen, das es mit dem anderen 
Programm ohne Probleme funktioniert.
Gast #3151844
Lesenswert?

Nun ja. Du hast gerade mehrere Sachen auf einmal geändert, was Die 
Ursache dafür sein kann, das sich das Verhalten geändert hat.

Nimm zunächst mal die delays raus. Auch den Port brauchst Du nicht auf 
Null zu setzen. (Denke ich).

Auch diese Schleife ist unnötig kompliziert.
1
void TWI_send_data(unsigned char dat)
2
{
3
  // int x = 4;
4
  TWDR = dat;
5
  TWCR = (1<<TWINT) | (1<<TWEN);
6
  while(!(TWCR & (1<<TWINT)));
7
  // for(int i=7; i>=3; i--)
8
  //{
9
    PORTD TWSR & 0xF8;
10
  //  x--;
11
  //}
12
  //_delay_ms(1000);
13
  //PORTD = 0x00;
14
  //_delay_ms(1000);
15
}

Ändere das auch in den anderen Funktionen.

Vielleicht ist das mit den Ausgaben allein nicht hinreichend. Schau Dir 
mal die Codebeispiele im Datenblatt an. Dort wird bei den entsprechenden 
Bedingungen zu Fehlern verzweigt. Vielleicht ist es besser dort 
entsprechende Portbits zu setzen und in einen Endlos-Schleife zu gehen.

Fehlendes ACK ist natürlich ungünstig.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren