Hallo zusammen,
ich nutze ein Atmega238p (genau genommen ist es hardwaremäßig ein
Arduino Nano), den ich ich allerdings in plain C (also nicht in
Arduino-Code) programmiere. Um den Verdrahtungsaufwand für verschiedene
Peripherie zu minimieren, möchte ich gerne mehrere PCF8574 Port-Expander
auf dem I2C-Bus einsetzen. Leider habe ich im Vorfeld noch nie mit dem
I2C-Bus gearbeitet, sodass auch der komplett neu für mich ist.
Ziel war es ursprünglich (und das ist auch noch immer das Fernziel), ein
4x20 LC-Display anzusteuern, was ich aber auch nach mehreren Stunden und
intensivem Googeln nicht hinbekommen habe. Die beiden Threads:
- Beitrag "HD44780 1602 LCD über I2C Modul ansteuern"
- Beitrag "I2CLCD Library für HD44780 LCDs"
sind mir bekannt.
Um Hardwarefehler auszuschließen habe ich dann Wohl oder Übel einmal
kurz den Arduino-Bootloader mittels meines AVRispMkII auf den Atmega
geflasht und einen Scan des I2C-Buses durchgeführt
(Beitrag "HD44780 1602 LCD über I2C Modul ansteuern"). Dieser zeigte mir, dass
sich ein Teilnehmer mit der Adresse 39 (dezimal) auf dem Bus befindet.
Dies zeigt zumindest, dass die Verdrahtung richtig ist und
Hardwarefehler weitestgehend auszuschließen sind.
Dass die von Arduino gefundene Adresse nicht direkt für die
Programmierung in plain C verwendet werden kann, ist mir bekannt (7-Bit-
vs. 8-Bit-Adresse mit R/W). Da aber zu diesem Zeitpunkt schon der
Bootloader geflasht war, habe ich auch direkt versucht das LCD
anzusteuern, was mit einer entsprechenden Bibliothek
(https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads) auch
äußerst zufriedenstellend verlief.
Ich bitte euch, diesen kleinen Umweg über die Arduino-IDE nicht falsch
zu verstehen. Das sollte lediglich zur Überprüfung der Hardware und
Verdrahtung dienen.
Für weitere Programmierung in plain C ist die Adresse des Expanders
erforderlich. Gemäß des Datenblatts des PCF8574 setzt sich diese aus
0b0100 sowie den Pegeln an den Pins A[0:2] zusammen. Da ich A[0:2] alle
auf VCC gezogen habe (ist im Breakout-Board schon so gemacht worden),
ergibt sich somit eine Adresse von 0b0100111x. Wobei x für das R/W-Bit
steht und zumindest bei der Adressangabe in der Arduino-Welt keine
direkte Beachtung findet und so zur Adresse 39 (dec) führt. Als
"komplette Schreibadresse" mit R/W-Bit ergibt sich schließlich 0x4F bzw.
0x4E als "komplette Leseadresse".
Um den "Ballast" des LC-Displays nicht bei der Implementierung des
Port-Expanders zu haben (bin ja noch I2C-Neuling), habe ich mich dann
dazu entschlossen, erstmal eine LED anzusteuern. Hierbei trat jedoch das
Problem auf, dass die LED nicht angesteuert wurde. Auch ein Messen der
Pegel mittels Multimeter brachte keine Ergebnisse.
Aus diesem Grunde habe ich mein Programm so umgebaut, dass ich erst
einmal herausfinden kann, ob eine I2C-Kommunikation überhaupt aufgebaut
werden kann. In Anlehnung an diesen Beitrag
(Beitrag "Re: I2CLCD Library für HD44780 LCDs") und der I2C-Lib
von Peter Fleury habe ich folgenden Code geschrieben:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<stdlib.h>
4
#include<stdint.h>
5
#include<util/twi.h>
6
#include"i2cmaster/i2cmaster.h"
7
8
// F_CPU already defined in Makefile
9
// #define F_CPU 16000000UL
10
#define LED PB5
11
#define I2C_R_ADDR 0x40
12
#define I2C_W_ADDR 0x4E
13
14
15
voidLED_init(void){
16
// define pin LED as output
17
DDRB|=(1<<LED);
18
}
19
20
21
voidLED_blink_slow(){
22
_delay_ms(1000);
23
PORTB^=(1<<LED);
24
_delay_ms(1000);
25
PORTB^=(1<<LED);
26
}
27
28
29
voidLED_blink_fast(){
30
_delay_ms(300);
31
PORTB^=(1<<LED);
32
_delay_ms(300);
33
PORTB^=(1<<LED);
34
}
35
36
37
voidLED_on(void){
38
PORTB^=(1<<LED);
39
}
40
41
42
voidLED_toggle(void){
43
PORTB^=(1<<LED);
44
}
45
46
47
uint8_tmain(void){
48
LED_init();
49
LED_blink_slow();
50
51
i2c_init();
52
53
if(i2c_start(I2C_R_ADDR)){
54
// error occured, turn on LED
55
LED_on();
56
while(1){
57
// caught in error loop
58
}
59
}
60
61
while(1){
62
// no error occured, blink LED every 300 ms
63
LED_blink_fast();
64
}
65
66
return0;
67
}
Bei erfolgreicher I2C-Kommunikation, soll die LED blinken. Bei
fehlgeschlagener Kommunikation soll die LED dauerhaft leuchten. So ist
zumindest der Plan, denn im Moment macht die LED keinen Mucks. Weder
leuchtet sie, noch blinkt sie.
Wie gesagt: Mit Arduino-Software klappt die Ansteuerung des Expanders
ohne Probleme, sodass ich zumindest bislang Hardwarefehler ausschließe.
Wie aus meinen Ausführungen evtl. deutlich wurde, bin ich mit meinem
Latein (und meinen eingeschränkten Mitteln) so langsam am Ende und
hoffe, ihr könnt mir weiterhelfen. Hier also meine beiden Fragen
zusammengefasst:
- Warum gibt mir die LED keine Infos über eine erfolgreiche oder
fehlerhafte I2C-Kommunikation?
- Wie ist jetzt die korrekte Adresse meines Port-Expanders? Bei der
unterschiedlichen Definition von 7- und 8-Bit-Addressen gemäß Datenblatt
des PCF8574, Arudino-Welt und AVR TWI habe ich definitv den
Überblick verloren.
Vielen Dank und viele Grüße
Sven
Sven G. schrieb:> - Wie ist jetzt die korrekte Adresse meines Port-Expanders? Bei der> unterschiedlichen Definition von 7- und 8-Bit-Addressen gemäß Datenblatt> des PCF8574, Arudino-Welt und AVR TWI habe ich definitv den> Überblick verloren.
Die Adresse zum lesen kann nicht stimmen:
1
#define I2C_R_ADDR 0x40
2
#define I2C_W_ADDR 0x4E
3
4
if(i2c_start(I2C_R_ADDR)){
Wahrscheinlich bleibt es beim Init hängen.
Probiere die Adresse 0x4F zum lesen, wenn es immer noch nicht geht,
probiere es mit 0x27.
Sven G. schrieb:> ergibt sich somit eine Adresse von 0b0100111x
In der I2C Spezifikation ist die Adresse als 7-Bit Adresse festgelegt.
Read und Write Zugriffe verwenden die selbe Adresse. Das R/W-Bit wird
bei der Adressierung zusätzlich im ersten übertragenen Byte übermittelt.
Wenn jeder seinen eigenen Sprachgebrauch hat ...
> Da ich A[0:2] alle auf VCC gezogen habeJoachim B. schrieb:> ich mache das im Studio so (alle A0 - A2 auf 0 gelötet)
Du solltest dich einigen, wie du deine unteren Adressbits setzt.
Sven G. schrieb:> Aus diesem Grunde habe ich mein Programm so umgebaut, dass ich erst> einmal herausfinden kann, ob eine I2C-Kommunikation überhaupt aufgebaut> werden kann.
Dafür wäre ein Logikanalysator wesentlich einfacher zu verwenden, z.B.
ebay 201541710029
Wolfgang schrieb:> Du solltest dich einigen, wie du deine unteren Adressbits setzt.
Die unteren 3 Bits des Adressbytes sind 1 (da A0, A1 und A2) auf VCC
liegen. Die binäre Adresse (7-bit) wäre demnach 0b0100111, was 0x27 bzw.
39 (dec) entspricht.
Unter Berücksichtigung des R/W-Bits ergeben sich folgende Adressbytes
- zum Lesen: 0b0100111 bzw. 0x4F oder 79 (dec)
- zum Schreiben: 0b0100110 bzw. 0x4E oder 78 (dec)
Das stimmt doch soweit, oder?
Marc V. schrieb:> Probiere die Adresse 0x4F zum lesen, wenn es immer noch nicht geht,> probiere es mit 0x27.
Das hatte ich schon probiert. Leider ohne Erfolg.
Joachim B. schrieb:> und in Arduino shifte ich um Vergleichbarkeit zu haben
Ich habe den Code-Schnipsel angepasst:
1
#include<Wire.h>
2
3
voidsetup(){
4
5
Serial.begin(9600);
6
Serial.write("\nI2C Scanner -> Scanning...\n");
7
8
byteerror,address;
9
intnDevices=0;
10
for(address=1;address<127;address++){
11
Wire.beginTransmission(address);
12
error=Wire.endTransmission();
13
14
if(error==0)
15
{
16
Serial.print("No error on address: ");
17
Serial.println(address);
18
switch(address<<1)// hier der Adress-shift um kompatibel zu bleiben
19
{
20
case0x40:
21
Serial.write("PCF8574\n");
22
break;
23
case0x70:
24
Serial.write("PCF8574A\n");
25
break;
26
default:
27
Serial.write("No address match\n");
28
break;
29
}
30
nDevices++;
31
}
32
elseif(error==4)
33
{Serial.print("Unknow error at address 0x");
34
if(address<16)
35
Serial.print("0x");
36
Serial.println(address);
37
}
38
}
39
if(nDevices==0)
40
Serial.println("No I2C devices found");
41
else
42
Serial.print("Done:");
43
Serial.print(nDevices);
44
Serial.println(" devices found.");
45
46
47
}
48
49
voidloop(){
50
// put your main code here, to run repeatedly:
51
52
}
Damit werden lt. Ausgabe im seriellen Monitor 62 Teilnehmer gefunden. Da
hängt aber definitiv nur der eine Port-Expander dran.
Wolfgang schrieb:> Dafür wäre ein Logikanalysator wesentlich einfacher zu verwenden, z.B.> ebay 201541710029
Das stimmt wohl, aber einen solchen besitze ich (leider noch) nicht.
Evtl. kann ich kommende Woche zumindest ein Oszi nutzen, wobei das noch
nicht ganz sicher ist.
Was mich aber total wundert, ist dass es in plain C so rein gar nicht
klappen will. Ich bin bislang also nicht wirklich weiter gekommen.
Könnte mir jemand nochmals bzgl. der Adressen weiterhelfen oder habe ich
die mittlerweile richtig "berechnet"?
Sven G. schrieb:> Ich habe den Code-Schnipsel angepasst:>> Damit werden lt. Ausgabe im seriellen Monitor 62 Teilnehmer gefunden. Da> hängt aber definitiv nur der eine Port-Expander dran.
vielleicht liegts an deiner Anpassung oder am Portexpander, ich finde
nur was ich wirklich dran habe:
Arduino = 105, auf nanoV3 oder proMINI auf 328p
File: A3_nan_Nok_RTC_OLE_EEP.ino
kompiliert: 2017/01/19_13:46:48
CPU Takt : 16,000 MHz
set I2C SCL = 400 kHz
compile 2017/01/19_13:46:48
-> Scanning...
I2C device found at address 0x3C; 0111100x; << 0x78; 01111000 I2C OLED
Arduino = 105, auf nanoV3 oder proMINI auf 328p
File: A5_nan_Nok_RTC_EEP_DHT22.ino
kompiliert: 2017/01/27_16:53:09
CPU Takt : 16,000 MHz
set I2C SCL = 400 kHz
compile 2017/01/27_16:53:09
-> Scanning...
I2C device found at address 0x50; 1010000x; << 0xA0; 10100000 I2C EEPROM
I2C device found at address 0x68; 1101000x; << 0xD0; 11010000 DS3231 RTC
Sven G. schrieb:> - zum Lesen: 0b0100111 bzw. 0x4F oder 79 (dec)> - zum Schreiben: 0b0100110 bzw. 0x4E oder 78 (dec)>> Das stimmt doch soweit, oder?
Jein (binär ist falsch), wenn du den PCF8574 vor dir hast und A0..A2 auf
VCC gelegt hast, ist die (7-Bit) Adresse 0b0100111 oder 0x27.
Übertragen musst du als erstes Byte <adress><R/!W>, also
Sven G. schrieb:> Marc V. schrieb:>> Probiere die Adresse 0x4F zum lesen, wenn es immer noch nicht geht,>> probiere es mit 0x27.>> Das hatte ich schon probiert. Leider ohne Erfolg.
Da stimmt schon mal was nicht.
1
#define I2C_R_ADDR 0x40
2
#define I2C_W_ADDR 0x4E
3
4
if(i2c_start(I2C_R_ADDR)){
Dein Codeschnipsel sagt etwas anderes.
Entscheide dich.
Sven G. schrieb:
1
for(address=1;address<127;address++){
Probiert wird normalerweise nur auf ungeraden Adressen.
Wolfgang schrieb:> Jein (binär ist falsch), wenn du den PCF8574 vor dir hast und A0..A2 auf> VCC gelegt hast, ist die (7-Bit) Adresse 0b0100111 oder 0x27.>> Übertragen musst du als erstes Byte <adress><R/!W>, also - zum> Schreiben: 0b01001110 0x4E oder 78 (dec)> - zum Lesen: 0b01001111 0x4F oder 79
Danke, dass du meine Antwort auf Deutsch übersetzt hast.
Wäre nicht nötig gewesen...
Marc V. schrieb:> Wolfgang schrieb:>> Jein (binär ist falsch), wenn du den PCF8574 vor dir hast und A0..A2 auf>> VCC gelegt hast, ist die (7-Bit) Adresse 0b0100111 oder 0x27.>>>> Übertragen musst du als erstes Byte <adress><R/!W>, also - zum>> Schreiben: 0b01001110 0x4E oder 78 (dec)>> - zum Lesen: 0b01001111 0x4F oder 79
Das mit den binären Adressbytes ist leider wohl ein Tippfehler gewesen.
Marc V. schrieb:> Dein Codeschnipsel sagt etwas anderes.> Entscheide dich.
Genau genommen habe ich verschiedene Ansätze ausprobiert
(zugegebenermaßen ein bisschen im Blauen rumgestochert), die ich aber
nicht weiter mit einzelnen Code-Schnipseln belegt habe.
Wie schon erwähnt, habe ich die Adressbytes 0x4F, 0x4E sowie 0x27
ausprobiert. Das bedeutet:
1
// natürlich immer mit nur einer Definition,
2
// sodass hier insgesamt drei Adressbytes getestet werden
3
#define I2C_R_ADDR 0x4F
4
#define I2C_R_ADDR 0x4E
5
#define I2C_R_ADDR 0x27
mit jeweils:
1
if(i2c_start(I2C_R_ADDR)){
2
// error occured, turn on LED
3
LED_on();
4
while(1){
5
// caught in error loop
6
}
7
}
Des Weiteren einmal mit der Adresse und dem zusätzlichen R/W-Bit per
I2C-Lib:
1
#define I2C_BASE_ADDR 0x40
mit
1
if(i2c_start(I2C_BASE_ADDR+I2C_READ)){
2
// error occured, turn on LED
3
LED_on();
4
while(1){
5
// caught in error loop
6
}
7
}
bzw.
1
if(i2c_start(I2C_BASE_ADDR+I2C_WRITE)){
2
// error occured, turn on LED
3
LED_on();
4
while(1){
5
// caught in error loop
6
}
7
}
Ich hoffe, das macht es einigermaßen deutlich. Trotz (mittlerweile
hoffentlich) richtiger Adresse kommt keine Kommunikation zustande. Weder
blinkt die LED (was für erfolgreiche Kommunikation steht) noch leuchtet
sie dauerhaft (was Fehler anzeigen soll). Es wurde bereits vermutet,
dass der Atmega bei i2c_init() hängen bleibt, was ich allerdings durch
entsprechendes Blinken der LED ausschließen konnte.
Hier also der überarbeitete Code (mit Ansteuerung von LEDs am PCF8574):
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<stdlib.h>
4
#include<stdint.h>
5
#include<util/twi.h>
6
#include"i2cmaster/i2cmaster.h"
7
8
// F_CPU already defined in Makefile
9
// #define F_CPU 16000000UL
10
#define LED PB5
11
#define I2C_BASE_ADDR 0x27
12
#define I2C_R_ADDR 0x4F
13
#define I2C_W_ADDR 0x4E
14
15
16
voidLED_init(void){
17
// define pin LED as output
18
DDRB|=(1<<LED);
19
}
20
21
22
voidLED_blink_slow(){
23
_delay_ms(1000);
24
PORTB^=(1<<LED);
25
_delay_ms(1000);
26
PORTB^=(1<<LED);
27
}
28
29
30
voidLED_blink_fast(){
31
_delay_ms(300);
32
PORTB^=(1<<LED);
33
_delay_ms(300);
34
PORTB^=(1<<LED);
35
}
36
37
38
voidLED_on(void){
39
PORTB^=(1<<LED);
40
}
41
42
43
voidLED_toggle(void){
44
PORTB^=(1<<LED);
45
}
46
47
48
voidmy_i2c_write(uint8_tdata){
49
i2c_start_wait(I2C_BASE_ADDR+I2C_WRITE);
50
i2c_write(data);
51
i2c_stop();
52
}
53
54
55
voidmain(void){
56
LED_init();
57
_delay_ms(2000);
58
LED_blink_slow();
59
60
i2c_init();
61
_delay_ms(2000);
62
LED_blink_slow();
63
64
while(1){
65
// LEDs connected to PCF8574 should flash with 500 ms
Marc V. schrieb:> Sven G. schrieb:>> Dann blinkt die LED alle 300 ms. So wie in der entsprechenden Funktion>> definiert.>> Dann bleibt es bei der>
1
>i2c_start_wait(I2C_BASE_ADDR+I2C_WRITE);
2
>
> hängen.>> Hast du so etwas ähnliches ohne wait ?
Ja, das habe ich:
1
i2c_start(I2C_BASE_ADDR+I2C_WRITE);
Leider bringt dies aber keine Veränderung.
Ich nutze Peter Fleury's I2C-Lib und frage mich gerade, ob die
"Busfrequenz" stimmt. Laut Datenblatt hat der PCF8574 ein 100 kHz
I2C-Bus-Interface.
Weiß zufällig auf die Schnelle, wo das bei Fleury's Lib eingestellt bzw.
festgelegt wird?
@ Sven G. (sgut)
>Weiß zufällig auf die Schnelle, wo das bei Fleury's Lib eingestellt bzw.>festgelegt wird?
in twimaster.c
/* I2C clock in Hz */
#define SCL_CLOCK 400000L
Falk B. schrieb:> @ Sven G. (sgut)>>>Weiß zufällig auf die Schnelle, wo das bei Fleury's Lib eingestellt bzw.>>festgelegt wird?>> in twimaster.c>> /* I2C clock in Hz */> #define SCL_CLOCK 400000L
Danke, Falk. Aber da stehen bereits 100000L, so wie im Datenblatt des
PCF8574 gefordert. :/
Vorher schriebst Du:
> sich ein Teilnehmer mit der Adresse 39 (dezimal) auf dem Bus befindet.
was:
>
1
#define I2C_BASE_ADDR 0x27
einer 7-Bit Adresse für den Expander entspräche, die Adressbits A2..A0
wären dann auf Highlevel.
Wenn wir die gleiche i2cmaster.zip von Peter Fleurys Seite meinen, so
verwendet diese eine 8-Bit Adressgebung.
Demnach wäre eine Basisadresse von 0x4E richtig.
I2C_WRITE wird in der I2Cmaster.h mit 0 definiert, I2C_READ mit 1
Da hier:
>
1
i2c_start_wait(I2C_BASE_ADDR+I2C_WRITE);
nichts geshiftet, sondern nur dazu addiert wird, muss die Basisadresse
bereits 8-Bit sein.
Irgendwie scheine ich mit der Bibliothek von Fleury auf Kriegsfuß zu
stehen.
Mit einer anderen Bibliothek
(https://github.com/g4lvanix/I2C-master-lib) klappt die Ansteuerung des
PCF8574 auf Anhieb.
Die verwendeten Adressen sind:
Sven G. schrieb:> Irgendwie scheine ich mit der Bibliothek von Fleury auf Kriegsfuß zu> stehen.
Naja, Du hast ja teils unbrauchbare Adressen verwandt.
Ein Stolperstrick kann auch sein, wenn das Symbol F_CPU nicht oder nicht
zum richtigen Zeitpunkt vom Makefile in die Fleury Bibliothek kommt.
Falls das Symbol beim Einbinden von twimaster.c also nicht gefunden
wird, dann würde auf 4MHz definiert:
1
#ifndef F_CPU
2
#define F_CPU 4000000UL
3
#endif
obgleich die CPU 4 mal so schnell läuft, die Rechnung für TWBR stimmt
dann nicht mehr und damit auch der TWI-Takt nicht.
Ändere doch probehalber das #define F_CPU 4000000UL in der twimaster.c
in #define F_CPU 16000000UL und versuch's nochmal.
Pullups sind extern dran?
MWS schrieb:> Naja, Du hast ja teils unbrauchbare Adressen verwandt.
Durch die Verwendung der anderen Bibliothek konnte ich ja zeigen, dass
die "neuen" Adressen prinzipiell richtig sind und funktionieren.
MWS schrieb:> Ändere doch probehalber das #define F_CPU 4000000UL in der twimaster.c> in #define F_CPU 16000000UL und versuch's nochmal.
Habe ich wieder einkommentiert und angepasst. Hat allerdings keine
Veränderung gebracht.
MWS schrieb:> Pullups sind extern dran?
Ja, die sind zumindest im Schaltplan eingetragen. Auch funktioniert die
Kommunikation ja mit der anderen Lib ohne Probleme.
Im Anhang der jeweilige Source Code. Einmal für die Fleury-Lib, einmal
für die alternativ genutzte Lib.
Sven G. schrieb:> Durch die Verwendung der anderen Bibliothek konnte ich ja zeigen, dass> die "neuen" Adressen prinzipiell richtig sind und funktionieren.
Es war kein neuer Code eingestellt und dann kann man nie sicher sein,
was denn nun verwendet wird.
> Ja, die sind zumindest im Schaltplan eingetragen. Auch funktioniert die> Kommunikation ja mit der anderen Lib ohne Probleme.
Ich habe die anderen Libs durchgesehen und konnte nicht entdecken, dass
da irgendwo die internen Pullups gesetzt wurden, mit denen es aber
funktionieren kann. Daher der Gedanke: ein Code setzt interne Pullups,
geht, der zweite ohne interne geht nicht.
> Im Anhang der jeweilige Source Code. Einmal für die Fleury-Lib, einmal> für die alternativ genutzte Lib.
Hm, da müsste man jetzt den Debugger anwerfen.
MWS schrieb:> Ich habe die anderen Libs durchgesehen und konnte nicht entdecken, dass> da irgendwo die internen Pullups gesetzt wurden, mit denen es aber> funktionieren kann. Daher der Gedanke: ein Code setzt interne Pullups,> geht, der zweite ohne interne geht nicht.
Das Board mit dem PCF8574 verfügt über die erforderlichen Pull-Ups an
den Datenleitungen.
MWS schrieb:> Hm, da müsste man jetzt den Debugger anwerfen.
Das nützt mir vermutlich relativ wenig, da ich mit meinem AVRisp MkII ja
nicht wirklich debuggen kann. Mit "Caveman-Debugging" über LEDs und UART
komme ich jetzt allerdings auch nicht wirklich weiter.
Marc V. schrieb:> Probiert wird normalerweise nur auf ungeraden Adressen.
Was soll das denn nun wieder. Willst du die I2C-Bausteine mit den
geraden Adressen, also z.B. einen PCF8574 mit A0=0 bei dem Scan nicht
abfragen?
Natürlich muss man alle 127 Adressen abfragen, wenn man alle
Busteilnehmer erwischen will.
https://www.arduino.cc/en/Reference/WireBeginTransmission
Man beachte die Parameterbeschreibung.
Sven G. schrieb:> Das nützt mir vermutlich relativ wenig, da ich mit meinem AVRisp MkII ja> nicht wirklich debuggen kann. Mit "Caveman-Debugging" über LEDs und UART> komme ich jetzt allerdings auch nicht wirklich weiter.
Korrigiere: nicht Debugger, sondern Simulator.
Mir wurde schnell klar was los ist, als ich das Hex-File simuliert hab',
denn der Prozessor blieb hängen bei:
1
SBIS 0x09,5
2
RJMP PC-0x0001
Das ist eine Abfrage des PinD.5 auf ein High. Solch' eine Abfrage gab's
nicht im normalen Quellcode und der Portpin PD5 hat im Code auch nichts
zu schaffen, sowas findet man aber in Soft-I2C Routinen.
Also in's Makefile geschaut und tadaa: Du hast die i2cmaster.h
eingebunden, welche wiederum die i2cmaster.S einbindet, das sind die
Soft-I2C Routinen der Fleury-Lib, welche alternativ als Soft oder
Hard-I2C compiliert werden kann.
Bei Dir war's Soft und da galt dann, Auszug aus der .S:
1
;******----- Adapt these SCA and SCL port and pin definition to your target !!
2
;
3
#define SDA 4 // SDA Port D, Pin 4
4
#define SCL 5 // SCL Port D, Pin 5
5
#define SDA_PORT PORTD // SDA Port D
6
#define SCL_PORT PORTD // SCL Port D
Du hättest also nur SCL an PD5 und SDA an PD4 anschließen müssen und
schon wäre es gelaufen.
Oder eben den Port und Pins in der.S umgestellt.
Oder die i2cmaster.h überhaupt nicht erst eingebunden, dann hättest Du
Hard-I2C auf den Standardpins gehabt.
MWS schrieb:> Korrigiere: nicht Debugger, sondern Simulator.
Den Simulator muss ich mir unbedingt mal ansehen! AVR-Simulation
scheint da ja einen guten Einstieg zu liefern.
MWS schrieb:> Oder die i2cmaster.h überhaupt nicht erst eingebunden, dann hättest Du> Hard-I2C auf den Standardpins gehabt.
Das ist tatsächlich des Rätsels Lösung. Ich musste auch noch den
#include in der twimaster.c anpassen und twimaster.c anstatt i2cmaster.h
in mein Makefile aufnehmen.
Falls noch jemand anderes dieses Problem hat und nach einer Lösung
sucht, so habe ich den kompletten Source Code angefügt.
Allen fleißigen Helfenden einen schönen Dank und eine gute Woche.
/P.S.: Gerade vermisse ich den gründen Haken von Stackoverflow ein
bisschen. Das ist immer so ein schönes Gefühl, wenn man eine Antwort
akzeptieren kann und eine Frage gelöst wurde/
Bei den Arduino Beispielprogrammen gibt es eines, daß die I2C-Adressen
auslesn kann, vielleicht kannst Du das mal im Original oder in eine
andere Sprache übersetzt, ausprobieren. Findet bei mir die LCD-Adresse.
1
// i2c_scanner
2
//
3
//
4
// This sketch tests the standard 7-bit addresses
5
// from 0 to 127. Devices with higher bit address
6
// might not be seen properly.
7
//
8
// Adapted to be as simple as possible by Arduino.cc user Krodal
9
//
10
// June 2012
11
// Using Arduino 1.0.1
12
//
13
14
#include<Wire.h>
15
16
voidsetup()
17
{
18
Wire.begin();
19
20
Serial.begin(9600);
21
Serial.println("\nI2C-Scanner");
22
}
23
24
voidloop()
25
{
26
byteerror,address;
27
intnDevices;
28
29
Serial.println("Scanning...");
30
31
nDevices=0;
32
for(address=0;address<=127;address++)
33
{
34
// The i2c_scanner uses the return value of
35
// the Write.endTransmisstion to see if
36
// a device did acknowledge to the address.
37
Wire.beginTransmission(address);
38
error=Wire.endTransmission();
39
40
if(error==0)
41
{
42
Serial.print("I2C-Device gefunden mit der Adresse 0x");