Forum: Compiler & IDEs ATMEGA644 und E2-Interface (i2c) hilfe


von fler (Gast)


Lesenswert?

Hallo

Da ich mehr in der SPS Programmierung tätig bin bin ich mit der 
Programmierung des Atmega644 nicht so vertraut und bitte euch um 
Ausführliche Hilfe.
Hardware: AVR-NET-IO Atmega32 auf Atmega644 getauscht.
Ich möchte den Temperatur Feuchte Sensor beiliegendes Datenblatt 
verwenden.
SDA und SCL müssen am PORTC.0 und PORTC.1 angeschlossen werden?
oder ist dies auch auf einem anderen Port möglich?

Nachdem ich den source Code von ROBUE Http Server in einer Abgespeckten 
version verwende bitte ich euch um hilfe bei der Implementierung des für 
den Sensor notwendigen C Code.

Ich habe die SW AVR-Studio und Winavr.

Ich bedanke mich im voraus.

von Erich F. (fler)


Angehängte Dateien:

Lesenswert?

Anscheind ist der Dateianhang nicht mitgegangen.

von Oliver (Gast)


Lesenswert?

Steht doch alles in deinem Dokument. Komplett mit Sourcode.

>4.3 Softwarefunktionen des E2 Interfacemoduls
>Die folgenden Funktionen ergeben, mit den Definitionen im Anhang, ein 
>vollständig kompilierbares E2-Interface Softwaremodul. Dieser Code kann sehr 
>einfach an den gewünschten Prozessor angepasst werden. Es sind dazu nur der 
>DELAY_FAKTOR, die HW-Pins und die gekennzeichneten Funktionen zu adaptieren.

as ist eine Softwareinplementierung des Protokolls, insofern kannst du 
deine Pins frei wählen.

Die delay-Funktionen musst du zwar anpassen, wie die beim WINAvr 
heissen, steht in der Doku zur avr-libc, zu finden auf deiner 
Festplatte.

Oliver

von Erich F. (fler)


Angehängte Dateien:

Lesenswert?

Danke für die rasche Antwort.
Jedoch hilft mir das nicht viel.
Da ich versucht habe dieses Programm zu implementieren.
Nachdem es nicht funktioniert bitte ich hier um Hilfe

von Oliver (Gast)


Lesenswert?

>Nachdem es nicht funktionier...

Es lässt sich so sicherlich noch nicht einmal kompilieren.

Zunindest ein
1
#include <avr/io.h>

sollte da schon drin vorkommen. Oben links im Menu gibt es ein Tutorial 
zum avr-gcc. Da stehen die wichtigsten Grundlagen drin.

Oliver

von Erich F. (fler)


Lesenswert?

Ja ist includiert, ich habe nur einen teil mit den Funktionen aus der 
main.c herauskopiert ich sehe auch mit dem Osci das Protokoll
jedoch werden keine Daten eingelesen und in die float RH bzw Float 
temperature geschrieben. Ich denke das er die einzellnen bit nicht lesen 
kann.
Mfg
Erich

von Oliver (Gast)


Lesenswert?

>ich habe nur einen teil mit den Funktionen aus der main.c herauskopiert

In dem Fall steckt der Fehler in Zeile 42.


Vermutlich aber eher hier:
1
#define SDA (*(volatile struct test*)&PORTA).b1

Solange du nicht verstehst, was du da machst, schmeiß diese Macros raus. 
avr-gcc kann keine Einzelbits ansprechen, und dabei sollte man es 
belassen.

Denn:
>Ich denke das er die einzelnen bit nicht lesen kann.

könnte daran liegen, daß man beim AVR IO-Pins über PINX liest, nicht 
über PORTX. Insofern macht
1
unsigned read_SDA(void)
2
{
3
  return SDA;
4
} // read SDA-pin status
nicht das, was du möchtest.

Oliver

von Erich F. (fler)


Lesenswert?

Hallo

Ja, die PINA definition habe ich oben in der structur schon getestet.
jedoch vermutlich nicht richtig.
die Struct test funktioniert einwandfrei und arbeitet auch.
Habe ich mir mit dem osci angesehen.
ich denke auch das die funktion read_SDA einen wurm beinhaltet.
Aber würdest du mir schreiben wie dies richtig wäre, bitte?
für SDA und SCL verwende ich PORTA.1 und PORTA.2
die habe ich als Ausgang definiert.
Kann ich trotzdem PINA verwenden?

mfg
Erich

von SF (Gast)


Lesenswert?

Du steuerst SDA, SCL falsch an. Du must beim I²C-Bus wissen, das der 
High-Pegel auf dem Bus nur durch die externen Pull-Up-Widerstände 
erreicht wird. High-Pegel bedeuet also Port ist hochohmig geschaltet. 
Nur der Low-Pegel wird aktiv erzeugt. Somit must du folgende Routinen 
verwenden:

Irgendwo oben im Code
1
#define SDA 0 // SDA ist Bit 0
2
#define SDA_PORT PORTA
3
#define SDA_DDR  DDRA
4
#define SDA_PIN  PINA
5
6
#define SCL 1 // SDA ist Bit 1
7
#define SCL_PORT PORTA
8
#define SCL_DDR  DDRA
9
#define SCL_PIN  PINA
1
void set_SDA(void)
2
{
3
  // SDA hochohmig schalten, High pegel wird durch externen Pull-up
4
  // erreicht.
5
  SDA_DDR &= ~(1 << SDA);
6
}
7
8
void clear_SDA(void)
9
{
10
  // SDA auf low, es wird ausgenutzt, das das entsprechende PORTA Bit
11
  // defaultmäßig 0 ist. Somit wird hiermit aktiv low ausgegeben
12
  // obwohl nur der Port von Eingang(=hochohmig) auf Ausgang geschaltet wurde.
13
  SDA_DDR |= (1 << SDA);
14
}
15
16
unsigned read_SDA(void)
17
{
18
  // read SDA-pin status 
19
  return ( (SDA_PIN & (1<<SDA)) != 0);
20
} 
21
22
23
void set_SCL(void)
24
{
25
  // SCL hochohmig schalten
26
  SCL_DDR &= ~(1 << SCL);
27
}
28
29
void clear_SCL(void)
30
{
31
  // SCL auf low
32
  SCL_DDR |= (1 << SCL);
33
}

Flüchtigkeitsfehler bitte ignorieren  ...

von Erich F. (fler)


Lesenswert?

Hallo SF

Das war mir eine große Hilfe nun verstehe ich die funktionsweise.
Danke nochmals.
Ich konnte es noch nicht testen habe es jedoch schon compilier.
Werde ich am abend testen, ergebnis schreibe ich hier.
mfg Erich

von Oliver (Gast)


Lesenswert?

>die habe ich als Ausgang definiert.
>Kann ich trotzdem PINA verwenden?

Jein. Du kannst zwar über PINA den Zustand des Pins lesen, unabhängig 
davon, ob der Pin als Ein- oder Ausgang definiert ist, aber was genau 
dann da ansteht, wissen die Götter. I²C, und vermutlich auch dein 
komischer E2-Bus, basiert auf wired and. Wenn da ein Busteilnehmer eine 
Leitung auf Null zieht, muß die auch Null sein. Hochgehalten wird die 
nur durch die 10k-Pull-Ups (die du hoffentlich auch eingebaut hast).
1
temperature = -300; // default value (error code)
2
E2Bus_start();
3
E2Bus_send(0xA1); // MW2-low request
4
if (check_ack()==ACK)
5
{
6
   temp_low = E2Bus_read();
7
...

Der als Ausgang konfigurierte Pin SDA wird am Ende von E2Bus_send() auf 
Null gesetzt, und zieht damit die Leitung auf Null, und damit dürften 
dann nur noch Nullen gelesen werden.

Falls dieer E2-Bus ein I²C sein soll, ist sowieso die Logik (auch in dem 
Beispiel im der Application note) falsch rum. Eine Leitung ist aktiv, 
wenn sie aktiv auf Null gezogen wird, und nicht aktiv, wenn sie im 
tri-state-Zustand ist.

Probier mal (ungetestet, daher selber mitdenken erwünscht):
1
// in main.c
2
DDRA &=~ ((1<<PA1) | (1<<PA2));   // default: Bus-Pins sind Eingänge
3
PORTA = 0x00; // keine Pull ups für PA1 und PA2 einschalten
4
              // 10k-Pull-Up-Widerstände sind extern erforderlich !!!
5
6
...
7
8
void set_SDA(void)
9
{ 
10
   DDRA |= (1<<PA1); // setzt PA1 als Ausgang und zieht die Leitung auf Low
11
} 
12
13
void clear_SDA(void)
14
{
15
 DDRA &= ~(1<<PA1);  // setzt PA1 als Eingang, damit hochohmig, und gibt die Leitung frei
16
} 
17
18
bit read_SDA(void) // C kennt keinen Datentyp bit...
19
{ 
20
   DDRA &= ~(1<<PA1);  // setzt PA1 zur Sicherheit als Eingang, falls er das nicht schon ist 
21
                       //(da wäre dann aber ein Programmfehler an anderer Stelle)
22
23
   if (PINA &= (1<<PA1)) // liest den Leitungsstatus
24
      return 1;
25
   else
26
      return 0;
27
} 
28
29
void set_SCL(void)
30
{
31
   DDRA |= (1<<PA2); // setzt PA2 als Ausgang und zieht die Leitung auf Low} 
32
33
void clear_SCL(void)
34
{ 
35
   DDRA &= ~(1<<PA2);  // setzt PA2 als Eingang, damit hochohmig, und gibt die Leitung frei
36
}

Oliver

von Oliver (Gast)


Lesenswert?

...da war SF schneller :-)

Oliver

von Erich F. (fler)


Lesenswert?

Hallo

Danke Es lauft schon.
Habe grundsätzlich code von SF genommen.
Danke nocheinmal

mfg Erich

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.