Hallo Gemeinde
Möchte einen PCA9536 in Betrieb nehmen. Leider klappt das nicht so.
Programm:
1
unsignedcharadr1_w=0x4e;// Schreibadresse Taster
2
unsignedcharadr1_r=0x4f;// Leseadresse
3
unsignedcharadr2_w=0x41;// Schreibadresse Relais
4
// unsigned char adr2_r = 0x41; // Leseadresse
5
6
unsignedcharadr3_w=0x4c;// Schreibadresse Relais 8 fach
7
unsignedcharadr3_r=0x4d;// Leseadresse
8
9
unsignedchard;
10
11
int16_tvar;// Variable var
12
var=0xff;// setze var auf ...
13
14
intmain(void)
15
{// Hauptprogramm
16
i2c_init();
17
i2c_start(adr1_w);// Schreibbefehl für Device 1
18
while(1)
19
{// Hauptschleife
20
i2c_write(0xff);// Alle Pins des PCF auf 0
21
i2c_start(adr1_r);// Starte Lesezugriff
22
d=i2c_readNak();// Schreib Leseergebnis in d
23
24
if(~d&0x01)// Taste 1
25
var&=~(1<<0);// Wenn T1 gedrückt ist...
26
else// wenn nicht dann ...
27
var|=(1<<0);
28
29
if(~d&0x02)// Taste 2
30
var&=~(1<<1);// Wenn T2 gedrückt ist...
31
else// wenn nicht dann ...
32
var|=(1<<1);
33
34
if(~d&0x04)// Taste 3
35
var&=~(1<<2);// Wenn T4 gedrückt ist...
36
else// wenn nicht dann ...
37
var|=(1<<2);
38
39
if(~d&0x08)// Taste 4
40
var&=~(1<<3);// Wenn T4 gedrückt ist...
41
else// wenn nicht dann ...
42
var|=(1<<3);
43
44
if(~d&0x10)// Taste 5
45
var&=~(1<<4);// Wenn T5 gedrückt ist...
46
else// wenn nicht dann ...
47
var|=(1<<4);
48
49
if(~d&0x20)// Taste 6
50
var&=~(1<<5);// Wenn T6 gedrückt ist...
51
else// wenn nicht dann ...
52
var|=(1<<5);
53
54
if(~d&0x40)// Taste 7
55
var&=~(1<<6);// Wenn T7 gedrückt ist...
56
else// wenn nicht dann ...
57
var|=(1<<6);
58
59
if(~d&0x80)// Taste 8
60
var&=~(1<<7);// Wenn T8 gedrückt ist...
61
else// wenn nicht dann ...
62
var|=(1<<7);
63
64
i2c_start(adr2_w);// Schreibbefehl
65
i2c_write(var);// Schreibe var
66
_delay_ms(1);// 5ms warten
67
68
i2c_start(adr3_w);// Schreibbefehl
69
i2c_write(var);// Schreibe var
70
_delay_ms(1);// 5ms warten
71
}
72
i2c_stop();
73
}
Hardware:
- Platine mit PCF 8574 und 8 Taster
- Platine mit PCA9536 und 4 Relais und ULN 2003 a als Treiber
(ULN 2003 Eingänge mit 4,7k nach Vcc gelegt)
- Platine mit PCF 8574 und 8 Relais
Problem.
Die Taster schalten den PCF8574 mit den 8 Relais ohne Probleme. Versuche
ich den PCA9536 zu schalten - kein Erfolg. Nach Datenblatt ist die
Adresse DEC 65 oder HEX 41. Korrekt eingegeben - kein Erfolg.
Schalte ich alle 3 Platinen zusammen, flattern die Relais am PCF8574
Warum kann ich den PCA9536 nicht schalten
Viele I2C Komponenten haben oft die Steuersequenz:
Slave address byte
Control Register byte
Data byte
Lies Dir mal das Datenblatt von T.I. Da wird die Ansteuerung sehr leicht
verständlich beschrieben. Solange Deine I2C library funktioniert und die
Hardware richtig mit Pull-up Widerständen angeschlossen ist, sollte der
Erfolg nicht ausbleiben. Ich weiß, das erste Mal ist immer die
schwierigste. Wenn Du mit PCA9536 erfolgreich umgehen kannst, kannst Du
auch 99.99% der anderen Bausteine steuern.
Die Sendefolge ist (generisch) einfach:
I2C_start
I2C_write(slaveaddress);
i2C_write(commandbyte);
I2C_write(databyte);
I2C_stop;
Noch eine Bemerkung zum SlaveAddress byte. Das wird oft praktisch nicht
richtig verstanden. In Bezug auf das Datenblatt, Sektion 7.3.2.1 siehst
Du das SA byte als 1000001rw angegeben. Darunter steht das SA byte ist
"41", aber es wird nicht als 0x41 angegeben. In Wirklichkeit mußt Du das
SA byte 0x82 beim schreiben und 0x83 beim lesen senden. Laß Dich nicht
verwirren. da die Schreibroutine nur 8-bit akzeptiert, mußt Du den Wert
41 um ein Bit nach links verschieben weil Du ja nicht 41 + 0/1 senden
kannst. Also wird das Schreib/lese bit dem SA Wert angefügt und aus dem
41 wird 0x82 mit dem Niedrigstwertigen Bit das Schreib/Lese bit
darstellend.
76543210 Schreib/Lese bit
------------------------------------
01000001 0 <--- T.I. Schreibweise "41"
10000010 <--- 0x82 zum Schreiben. "0x82"
10000011 <--- 0x83 zum Lesen. "0x83"
Beachte daß im PCA9536 vier Register vorhanden sind, die für die
Gesamtoperation richtig beschrieben oder gelesen werden müssen.
(Input, output, polarity, und configuration). Diese Register werden vor
dem schreiben oder lesen mit dem command byte selektiert.
Zum Beispiel wenn Du die Io pins als Ausgänge brauchst, sende zuerst am
Anfang nur einmal diese Sequenz: 0x82 und 0x03 und 0x00.
Um alle Ausgänge hochzusetzen sende: 0x82 und 0x01 und 0x0F
Beim Lesen studiere zuerst Sektion 7.3.2.4.2 und beachte sorgfältig die
angegebene Steuerfolge wo man zuerst das zu lesende Register bestimmt
und dann ohne Stop Bit mit dem Lese AS weitermacht und dann mit der I2c
Lesefunktionsabfrage das Daten Register ausliest.
Beim Lesen: SA(Wr) CB SA(R) DB...
Das T.I. Datenblatt ist sehr gut geschrieben. Nimm Dir die Zeit dafür.
Bei mehreren Bausteinen an einen Bus, muß jeder Baustein einzeln in der
notwendigen Datenfolge mit Stop Bedingung am Schluß zwischen jeden
Baustein abgearbeitet werden.
Hoffe es hilft,
Gerhard
Achim Seeger schrieb:> Werde es lesen. Hab bereits ca 10 andere Bauteile angesteuert. Der BUS> steht, Anzeige geht, Temp geht. Ist allerdings der erste PCA ..> achim
Hallo Achim,
Dein obiges Codebeispiel ist prinzipiell nicht günstig. Da eine i2C Bus
Transaktion immer komplett abgearbeitet werden muß, schlage ich vor Du
baust Dir Ansteuerroutinen mit denen Du jede Funktion automatisch
ansteuern kannst.
Z.B. So würde ich es machen:
int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8
databyte)
Dann steuerst Deinen Baustein etwa so an:
#define PCA_WRITE_ADR 0x82
#define CFG_REGISTER 0x03
#define OUTPUT_REGISTER 0x01
...
/* Konfiguriere Pins 0-2 als Ausgänge und Pin-3 als Eingang */
PCA9536_Write(PCA_WRITE_ADR, CFG_REGISTER, 0x07);
/* Setze PINS 0 und 2 */
PCA9536_Write(PCA_WRITE_ADR, OUTPUT_REGISTER, 1<<2 | 1<<0);
...
int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8
databyte)
{
I2C_start();
I2C_write(slave_address);
I2C_write(cmd);
i2C_write(databyte);
I2C_stop();
return 0;
}
Gerhard
Sorry, muss mal was dazu fragen.
Dein Code sieht so anders aus. Wird der PCA9536 anders angsteuert als
z.B. der PCF 8574? Da brauch ich etwas länger um das zu verstehen.
Leider gibt es nicht viele Beispiele dazu im Netz
Gerhard O. schrieb:> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8> databyte)
Ist dieser Code auch für andere geeignet. Bin noch beim lesen und
verstehen
Man , Man ist so anders ...
Achim Seeger schrieb:> Sorry, muss mal was dazu fragen.> Dein Code sieht so anders aus. Wird der PCA9536 anders angsteuert als> z.B. der PCF 8574? Da brauch ich etwas länger um das zu verstehen.> Leider gibt es nicht viele Beispiele dazu im Netz>> Gerhard O. schrieb:>> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8>> databyte)>> Ist dieser Code auch für andere geeignet. Bin noch beim lesen und> verstehen> Man , Man ist so anders ...
Hallo Achim,
Ja, der PCF8574 hat die vier internen Register der PCA Serie nicht. Der
ist einfacher zum ansteuern.
Schreiben:
PCF8574: SA(W) und DB....DB...
PCA9536: SA(W) und CR und DB....
Das extra Command Register ist zwischen SA unD DB so dass der PCA9536
weiß welches Register geschrieben oder gelesen werden soll.
Meine Beispielroutine passt für alle PCA Familienmitglieder. Es gibt
auch 16-bit Versionen wie der PCA9555 wo zwei Registerbänke vorhanden
sind und der gültige CR Bereich von 0-7 spannt. Dann gibt es auch noch
eine 40-bit Version (PCA9568?).
Such Dir die T.I. Version des PCF8574 Datenblatt und vergleiche es mit
dem PCA9536 Datenblatt. Dann werden Dir die Unterschiede bestimmt sofort
klar.
Grüße,
Gerhard
Gerhard O. schrieb:> ...> /* Konfiguriere Pins 0-2 als Ausgänge und Pin-3 als Eingang */> PCA9536_Write(PCA_WRITE_ADR, CFG_REGISTER, 0x07);
Da habe ich Mist gemacht. Ausgänge sind 0 und Eingänge sind 1.
Für die angegebene Konfigurierung sollte das natürlich umgekehrt sein,
also 0x08 anstatt 0x07.
Sorry!
Gerhard
Hallo Gerhard
habe jetzt einige Stunden im Netz zugebracht. Sieht richtig dünn aus.
Selbst auf chinesisch ist kaum was zu finden. Datenblätter gibt es
genug. Habe auch diese gelesen (so weit möglich). Leider versteh ich es
nicht. Auch auf diesen Seiten gibt es kaum Info dazu. Werde mit deinen
Sachen versuchen was zu machen. Noch keine Ahnung wie.
Kennst du vielleicht ein paar Sachen zur Hilfe?
achim
@ achim (Gast)
>habe jetzt einige Stunden im Netz zugebracht. Sieht richtig dünn aus.
Was? Die Infos im Netz oder was?
Das glaub ich mal keine Sekunden.
>Selbst auf chinesisch ist kaum was zu finden. Datenblätter gibt es>genug.
Die reichen, wenn man I2C einmal WIRKLICH verstanden hat. Hast du aber
leider immer noch nicht. Und leider glaube ich auch nicht, dass das je
passieren wird. Wie lange bist du an dem Thema schon dran?
>Kennst du vielleicht ein paar Sachen zur Hilfe?http://www.nadelspiel.com/stricken/strickmuster/
Hallo Falk
egal ob du es glaubst oder nicht, war gestern und heute morgen im Netz
und habe die verschiedensten Seiten durchsucht. Die Ausbeute betrug ein
paar (kleine) Sachen in Basic, einiges in mir unbekannten oder
unverständlichen Sprachen.
Warum schickst du mir eine Anleitung zum Stricken? Diese Seiten wollen
helfen, so steht es jedenfalls drin. Wenn man mit einer konkreten Frage
kommt, erwartet auch Verständnis dazu.
Wenn ich mir ansehe, wie lange der IC bereits auf dem Markt ist und das
vergleiche mit den Beschreibungen, Anwendungen, Programmen oder
Platinen, so kann ich nur feststellen, das er kaum verbreitet ist oder
angewendet wird. Ist schade drum. Ist zwar ein SMD aber relativ einfach
zu montieren und reicht für viele Anwendungen aus.
Geb es offen zu, das ich das Datenblatt nicht verstehe. Habe mich beim
PCF8574 soweit durchgekämpft, das ich ihn anwenden kann. Hatte zu Anfang
auch genug Schwierigkeiten damit.
achim
@ achim (Gast)
>egal ob du es glaubst oder nicht, war gestern und heute morgen im Netz>und habe die verschiedensten Seiten durchsucht. Die Ausbeute betrug ein>paar (kleine) Sachen in Basic, einiges in mir unbekannten oder>unverständlichen Sprachen.
Wie bereits gesagt, das Datenblatt reicht vollkommen. Wenn du für jeden
IC schon fertige Software willst, muss du dich bei Arduino & Co umsehen.
>Warum schickst du mir eine Anleitung zum Stricken?
Ich wollte damit aufzeigen, dass es noch andere schöne Hobbys gibt . . .
>Wenn ich mir ansehe, wie lange der IC bereits auf dem Markt ist und das>vergleiche mit den Beschreibungen, Anwendungen, Programmen oder>Platinen, so kann ich nur feststellen, das er kaum verbreitet ist oder>angewendet wird.
;-)
DU kennst die Anwendungen nicht. 99,9% der Anwender benutzen ihn und
gut, aber sie stellen halt keinerlei Quelltexte ins Netzt. Müssen sie
auch gar nicht!
> Ist schade drum. Ist zwar ein SMD aber relativ einfach>zu montieren und reicht für viele Anwendungen aus.
Ja und?
>Geb es offen zu, das ich das Datenblatt nicht verstehe.
Damit kommen wir dem Problem schon näher.
> Habe mich beim>PCF8574 soweit durchgekämpft, das ich ihn anwenden kann. Hatte zu Anfang>auch genug Schwierigkeiten damit.
Du hast I2C immer noch nicht verstanden. Du hoffst immer, dich irgendwie
durchwurschteln zu können, ohne die Dinge WIRKLICH grundlegend zu
verstehen. Das sieht man immer wieder. Sobald aber mal ein neuer IC dran
ist, der halt etwas anders als deine bisherigen ICs sind, ist immer
wieder Feierabend. Im Ernst, such dir ein anderes Hobby. Du quälst dich
mehr mit Elektronik als dass es dir Freude macht.
Selbst wenn dir hier jemand den PCA9636 harklein erklärst, wirst du
dieses Wissen beim nächsten, anderen IC nicht anwenden können.
Hatten wir dir nicht auch mal den LM75 haarklein erklärt? Der PCA9536
ist sehr ähnlich!
Beitrag "Re: Temperaturmessung mit dem LM75"
Da du das Gelernte vom LM75 nicht auf den PCA9536 übertragen kannst,
müssen wir leider feststellen, dass dur ein grundlegendes Lern- und
Logikproblem hast.
Danke dir Gerhard
hab mir einen kleinen überblick verschafft. Viel neues drin und viel zu
lesen und lernen: Habe keine Angst zu lernen und will es auch.
achim
achim schrieb:> Danke dir Gerhard> hab mir einen kleinen überblick verschafft. Viel neues drin und viel zu> lesen und lernen: Habe keine Angst zu lernen und will es auch.> achim
Dieser Beitrag könnte Dir auch noch nützlich sein:
http://www.mikrocontroller.net/articles/AVR_TWI
Gerhard
Hallo Gerhard
habe den letzten Teil gerade angesehen. Kannte leider nur ein Teil da
von. Ist viel neues drin. TV ist gestrichen für heute, muss lesen und
lernen.
danke
achim
PS Das mit dem Stricken (Falk) werde ich erst mal vertagen
Achim Seeger schrieb:> Hallo Gerhard> habe den letzten Teil gerade angesehen. Kannte leider nur ein Teil da> von. Ist viel neues drin. TV ist gestrichen für heute, muss lesen und> lernen.> danke> achim> PS Das mit dem Stricken (Falk) werde ich erst mal vertagen
Hallo Achim,
das ist schon mal ein guter Anfang. Aber übertreibe es nicht. Es ist
meistens besser das Studieren über ein paar Tage zu strecken. Du wirst
erstaunen wie dann auf einmal beim nachlesen manche Sachen von alleine
klar werden.
Es ist auch nützlich am Anfang sich guten Beispiel Source Code zu suchen
um ein gewisses Überblick zu bekommen wie das alles umgesetzt wird.
Ich denke mir schon fast, dass es möglicherweise besser ist zuerst mehr
über die einzelnen Schritte und praktische Anwendung des Bus Protokolls
zu kennen und erst spaeter die I2C Bus Spezifikation zu studieren weil
die am Anfang nicht unbedingt sehr gut im Kontext verständlich ist und
auch zu abstrakt. Mir ist Anfangs selber so gegangen.
Vielleicht mal in dieser Art für einfaches Senden, wenn gegeben ist,
dass die I2C Library schon auf dem MCU Deiner Wahl funktioniert:
Merke: I2C ist immer ein MASTER SLAVE system (Ein Slave kann auch nach
Übergabe ein Master werden, aber wie das geht brauchst Du im Augenblick
noch nicht zu wissen;-) )
Bus braucht wegen der Open Drain Ausgänge immer Pull-Up Widerstaende
(2-4kOhm) nach Vcc damit der Bus funktioniert.
Damit eine einfache BUS Transaktion tatsächlich funktioniert, läuft die
grundsätzliche Busabwicklung für einfache ICs wie der LM75, PCF8574,
PCA95xx immer so ab:
1) Am Anfang muss immer eine START Condition den Bus Aktiv machen (Siehe
i2c_start().
2) Sende die SLAVE ADDRESS mit dem richtigen Hexbyte Wert mit dem LSb
auf 0 so dass die Schreibfunktion Absicht zum Sklaven weiter geleitet
wird.
(Master wartet auf ACK vom Slave, erst dann darf das nächste Byte
gesendet werden) (i2c_write(data) ) Slave byte darf zum SCHREIBEN nie
ungerade sein, z.B. 0x82
3) Dann kommen die Daten oder zusätzliche Steuer Register
(Master wartet auf ACK vom Slave, erst dann darf das naechste Byte
gesendet werden) (i2c_write(data)
4) Beende die Transaktion mit einer STOP Kondition.
(i2c_stop)
Dise Folge ist nämlich immer gleich um Bus Fehler zu vermeiden. Wie der
sogenannte I2C Bushandshake im Detail funktioniert ist im Augenblick
fuer Dich nicht wichtig
Zum LESEN wird es etwas komplizierter weil extra Schritte gebraucht
werden. Lesevorgange werden meist mit einem NACK gestoppt. Aber das auch
spaeter.
Wenn dann das Mal funktioniert, lese die I2C Bus Spezifikation und es
ist dann bestimmt leichter für Dich verständlich.
Hoffe das hilft um Dir einen Überblick zu schaffen um was es geht. Das
reicht mal fürs erste und meine Mittagspause ist auch um,
Gerhard
Achim Seeger schrieb:> Habe bereits einen funktionierenden Bus aufgebaut. Da werde ich den Code> mal gründlich auseinander nehmen.> achim
Das sollte schon mal helfen. Gut Gelingen!
Gerhard
Hallo Gerhard
>> http://www.mikrocontroller.net/articles/AVR_TWI>
Bin gerade dabei diesen Artikel durchzuarbeiten. Es dämmert langsam,
leichte Helligkeit am Horizont zu sehen.
Es kommen auch Fragen zum Thema. In meinem Programm was ich ganz oben
eingestellt habe, verwende ich fast keine Befehle aus dem Artikel. Mach
es einfacher, oder halt anders. Wieso? Da ich viel mit dem AT1284p
arbeite, hat der I2C drin bzw. verwende ich es? Kommt daher der
Unterschied? Ich weiss das es Hardware und Software I2C gibt
achim
achim schrieb:> Es kommen auch Fragen zum Thema. In meinem Programm was ich ganz oben> eingestellt habe, verwende ich fast keine Befehle aus dem Artikel.
Das liegt daran, das im Artikel die Maschinerie beschrieben ist, die dir
die Fleury Library vom Leibe hält bzw. um die sich die FLeury Lib für
dich kümmert.
Aus meiner Sicht besteht dein Hauptproblem darin, dass du alle I2C
Slaves über einen gemeinsamen Kamm scheren willst. Dem ist nicht so.
Das ganze hat was vom Telefonsystem. Du wählst eine Nummer und die
Vermittlungsstelle der Post kümmert sich um den Verbindungsaufbau.
Welche Zifferntasten du dann weiter drücken musst um den
Anrufbeantworter am anderen Ende der Leitung zu steuern ist aber nicht
mehr das Bier der Vermittlungsstelle, auch wenn du dazu am Telefon
dieselben Tasten drückst. Welche Tasten dann zu drücken ist, bestimmt
ausschliesslich der Hersteller des Anrufbeantworters. Die können beim
Hersteller X identisch sein zum Hersteller Y, können aber auch ganz
anders sein. Und wenn du deine Mailbox anrufst hast du wieder andere
Tasten zu drücken um die gespeicherten Anrufe abzuhören oder zu löschen.
Aber: Die Vermittlungsstelle hält sich da raus. Ab dem Zeitpunkt ab dem
die Verbindung steht, interessiert die die Tonsignale nicht mehr, die
sie sich aus der Leitung rausgefischt hat, die du zum Wählen der Nummer
benutzt hast.
So auch hier.
Die I2C Routinen kümmern sich um den Verbindungsaufbau und um den
Transfer der Bytes. Aber welche Bytes du nach dem Verbindungsaufbau zum
Slave schicken musst um bestimmte Reaktionen auszulösen, das bestimmt
der Slave und das lässt sich in seinem Datenblatt nachlesen. Bei vielen
I2C Slaves ist das Prinzip ähnlich: es gibt sogenannte Register die
Werte enthalten und beschrieben bzw. gelesen werden können. Um zu wissen
welches Register gemeint ist, erwartet der Slave, dass man ihm das nach
dem Verbindungsaufbau in Form einer Zahl mitteilt, wobei es keine Rolle
spielt ob der Hersteller das jetzt 'Pointerregister' oder 'Index' oder
'Registernummer' oder 'Registeradresse' nennt - das Prinzip ist meistens
dasselbe.
Karl Heinz schrieb:> Werte enthalten und beschrieben bzw. gelesen werden können. Um zu wissen> welches Register gemeint ist, erwartet der Slave, dass man ihm das nach> dem Verbindungsaufbau in Form einer Zahl mitteilt, wobei es keine Rolle> spielt ob der Hersteller das jetzt 'Pointerregister' oder 'Index' oder> 'Registernummer' oder 'Registeradresse' nennt - das Prinzip ist meistens> dasselbe.
Hier beim PCA heisst das dann eben 'Command'. Aber wenn man mal genauer
darüber nachdenkt, dass ist diese Kommando auch nichts anderes als die
Auswahl mit welchem Register man weiter arbeiten möchte.
Hallo Achim,
Wie Karl Heinz schon sagt, die Peter Fleury Library befasst sich mit der
(versteckten) I2C Hardware im MCU.
Diese Hardware befasst sich halbautomatisch mit der Abwicklung des BUS
Protokolls welche in den obigen Referenzen im Detail beschrieben ist.
Darum brauchst Du Dich im Augenblick nicht kümmern weil der MCU und die
Library Dir die Arbeit abnimmt so dass Du Dich auf die Anwendung
konzentrieren brauchst. Da ich kein Naturtalent als Lehrer habe, musst
Du mit meiner Darstellungsweise vorlieb nehmen:-)
Fangen wir mal so an. Wie Du schon weißt hat Dein PCA9536, wie im
Datenblatt (Texas Instruments) ausführlich beschrieben, vier
Datenregister. Die sind spezifisch auf die Anwendung des PCA9536
zugeschnitten. Wie greifst Du auf diese einzelne Register zu? Dazu haben
die Entwickler im Datenprotokoll zusätzlich vom SLAVE ADDRESS REGISTER
das COMMAND REGISTER (CR) eingeführt. Dieses CR ist ein Index zum
Zugriff dieser vier register. Jedes dieser Register ist für einen
bestimmten Zweck da. Wenn der Index 0 ist, kannst Du auf das INPUT
REGISTER zugreifen, CR=1 ist zum Stellen des Pinzustands für die IO Pins
gedacht. CR=2 erlaubt Dir die Bits des Input Registers entweder zu
invertieren oder so lassen wie sie gelesen werden. Mit CR=3 kannst Du
den Modus der PINS einstellen. Ein 0 macht aus den PIN einen Ausgang und
eine 1 einen PIN Eingang. Das ist ähnlich wie im AVR.
Um mit dem PCA9536 kommunizieren zu können musst Du jetzt die einzeln
Kommandos der Fleury I2C Library in richtiger Weise anwenden. Diese
Funktion dienen als Brücke zwischen Dir und der (versteckten) internen
Hardware der TWI Schnittstelle. Solange Du nicht selber eine TWI
Schnittstelle entwerfen musst, ist das im Augenblick alles was Du wissen
musst um mit dem TWI Teil kommunizieren zu können.
Die Fleury TWI Routinen sind in gewisser Weise halbautomatisch. Du bist
immer noch für den richtigen Gebrauch verantwortlich.
http://www.ti.com/lit/ds/symlink/pca9536.pdf
Jetzt such Dir mal die Sektion 7.3.2.4 Bit Transaktion. Dort werden die
Busabwicklungen spezifisch für den PCA9536 beschrieben. Sobald Du die
Anwendung richtig versteht zeigen Dir diese Datenblätter wie man mit
diesen ICs richtig kommuniziert.
Sektion 7.3.2.4.1 WRITES
Hier wird beschrieben wie die TWI Busabwicklung im Einzeln abläuft. Sieh
Dir FIGURE 23 genau an. Da siehst Du oben erst mal den SCL Takt.
Unterhalb sind die einzelnen Datenbytes gezeigt. Was nicht gleich
ersichtlich ist, dass zu den 8 Datenbits am Anfang die START CONDITION
bit dazu kommt und die ACK und das STOP Bit. Diese zusätzlichen Bits
werden zu Teil vom MASTER und zum Teil vom SLAVE manipuliert.
Gleich am Anfang wird vom MASTER die START Condition gesetzt. Das machst
Du mit der Funktion i2c_start(). Mit Referenz zu FIGURE 18 und Sektion
7.3.1. Wie dort postuliert wird die START CONDITION initialisiert in dem
die SDA Leitung auf Null gesetzt wird während SCL auf High bleibt. Das
macht der MCU wenn Du i2c_start abrufst. Wenn Du einen Oszi dort
dranhängst könnte man da beobachten. Nun muss das SLAVE ADDRESS BYTE
gesendet werden. Im FAlle des PCA9536 ist das der Wert 0x82. Das ist die
verpackte Adresse des PCA9536 und das Schreib/Lese Bit. Die SLAVE
ADDRESS ist 41h und das Schreib bit zum Schreiben muss Null sein. Damit
Platz für das Schreib/Lese Bit gemacht wird, verschiebt man die 41h um
ein bit nach links was einer Multiplizierung gleich kommt und es wird
0x82 daraus. Wenn Du nur schreiben willst ist jetzt das Schreib/Lese Bit
schon richtig gesetzt. Wenn Die den IC lesen würdest willst dann musst
das Bit auf 1 gesetzt werden und es wird 0x83 daraus.
So, jetzt sind wir soweit den PCA9536 zu adressieren. Beim Abrufen der
i2c_write(0x82) empfängt der PCA9536 die Bit Sequenz wie im ersten Teil
von FIGURE 23 gezeigt. Dem PCA9536 wird jetzt diese Wort in das intern
TWI Interface Schiebe Register geschoben. Wenn die eingeschoben Adresse
mit der internen fest gelegten Adresse übereinstimmt bestimmt die
interne Logik des PCA9536 dass eine gültige SLAVE ADDRESS angekommen ist
und ein SCHREIB Zyklus zu erwarten ist. Und jetzt kommt was ganz
Wichtiges: Wenn also die SLAVE ADDRESS gültig ist setzt der PCA9536
jetzt das ACK Bit (NULL). Der MASTER nimmt das ACK bit als Hinweis dass
der PCA9536 seine SLAVE ADDRESS als gültig empfangen hat. Wenn die SLAVE
ADDRESS nicht stimmt dann schweigt der PCA9536 und der MASTER wird durch
eine STATUS BIT notifiziert und kann dann entsprechend handeln.
Fassen wir mal zusammen: Zu diesem Zeitpunkt weiß der MASTER, dass der
PCA9536 jetzt sehnsüchtig auf weitere Instruktionen vom MASTER wartet
weil der PCA9536 mit dem ACK bit geantwortet hat und weitere Daten
folgen können.
Bis jetzt haben wir:
1
i2c_start();/* MASTER weckt alle Busteilnehmer auf damit sie wissen dass jetzt der MASTER sprechen wird */
2
i2c_write(0x82);/* Addressiere PCA9536 */
Beim Studieren des PCA9536 weißt Du jetzt dass der PCA9536 jetzt das
COMMAND BYTE (CB) erwartet. In diesem IC liegt der gültige Wertbereich
zwischen 0 bis 3. Damit bist jetzt Du in der Lage zu bestimmen welches
interne Datenregister geändert werden soll. Wenn Du zum Beispiel die
PINS ändern möchtest musst Du zuerst das CONFIGURATION REGISTER (CB=3)
auf Null setzen weil der PCA9536 im INPUT Modus initialisiert. Also
musst Du nach dem SA Byte eine drei senden. Der PCA9536 wird jetzt wenn
alles gut geht mit einem ACK antworten.
CONFIGURATION REGISTER SETZEN:
1
i2c_start();/* MASTER weckt alle Busteilnehmer auf damit sie wissen dass jetzt der MASTER sprechen wird */
2
i2c_write(0x82);/* Addressiere PCA9536 */
3
i2c_write(0x03);/* Index auf CFG REGISTER stellen */
4
i2c_write(0x00);/* Alle Port Pins als AUSGANG einstellen */
5
i2c_stop();/* Stop Condtion setzen damit der PCA9536 weiss das wir fertig sind */
OUTPUT PINS SETZEN:
Jetzt kannst Du PINS setzen. Wenn Du alle PINS auf einmal hoch setzen
möchtest, muss das Datenwort 0x03 betragen.
1
2
i2c_start();/* MASTER weckt alle Busteilnehmer auf damit sie wissen dass jetzt der MASTER sprechen wird */
3
i2c_write(0x82);/* Adressiere PCA9536 */
4
i2c_write(0x01);/* Index auf OUTPUT REGISTER stellen */
5
i2c_write(0x03);/* Alle Port Pins hochstellen */
6
i2c_stop();/* Stop Condtion setzen damit der PCA9536 weiß das wir fertig sind */
Das ist das Beispiel in FIGURE 23 umgeändert auf CFG REGISTER schreiben
und PINS setzen.
Wie Du an meinen Beispielen siehst wird der PCA9536 nur für einen Befehl
angesteuert. Du darfst nichts anderes senden. Wenn der MASTER mit einer
TWI BUS Transaktion anfängt muss es dem Datenblatt nach komplett
abgearbeitet werden. Nicht mehr und nicht weniger. Also nicht wie in
Deinem Codebeispiel am Anfang.
Weiche niemals von den gezeigten BUS Transaktion wie im Datenblatt ab.
Diesen Beispielen muss gefolgt werden. Abweichen führt meist zu LOGIK
Fehlern in der internen Steuerung des SLAVES und kann den BUS aufhängen
so dass man alles neu starten muss. (SMB macht da eine Ausnahme. Bei SMB
Bausteinen darf die MASTER SCL Datenrate 10kHz nicht unterschreiten.)
Das Lesen der Register beschreibe ich spaeter wenn ich mehr Zeit habe.
Vielleicht sieht jetzt Du das ganze in einem anderen Licht. Ich bin der
Ansicht dass Du zuerst wissen musst wie man diese Library anwenden kann.
Jetzt kannst Du die I2C Vorgänge gleichzeitig im Kontext studieren. Wie
gesagt das ganze ist im TI Datenblatt ist sehr gut beschrieben. Wenn Du
nicht gleich alles verstehst dann versuche es nach einem Tage wieder.
Auf einmal wirst Du es verstehen. Ich hoffe das meine obige Darstellung
Dir einen anderen Blickwinkel über den Gebrauch der TWI verschafft. Noch
viel Erfolg wünsche ich Dir. Muss jetzt aber arbeiten;-)
Gruesse,
Gerhard
Achim,
hast Du die vier Register richtig konfiguriert, E/A gesetzt? -> siehe
Datenblatt
Letztlich kannst Du z.B. über Register 0 den Status eines Schalters
abfragen.
Adresse ist 130d/82h für schreiben und entsprechend 131d/83h für lesende
Zugriffe.
Sofern Du nicht mit den I²C Abläufen vertraut ist, hilft hier auch das
DB weiter (das ist nicht ironisch gemeint!), aber der prinzipielle
Ablauf ist wie bei anderen Bausteinen auch
schreiben:
1. I2C Start
2. schreibe Adresse(W)
3. schreibe Register
4. schreibe Daten
5. I2c Stop
lesen:
1. I2C Start
2. schreibe Adresse(W)
3. schreibe Register
4. I2CStart
5. schreibe Adresse(R)
4. lese Daten
5. I2C Stop
Gruß
Tom
Offtopic:
Bringt Dich im akutellen Fall zwar nicht weiter..Aber versuch mal auch
den MCP23008 zu mögen :-) ...Der ist wirklich toll, Leistungsfähiger,
Einfacher in der Handhabung und günstiger als diese PCA Dinger..
Wenn ich richtig gesehen habe, ist es ein I2C I/O 8 bit in einem 18
poligen Gehäuse.
Denn hatte ich garnicht auf dem Schirm und kannte ihn nicht. Werde mir
mal näher ansehen. Hast du schon erfahrung mit Ihm?
achim
Achim Seeger schrieb:> Sorry, was vergessen.> Es geht mir um die 4 Bit dabei. Will nicht immer einen viel zu grossen> IC nehmen und ein Teil der Beine unbenutzt lassen.> achim
Jetzt habe ich Dich beim Forum schauen erwischt! :-(((.
//
||
|^^^
||||
| |
\ /
| |
Lass Dich nicht zu sehr ablenken. Der MCP23008 hat aber 11 interne
Register um Du Dich kümmern musst. Warte mit dem bis Du mit dem PCA
Typen komfortabel bist. Wenn Du mehr Bits brauchst und bei den PCA Typen
bleiben willst, dann ist auch der PCA9554 nicht zu schlecht. Ich habe
auch schon mit der 16-Bit SPI-Version vom MCP23017 gearbeitet und der
ist tatsächlich recht brauchbar.
Funktioniert Dein PCA9536 schon beim Output setzen der Pins?
Gerhard
Danke der Nachfrage. Hab grade erst mal meine mails angeschaut. Habe
vorhin auf Arbeit erst mal deinen Aufsatz gezogen. noch ein bischen
ordnen und ausdrucken, dann kann ich genüsslich drin anstreichen,
unterstreichen usw. Steh leider noch auf Papier, ist man so gewohnt.
Es gibt noch viele andere ICs. Mir ist heute der PCF8576 gegegnet. So
richtig mit Display und einem PIC oder sowas, hab das Gehäuse schell
wieder zu gemacht. Du hast den grossen Bruder erwähnt, den 9554. Es gibt
so viele da von. Da muss ich noch eine Menge lesen. Morgen früh sind die
Datenblätter der beiden IC dran und der Vergleich der Register.
Nach dem Info von KH habe ich mir die Datein von Peter angesehen.
Stimmt, da stehen die Sachen drin.
Habe wo anders die Seite von Gerhard O gefunden. Leider nur die Adresse
und Home, ohne Sachen drin. Ist das deiner?
achim
Achim Seeger schrieb:> Habe wo anders die Seite von Gerhard O gefunden. Leider nur die Adresse> und Home, ohne Sachen drin. Ist das deiner?
Kannst Du mir mehr info geben?
Gerhard
Ähm. Was Gerhard da oben gemacht hat, ist nichts anderes als ein Exzerpt
aus dem Datenblatt und eine Erläuterung was man in den Timingdiagrammen
sieht bzw. was man daraus ablesen kann.
Du (wortwörtlich) sammelst mir zu viel Papier anstatt das du dahinter
wärst die Dinge zu verstehen. Tatsächlich ist der Vorgang nämlich sogar
ziemlich einfach und logisch. Er ist genauso logisch, wie der Vorgang
ein Fenster zu öffnen. Da braucht es nicht für jeden Fensterhersteller
eine eigene ausgedruckte Beschreibung, wenn man den ein für allemal vom
Prinzip her verstanden hat. Hat man das Prinzip, dann sieht man im
Datenblatt nur noch nach, in welche Richtung man den Griff drehen oder
kippen muss.
Und ganau letzteres, das Verstehen der Prinzipien, das fehlt mir bei
dir.
Ohne jetzt sexistisch sein zu wollen, aber du erinnerst mich an die
Mädchen in meinen Schulklassen. Im auswendiglernen waren sie spitze. Nur
beim Anwenden wenn man mal um die Ecke denken musste, haperte es. Warum?
Weil sie das Prinzip nicht verstanden haben.
Sorry Gerhard,
da war nicht viel drin. Habe schon gelöscht, vietleicht finde ich es
wieder
Hallo Karl Heinz,
folge eigentlich den Sachen von Gerhard. Ich will nicht den ganzen Text
ausdrucken, einfach nur die Register der beiden vergleichen. Das DB vom
PCF8574 kenne ich soweit schon. Hatte auch dort Infos gesucht und
angewendet. Will nur den Unterschied sehen und mit dem vergleichen, was
anders gemacht wird. Ich bin nicht der Typ, irgendwas auswendig zu
lernen. Wozu auch. Mir geht es um das Verständnis und die Logig dabei.
Möchte es verstehen und anwenden. Habe es mit der Tastenentprellung, den
Timern und anderes genau so gemacht. Du hast mir den Weg gezeigt, ich
nutze mein gelerntes und wende es an. Bin dabei immer offen für neues
achim
Hallo Bülent
Ja, mit Falk habe ich lange Dikussuonen geführt. Beim letzten mal war
das Display defekt, erst ging es und plötzlich nicht mehr. Ohne
erkennbaren Grund. Bin hier auch vertreten mit Tasterentprellung,
Multitasking, mehrere Zeichensätze laden, Ansätze von Statemaschine und
einiges mehr. Nicht zuvergessen den I2C Bus als Module mit Netzteilen,
LM75, FB, IR und einges mehr.
Wir haben auch schon mails getauscht.
achim
PS Falk schimpft immer so viel, eigentlich hat er Recht, bis auf das
stricken. Ist sonst aber netter Kerl
Hallo Achim,
Wir hatten doch dann auch mal zusammen was zu tun gehabt. Ich hatte ja
die lib von falk auf den Mcp23008 umgeschrieben... Oder verwechsle ich
dich gerade mit jemand anderem?
Vg, Bülent
Hallo Gerhard
Danke für die viele Info. Habe heute gründlich studiert und das
Datenblatt gelesen. Als Grundlage benutze ich das angegeben
Datenblatt.Fasse noch mal kurz zusammen:
Die angebene Adesse ist 41, Bitschiebung nach links ergibt 0x82 beim
schreiben und 0x83 beim lesen
Mögliches Programm:
1
I2C_start();
2
I2C_write(slave_address);
3
I2C_write(cmd);
4
i2C_write(databyte);
5
I2C_stop();
1. Start der übertragung
2. Als erstes wird die Slave Adresse übetragen
3. Es wird das Kontrollregister angegeben
4. Es werden die Daten übertragen.
5. Ende der übertragung
Im einzelnen:
Controllregister:
B0 B1
0 0 - Input Port (R) - Tab 3
1 0 - Output Port (R/W) - Tab 4
0 1 - Polarity Invasion - (R/W) - Tab 5
1 1 - Configuration (R/W) - Tab 6
In Fig 23 ist die übertragung angegeben.
Diese erfolgt immer
Slave Adresse - Command Byte - Data to Port
Mit diesen Angaben und deiner Hilfe und den Angaben von Falk werde ich
mich an das Programm machen.
Habe auch schon mal einen Blick aufs lesen geworfen. Erst mal das einen
und dann sehen wir weiter.
Werde das Stück Code reinstellen. Was ich noch nicht ganz durchschaue
ist dein Stück
Gerhard O. schrieb:>>> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8>>> databyte)
und diese Sache von Tom
Tom schrieb:> lesen:> 1. I2C Start> 2. schreibe Adresse(W)> 3. schreibe Register> 4. I2CStart> 5. schreibe Adresse(R)> 4. lese Daten> 5. I2C Stop
Sind die anderen IC (16 Bit) genauso zu programmieren?
achim
Hallo Achim,
Das ist schon mal ein guter Start und ist vielleicht ein guter Zeitpunkt
mit den "Laborarbeiten" anzufangen um das Ganze in die Praxis
umzusetzen.
Da Du schon eine gewisse Erfahrung mit dem Gebrauch der Peter Fleury
Routinen hast, könntest Du das mal jetzt ausprobieren.
Ich schlage Dir vor eine einfaches Programm in Main() zu schreiben wo Du
zuerst den Pca9536 einmal initialisierst so dass das CONFIG REGISTER AUF
Null gestellt wird, damit alle Pins Ausgänge werden.
Dann mache eine endlose while loop wo Du alternativ die Pins zwischen 0
und 1 mit 500ms delay toggeln lässt.
Also so wie dieser pseudo code:
Main()
{
Initialisiere Mcu
Initialisiere pca9536
While(1)
{
I2c pin schreib "0xf" // setze pins hoch(LEDs aus)
Warte 500ms
I2c pin schreib "0". // setze pins nieder(LEDs ein)
Warte 500ms
}
}
An die pca9536 schliess LEDs an zwischen Vcc und den Pins damit man was
sieht.
Wenn Du das zum Laufen kriegst, sieht Du ja auch dem Unterschied zum
PCF8574. Du kannst dann auch Dein Program entsprechend umändern und
vereinfachen so dass es auch mit dem PCF8574 funktioniert. Beachte dass
der PCF8574 Open Drain Ausgänge hat und das LED von Vcc angeschlossen
werden muss.
Am besten verkapsle die I2C Schreibinstruktionen in eine immer wieder
verwendbare Funktion zur bequemen Anwendung wie ich sie Dir schon früher
gezeigt hatte.
Bei den 16-bittigen IO expandern sind einfach die doppelte Anzahl der
internen Register vorhanden. Es gibt keinen wirklichen Unterschied im
Konzept.
Viel Erfolg!
Gruss,
Gerhard
Hallo Gerhard
habe den Code geschrieben. Er geht, aber einge Sachen verstehe ich
nicht.
Auch die angegebenen Daten/Einstellungen fumktionoeren nicht richtig.
Ist der erste Versuch mit diesem IC, daher auch das einfache Programm.
Arbeite mit 16 MHz, C, ATmega1284p
Der Code:
1
intmain(void)
2
{
3
i2c_init();// Starte I2C Bus
4
5
while(1)
6
{
7
i2c_start(adr1_w);/* MASTER weckt alle Busteilnehmer auf damit sie wissen dass jetzt der MASTER sprechen wird */
8
//i2c_write(adr1_w); /* Adressiere PCA9536 0x82*/
9
i2c_write(0x03);/* Index auf OUTPUT REGISTER stellen */
10
i2c_write(0x02);/* Alle Port Pins hochstellen */
11
i2c_stop();/* Stop Condtion setzen damit der PCA9536 weiß das wir fertig sind */
12
}
13
}
Als Adresse habe ich 0x82 eingestellt und verwende die Datein von Peter.
i2c_write(0x03); /* Index auf OUTPUT REGISTER stellen */
Mit dieser Zeile könnte ich invertieren, nur bei Input?
i2c_write(0x02); /* Alle Port Pins hochstellen */
Mit dieser Zeile kann ich die verschiedenen Pins ansteuern. Ist die
Eingabe 0 bis 8 korrekt? Oder nur 0 bis 3?
Das grösste Problem ist aber was anderes.
Das Programm hängt sich manchmal auf. Dann lassen sich die Pins nicht
umschalten
achim
Hi Achim,
das ist noch nicht ganz richtig. Du mußt zuerst den PCA9536 auf OUTPUT
MODUS umstellen. Nach dem Einschalten ist er nämlich immer noch im INPUT
MODUS.
Versuchs noch einmal:
Aufpassen, daß Du die MCU Clock richtig angibst und die delay.h lib
einbindest. Ich arbeite normalerweise mit GCC_AVR nicht - weiß also
nicht ob alles mit Setup und Syntax stimmt. Darum mußt Du Dich kümmern.
#define F_CPU 16000000UL // 16 MHz
#include <util/delay.h>
int main(void)
{
i2c_init(); // Starte I2C Bus
/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */
i2c_start(0x82); /* 0x82 = Schreib Modus */
i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */
i2c_write(0x00); /* Alle Port Pins auf OUTPUT MODUS stellen */
i2c_stop();
/* Loop startet hier */
while(1)
{
// Die o/p pins auf Hoch Stellen
i2c_start(0x82); /* 0x82 = Schreib Modus */
i2c_write(0x01); /* Index auf OUTPUT DATA stellen */
i2c_write(0x0F); /* Alle Port Pins hochstellen */
i2c_stop();
_delay_ms(500);
// Die o/p pins auf Null Stellen
i2c_start(0x82); /* 0x82 = Schreib Modus */
i2c_write(0x01); /* Index auf OUTPUT DATA stellen */
i2c_write(0x00); /* Alle Port Pins nullstellen */
i2c_stop();
_delay_ms(500);
}
}
Mit diesem Programm sollte alle Ausgänge im Sekunden Zyklus toggeln.
Versuch das mal. Wenn das einwandfrei funktioniert dann fang zu
experimentieren. Gut Glück!
Es ist normal für den Bus zu hängen wenn etwas mit der Hardware nicht
mehr stimmt.
mfg,
Gerhard
Achim Seeger schrieb:> Als Adresse habe ich 0x82 eingestellt und verwende die Datein von Peter.> i2c_write(0x03); /* Index auf OUTPUT REGISTER stellen */> Mit dieser Zeile könnte ich invertieren, nur bei Input?
Das Invertierung Register "POLARITY" ist nur für das Input Register
gedacht. Die Outputs werden davon nicht betroffen.
>> i2c_write(0x02); /* Alle Port Pins hochstellen */> Mit dieser Zeile kann ich die verschiedenen Pins ansteuern. Ist die> Eingabe 0 bis 8 korrekt? Oder nur 0 bis 3?
Für den PCA9536 sind wegen der vier Pins nur Werte von 0-15 zulässig.
Groessere Werte falten sich wieder im Modulo 16 auf. Z.B. Wenn Du den
Wert 17 eingibst, dann ist das gleich wie der Wert 1. Dasselbe gilt für
33 und so weiter. Bei einem 8-bittigen natürlich 0-255.
PIN0 = 1
PIN1 = 2
PIN2 = 4
PIN3 = 8
=========
Alle ein = 15
Alle aus = 0
mfg,
Gerhard
Hallo Gerhard
den oberen Bereich habe ich nicht reingestellt. Dort steht auch die
Frequenz und delay. Muss erst noch sortieren was gebraucht wird. Das mit
der Modus umstellung war mir nicht klar. Bin schon am testen und
probieren dran. Da ja die Ausgänge gehen, kann ich jetzt so richtig mit
spielen.
Fehlt nur noch das lesen
achim
Hallo Achim,
Das hört sich schon mal gut an!
Am Anfang mit neuer Hardware ist es immer gut eine Referenztestschaltung
und Treiber code zu haben der einwandfrei funktioniert.
Jedenfalls scheint der PCA9536 jetzt zu funktionieren. Sieh zu dass die
Delay funktioniert und lass die Ausgänge mit LEDs blinken.
Gerhard
Achim schrieb:> Hallo Gerhard> den oberen Bereich habe ich nicht reingestellt. Dort steht auch die> Frequenz und delay. Muss erst noch sortieren was gebraucht wird. Das mit> der Modus umstellung war mir nicht klar. Bin schon am testen und> probieren dran. Da ja die Ausgänge gehen, kann ich jetzt so richtig mit> spielen.> Fehlt nur noch das lesen> achim
Hallo Gerhard
Habe das Programm so geschrieben. Verwende die Datein von Peter. Die
Angaben Adresse und Frequenz habe ich in einen h geschrieben. Das
Programm läuft ohne Probleme. Kann die Ausgänge entsprechend ansteuern.
Habe die Kommentare reingeschrieben.
1
//#define F_CPU 16000000UL
2
#include"main.h" // Angabe der Adresse und Frequenz
3
#include"i2cmaster.h" // Aufruf twimaster
4
5
intmain(void)
6
{
7
i2c_init();// Starte I2C Bus
8
// PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig!
9
i2c_start(adr1_w);// adr1_w ist 0x82 = Schreib Modus
10
i2c_write(0x03);// Index auf CONFIG REGISTER stellen
11
i2c_write(0x00);// Alle Port Pins auf OUTPUT MODUS stellen
12
i2c_stop();
13
14
while(1)
15
{
16
i2c_start(adr1_w);// weckt Busteilnehmer auf
17
i2c_write(0x01);// Index auf OUTPUT Data stellen
18
i2c_write(0x09);// Port Pins stellen 0x00 bis 0x0f
19
i2c_stop();// Stop setzen damit der PCA9536 weiß das wir fertig sind
20
}
21
}
Damit haben wir das erste Programm fertig. Werde auch die andere Version
umsetzen.
achim
So moch der dritte Teil. Ist eigentlich wie das erste Programm. Die
taster werden von einem PCF8574 abgefragt und mit dem PCA9536 die
Ausgänge geschaltet. Die Adressen stehen wieder in einer main.h
1
//#define F_CPU 16000000UL
2
#include"main.h" // Angabe der Adresse und Frequenz
3
#include"i2cmaster.h" // Aufruf twimaster
4
5
unsignedchard;
6
7
int16_tvar;// Variable var
8
9
intmain(void)
10
{
11
i2c_init();// Starte I2C Bus
12
// PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig!
13
i2c_start(adr1_w);// adr1_w ist 0x82 = Schreib Modus
14
i2c_write(0x03);// Index auf CONFIG REGISTER stellen
15
i2c_write(0x00);// Alle Port Pins auf OUTPUT MODUS stellen
16
i2c_stop();
17
18
while(1)
19
{// Hauptschleife
20
i2c_start(adr2_w);// Schreibbefehl für Device 2
21
i2c_write(0xff);// Alle Pins des PCF auf 0
22
i2c_start(adr2_r);// Starte Lesezugriff
23
d=i2c_readNak();// Schreib Leseergebnis in d
24
25
if(~d&0x01)// Taste 1
26
var|=(1<<0);// Wenn T1 gedrückt ist...
27
else// wenn nicht dann ...
28
var&=~(1<<0);
29
30
if(~d&0x02)// Taste 2
31
var|=(1<<1);// Wenn T2 gedrückt ist...
32
else// wenn nicht dann ...
33
var&=~(1<<1);
34
35
if(~d&0x04)// Taste 3
36
var|=(1<<2);// Wenn T3 gedrückt ist...
37
else// wenn nicht dann ...
38
var&=~(1<<2);
39
40
if(~d&0x08)// Taste 4
41
var|=(1<<3);// Wenn T4 gedrückt ist...
42
else// wenn nicht dann ...
43
var&=~(1<<3);
44
45
i2c_stop();
46
47
i2c_start(adr1_w);// weckt Busteilnehmer auf
48
i2c_write(0x01);// Index auf OUTPUT Data stellen
49
i2c_write(var);// Port Pins stellen
50
i2c_stop();// Stop setzen damit der PCA9536 weiß das wir fertig sind
Hallo Achim,
Das sind schon mal gute Nachrichten. Du hast jetzt sozusagen ein
Referenz Design auf das Du Dich in der Zukunft beziehen kannst.
Jetzt ist es an der Zeit dass Du "lesen" lernst:-)
Du könntest jetzt versuchen die einzeln Register des PCA9536
zurückzulesen. Tom hat Dir ja schon gezeigt wie man das macht.
Wenn Du schon weißt wie man printf() übers UART gebraucht dann kannst Du
bequem Sequenziell alle vier Register auslesen.
Manche dieser PCA IO Expander haben auch einen Interrupt on Change
Ausgang was auch sehr nützlich ist wenn Du Pollen beim Abfragen von
externen PIN Änderungen vermeiden möchtest.
Wenn das alles funktioniert baue Dir eine Schreib- und Lesefunktion die
Du dann immer wieder verwenden kannst. Du baust Dir sozusagen eine
eigene Baustein Bücherei an nützlichen Funktionen mit denen Du auf alle
Deine Vorzugs ICs zugreifen kannst.
Mfg,
Gerhard
Hi Achim,
Sah gerade Deinen letzten Post.
Ich sehe dass Deine Stop Funktion erst später gesendet wird. Mach das
nicht. Das soll idealerweise immer gleich nach der letzten Instruktion,
also bei Deinem Lesevorgang erfolgen. Ziehe I2C Sequenzen nicht ohne
guten Grund auseinander. Ich finde das persönlich als schlecht an weil
das die Bustransaktion unnötig verlängert. Bei SMB Bausteinen kann das
möglicherweise je nach Umständen sogar zu einem Device Timeout Fehler
führen.
Gruß,
Gerhard
Hallo Gerhard
sorry, das versteh ich nicht. Beim letzten Programm wird zuerst der
PCF8574 ausgelesen und damit var gesetzt. Wenn ich alle 4 Eingänge
ausgelesen habe kommt stop und dann wird erst der PCA9536 gestartet und
var gesendet.
Hatte es so aufgefasst, das erst eine I2C Funktion abgearbeitet wird und
dann die nächste startet.
Mit printf habe ich schon gearbeitet, allerdings nicht mit UART. Erfolgt
das lesen wie es Tom beschrieben hat bzw so wie in dem oberen Programm,
oder muss ich was beachten?
Leider kann ich diese Funktion (Eingang lesen) nicht sofort so elegant
testen. Bei den Ausgängen habe ich Relais und LED dran. Da sehe ich
sofort was läuft. Die notwendige Platine ist leider noch nicht gekommen.
Dann kann ich auch Ein- und Ausgänge gleichzeitig schalten.
Kennst du den IC PCA9544 (Multiplexer 4 Kanal)?
Du hattest bereits oben eine Funktion kurz angedacht
Gerhard O. schrieb:> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8> databyte)
Ein int Aufruf mit übergabe der Adresse, command Register und Datenbyte
Achim Seeger schrieb:> i2c_start(adr1_w); // weckt Busteilnehmer auf> i2c_write(0x01); // Index auf OUTPUT Data stellen> i2c_write(var); // Port Pins stellen> i2c_stop(); // Stop setzen damit der PCA9536 weiß das wir> fertig sind> }
Noch die Klammer drunm und den Aufruf und fertig?
Da die Adresse beim PCA9536 feststeht und nicht ändern kann, geht der
Anschluss von mehreren an einem Bus nur mit dem PCA9544, (auch andere).
Nach deinem Schnellkurs im Datenblatt lesen werde ich mir das Datenblatt
ansehen und vielleicht verstehen.
achim
Hallo Achim,
Achim Seeger schrieb:> Hallo Gerhard> sorry, das versteh ich nicht. Beim letzten Programm wird zuerst der> PCF8574 ausgelesen und damit var gesetzt. Wenn ich alle 4 Eingänge> ausgelesen habe kommt stop und dann wird erst der PCA9536 gestartet und> var gesendet.> Hatte es so aufgefasst, das erst eine I2C Funktion abgearbeitet wird und> dann die nächste startet.
Das ist schon richtig. Es ist aber nicht gut eine unvollständige I2C
Transaktion durch Deinen eigenen Code wie Du gemacht hast unnötig ohne
wirklich guten Grund zu verlängern. Die stop() Funktion soll IMMER
gleich nach dem letzten write oder read erfolgen. Weiche davon nicht ab,
es ist meiner Ansicht auch schlechter Programmierstil. Wie schon gesagt,
man sollte den Bus nicht länger wie notwendig belegen. Sicher, in Deinem
Programm braucht das abarbeiten Deiner Bit Tests nicht viel Zeit, das
ist ja klar; aber hier geht es um das Prinzip, weil eines Tages Dich
solche Programmiersünden gründlich in den Hintern beißen werden. Die
Alligatoren warten nur darauf:-)
> Mit printf habe ich schon gearbeitet, allerdings nicht mit UART. Erfolgt> das lesen wie es Tom beschrieben hat bzw so wie in dem oberen Programm,> oder muß ich was beachten?
Das kann ich Dir nicht genau beschreiben da ich selber noch nicht mit
GCC_AVR gearbeitet habe. Jeder Kompiler hat seine eigenen Vorschriften
zum Gebrauch. Ich glaube Peter Fleury hat auch Kommunikation-Libraries.
Folge seinem Beispiel und das ist wahrscheinlich ein guter Anfang den
Seriell-Port zum Arbeiten kriegen. Wie das mit GCC_AVR spezifisch
gemacht wird kann ich nicht beurteilen.
Das lesen der I2C Register machst Du im Prinzip genau wie Tom es Dir
schon beschrieben hat. Ist ja im Prinzip mit dem PCF8574 verwandt.
> Leider kann ich diese Funktion (Eingang lesen) nicht sofort so elegant> testen. Bei den Ausgängen habe ich Relais und LED dran. Da sehe ich> sofort was läuft. Die notwendige Platine ist leider noch nicht gekommen.> Dann kann ich auch Ein- und Ausgänge gleichzeitig schalten.> Kennst du den IC PCA9544 (Multiplexer 4 Kanal)?> Du hattest bereits oben eine Funktion kurz angedacht
Den PCA9544 kenne ich und ist nützlich. Aber in Deinem Fall kannst Du
das Problem mit anderen ICs lösen. In Deinem Fall solltest Du nämlich
andere IO-Expander berücksichtigen. Die PCA9554 und PCF8574 haben drei
Hardware I2C Adressen Pins. Damit kannst Du acht Stück auf einen
einzelnen I2C Bus anschließen. Dann gibt es noch den PCA9554A wo die
Adressen noch einmal um 8 verschoben sind. Da kannst Du also 16 PCA9554
betreiben mit bis zu 128 Pins!
>> Gerhard O. schrieb:>> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint_8>> databyte)>> Ein int Aufruf mit übergabe der Adresse, command Register und Datenbyte>> Achim Seeger schrieb:>> i2c_start(adr1_w); // weckt Busteilnehmer auf>> i2c_write(0x01); // Index auf OUTPUT Data stellen>> i2c_write(var); // Port Pins stellen>> i2c_stop(); // Stop setzen damit der PCA9536 weiß das wir>> fertig sind>> }>> Noch die Klammer drum und den Aufruf und fertig?> Da die Adresse beim PCA9536 feststeht und nicht ändern kann, geht der> Anschluss von mehreren an einem Bus nur mit dem PCA9544, (auch andere).> Nach deinem Schnellkurs im Datenblatt lesen werde ich mir das Datenblatt> ansehen und vielleicht verstehen.> achim
1
#define PCA_WRITE_ADR 0x82
2
#define CFG_REGISTER 0x03
3
#define OUTPUT_REGISTER 0x01
Hier ist noch einmal mein Funktionsbeispiel zum beschreiben eines
Registers beim PCA9554:
I2C_write(register_index);// Setze lesezugriff Register Index
25
i2c_start(slave_address|0x01);// Starte Lesezugriff mit READ bit gesetzt
26
d=i2c_readNak();// Schreib Leseergebnis in d
27
I2C_stop();
28
29
returnd;
30
}
Das folgende Test Programm schreibt einen Wert ins Ausgangsregister und
liest selbigen zurück. Damit kannst Du den IC vollständig im einfachsten
Fall betreiben.
1
#include<stdio.h>
2
#include"main.h" // Angabe der Adresse und Frequenz
3
#include"i2cmaster.h" // Aufruf twimaster
4
5
/*
6
Hier musst Du den Serial Port initialisieren und Serial Port Einstellungen machen wie BAUDRATE, PARITY, STOPBITS
7
... (Siehe Peter Fleury Serial Library)
8
9
Aufpassen, daß Du den Serial-Port richtig mit Transceiver-Port anschließt da der AVR CMOS pegel hat
10
Entweder FTDI232RL + MAX232 oder chinesisches USB Kabel mit SERIAL CMOS ein- und Ausgängen, meist mit Prolific PL2303 USB/SERIAL drinnen)
// Soll am Terminal so aussehen: "PCA9536 Register 0 Wert = 0x05"
40
41
while(1);// End Program hier da kein Betriebssytem vorhanden ist.
42
43
}
Ich schlage Dir, befasse Dich mit diesem Test Programm und höre mit der
Fehlersuche nicht auf bis es funktioniert. Dann hast Du ein komplettes
Referenz Design das Dir bei einer zukünftigen etwaigen Fehlersuche
verhilft.
Ich habe nicht die Absicht Dir alles vorzukauen. Es ist aber meine
Erfahrung, daß es am Anfang wenn man mit neuen ICs arbeitet, durchaus
nützlich ist etwas konkrete Anleitung zu haben. Das soll Dich aber nicht
abhalten die Referenzunterlagen zu studieren und damit arbeiten bis Du
wirklich alles gründlich verstehst.
Das obige Test Programm schreibt einen Wert ins Ausgangsregister und
liest selbigen zurück. Damit kannst Du den IC vollständig im einfachsten
Fall betreiben.
Gut Gelingen!
mfg,
Gerhard
Hallo Gerhard
habe gerade die letzten Fehler gefunden. Mist - gross und
kleinschreibung.
Einen Buchstaben übersehen und man sucht stunden daren. Egal es geht
jetzt. Habe auch das ändern der Variablen und Angaben verstanden und
angepasst.
Der Code:
1
//#define F_CPU 16000000UL
2
#include"main.h" // Angabe der Adresse und Frequenz
// PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig!
23
i2c_start(adr1_w);// adr1_w ist 0x82 = Schreib Modus
24
i2c_write(0x03);// Index auf CONFIG REGISTER stellen
25
i2c_write(0x00);// Alle Port Pins auf OUTPUT MODUS stellen
26
i2c_stop();
27
28
while(1)
29
{// Hauptschleife
30
i2c_start(adr2_w);// Schreibbefehl für Device 2
31
i2c_write(0xff);// Alle Pins des PCF auf 0
32
i2c_start(adr2_r);// Starte Lesezugriff
33
d=i2c_readNak();// Schreib Leseergebnis in d
34
35
if(~d&0x01)// Taste 1
36
var|=(1<<0);// Wenn T1 gedrückt ist...
37
else// wenn nicht dann ...
38
var&=~(1<<0);
39
40
if(~d&0x02)// Taste 2
41
var|=(1<<1);// Wenn T2 gedrückt ist...
42
else// wenn nicht dann ...
43
var&=~(1<<1);
44
45
if(~d&0x04)// Taste 3
46
var|=(1<<2);// Wenn T3 gedrückt ist...
47
else// wenn nicht dann ...
48
var&=~(1<<2);
49
50
if(~d&0x08)// Taste 4
51
var|=(1<<3);// Wenn T4 gedrückt ist...
52
else// wenn nicht dann ...
53
var&=~(1<<3);
54
55
i2c_stop();
56
57
PCA9536_Write(adr1_w,cr_slave,var);
58
59
}
60
}
ansonsten geb ich dir recht (aus erfahrung). Mit einem lauffähogen Code
lernt sich weitaus besser. Manchmal reicht auch Schubs in die richtige
Richtung weiter (siehe Falk und Karl Heinz). Zum Code. Habe den Aufruf
in eine int gelegt. Die Slave Adresse und die Frequenz habe ich einer h
geschrieben. Das Programm läuft ohne Probleme. Habe einige Angaben
verändert und getestet.
Deinen letzten Text muss ich gründlich vornehmen. Danke
achim
@ Achim Seeger (achims)
>jetzt. Habe auch das ändern der Variablen und Angaben verstanden und>angepasst.>Der Code:
Naja, es bewegt sich immerin irgendwie in die richtige Richtung.
>//#define F_CPU 16000000UL>#include "main.h" // Angabe der Adresse und Frequenz>#include "i2cmaster.h" // Aufruf twimaster
Nix Aufruf, EINFÜGEN
>unsigned char d;>uint8_t var; // Variable var
Apfelmus ist Mus aus Äpfeln. Solche Kommentare kannst du dir sparen.
//#define adr1_w 0x82
#define cr_slave 0x01
Ja was denn nun? Drei Dutzend #define und dann doch ein anderes benutzt.
Das ist reichlich unsinnig.
>int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint8_t databyte)>{> i2c_start(slave_address);> i2c_write(cmd);> i2c_write(databyte);> i2c_stop();>}
GENAU! So wird ein Schuh drauf. Sinnvolle Funktion zusammenstellen!
>int main(void)>{> i2c_init(); // Starte I2C Bus> // PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig!> i2c_start(adr1_w); // adr1_w ist 0x82 = Schreib Modus> i2c_write(0x03); // Index auf CONFIG REGISTER stellen> i2c_write(0x00); // Alle Port Pins auf OUTPUT MODUS stellen> i2c_stop();
Warum zum Geier NUTZT du deine neue Funktion PCA9536_Write hier nicht?
> if (~d & 0x01) // Taste 1> var |=(1<<0); // Wenn T1 gedrückt ist...> else // wenn nicht dann ...> var &=~(1<<0);
Das gewöhn dir mal GANZ schnell wieder ab! Das schreit nach Problemen.
Man sollte bei if() IMMER Klammern setzen UND einrücken!
Warum? Ersten, weil es die Leute, die Doom, Quake und Co programiert
haben auch so gemacht haben, zweitens weil die Lesbarkeit DEUTLICH
verbessert wird und man drittens ohne Gefahr Befehle in die Zweige
einfügen kann, die sonst NICHT drin stehen würden!
Hi Achim,
Ich sehe die Stop Funktion ist noch immer dort. Sie soll gleich nach der
Lese Funktion kommen und nicht meilenweit mit Deinem Code dazwischen.
Es ist empfehlenswert eine I2C Sequenz immer vom start bis stop
zusammenhängend zu schreiben. Ziehe Teile der Sequenz nicht auseinander
- Du spielst potenziell mit Feuer! Ändere das umgehend.
Ja, das mit der Groß und Kleinschreibung kenne ich. Da mußt dich dran
gewöhnen. Der C Compiler ist nicht gerade für seine Eloquenz der
Fehlermeldungen bekannt. Den ersten Fehler sollte man immer genau
studieren. Das spart Dir manchmal seitenlange Fehlerlisten.
Am Anfang ist es halt so, dass man in C alle Augenblicke an einer
Bananenschale ausrutscht. Nach einiger Zeit gewöhnt man sich daran und
wird auch selber viel disziplinierter im Syntax und Gebrauch der Sprache
und die Fehler reduzieren sich gewaltig. Es ist gar nicht ungewöhnlich
eine ganze Funktion oder Seite von Code zu schreiben der dann auf Anhieb
funktioniert. Es kommt aber auch manchmal vor, dass man stundenlang an
einem fast unsichtbaren Fehler sucht.
Ich habe den Eindruck, dass Du Auf dem Weg bist wo das explorieren im
Code langsam Spass macht. Nur weiter so.
Lerne auf alle Fälle wie man Seriell Kommunikation macht. Das ist beim
Debuggen sehr nützlich. Wenn Du wirklich Deluxe Debugging genießen
willst, dann migriere später zu einem größeren MCU wie z.B. bei den
STM32 wo ein JTAG ein Standard ist und es gute integrierte
Entwicklungstools wie CooXox gibt. Bei den AVRs kenne ich mich in der
Hinsicht nicht aus welche Typen mit JTAG unterstützt werden. Da kriegst
Du aber hier bestimmt eine Menge an Informationen. Ich arbeite nur
selten mit AVRs und debugge alles in altmodischer Weise mit Seriell
Port, Oszilloskop, Logikprobe, LEDs und eine gehörige Menge an
Intuition. Intuition schärft das Fehlersuchen. Wenn man auf dem Gebiet
schon Erfahrung hat, findet man viele Probleme mir etwas Überlegung und
einfache Tests recht schnell. Bei einfacheren Projekten und als Hobbyist
ist das durchaus ausreichend. In professionellen Entwicklungssituationen
sind natürlich andere Maßstäbe anzulegen weil "Time is Money" ist, man
fähigere Tools braucht und ganz wichtig, hochbezahlte Spezialisten
einstellt die auch die theoretischen Grundlagen für die richtige
Anwendung und gezielten Einsatz von sophistikierten Algorithmen haben
und sich oft mit hochkomplexen Industrie Anwendungen herumschlagen
müssen. Das ist natürlich eine ganz andere Liga. Als Hobbyist stösst man
hier manchmal schnell an die Grenzen des erreichbaren in Bezug auf
Kenntnisse. Da schließe auch ich mich ein. Aber das bedeutet natürlich
nicht, dass man nicht auch selber auch schöne Projekte durchziehen kann
die viel Freude bereiten können. Jeder tut halt sein Bestes je nach
seinen Fähigkeiten. Man kann ja dazulernen.
Noch einen schönen Abend, dann,
Gerhard
Hallo Gerhard
sorry, das verstehe ich nicht so richtig mit dem stop. Ich muss doch die
Taster abfragen und das bit entsprechend setzen. Wie soll ich das kürzer
machen bzw dichter dran?
Habe jetzt das Stück von Falk geholt und baue es ein.
Hallo Falk
das sind meine Kommentare. Habe sie so einfach drin und nicht weiter auf
den Ausdruck geschaut. Brauche sie bald gar nicht mehr. Das mit der
Abfrage der taster hat nur die Aufgabe, das ich es verstehe. Es kann
immer besser gemacht werden. Deine Anmerkung ist aber wieder ein Grund
das Stück noch mal anzusehen und einzufügen. Auch mit deiner Kritik
bringst du mich weiter.
Noch mal zu dem IC. Bei einigen Anwendungen ist der Nutzen von 8 Bit
einfach zu viel. Wenn ich nur 4 Relais oder LED habe reicht der kleine
IC vollkommen aus. Manchmal reichen sogar 2 Pins oder 1 Pin. Leider ist
in dieser Grösse nichts zu finden. Nehme ich den PCA habe ich den
nachteil der Adressen. Deshal auch die Frage zu dem anderen IC
achim
Hallo Achim,
Achim Seeger schrieb:> Hallo Gerhard> sorry, das verstehe ich nicht so richtig mit dem stop. Ich muss doch die> Taster abfragen und das bit entsprechend setzen. Wie soll ich das kürzer> machen bzw dichter dran?
Seh Dir mal meine kleine Änderung an. So meinte ich das:
1
while(1)
2
{// Hauptschleife
3
i2c_start(adr2_w);// Schreibbefehl für Device 2
4
i2c_write(0xff);// Alle Pins des PCF auf 0
5
i2c_start(adr2_r);// Starte Lesezugriff
6
d=i2c_readNak();// Schreib Leseergebnis in d
7
// Die Stop Condition muss hier kommen
8
i2c_stop();
9
10
// Der folgende Code hat NICHTS mit I2C zu tun
11
12
if(~d&0x01)// Taste 1
13
var|=(1<<0);// Wenn T1 gedrückt ist...
14
else// wenn nicht dann ...
15
var&=~(1<<0);
16
17
if(~d&0x02)// Taste 2
18
var|=(1<<1);// Wenn T2 gedrückt ist...
19
else// wenn nicht dann ...
20
var&=~(1<<1);
21
22
if(~d&0x04)// Taste 3
23
var|=(1<<2);// Wenn T3 gedrückt ist...
24
else// wenn nicht dann ...
25
var&=~(1<<2);
26
27
if(~d&0x08)// Taste 4
28
var|=(1<<3);// Wenn T4 gedrückt ist...
29
else// wenn nicht dann ...
30
var&=~(1<<3);
31
32
// Die Stop Condition soll gleich nach der letzten I2C Funktion kommen.
33
// i2c_stop();
34
35
PCA9536_Write(adr1_w,cr_slave,var);
36
37
}
> Habe jetzt das Stück von Falk geholt und baue es ein.>> Hallo Falk> das sind meine Kommentare. Habe sie so einfach drin und nicht weiter auf> den Ausdruck geschaut. Brauche sie bald gar nicht mehr. Das mit der> Abfrage der taster hat nur die Aufgabe, das ich es verstehe. Es kann> immer besser gemacht werden. Deine Anmerkung ist aber wieder ein Grund> das Stück noch mal anzusehen und einzufügen. Auch mit deiner Kritik> bringst du mich weiter.>> Noch mal zu dem IC. Bei einigen Anwendungen ist der Nutzen von 8 Bit> einfach zu viel. Wenn ich nur 4 Relais oder LED habe reicht der kleine> IC vollkommen aus. Manchmal reichen sogar 2 Pins oder 1 Pin. Leider ist> in dieser Grösse nichts zu finden. Nehme ich den PCA habe ich den> nachteil der Adressen. Deshal auch die Frage zu dem anderen IC> achim
Das verstehe ich nicht, wenn Du den PCA9544 Bus Selektor verwenden
willst, sagst ja indirekt, daß Du noch mehr PCA9536 Bausteine einsetzen
willst.
Dan kannst Du gleich einen höherwertigen IO-Expander einsetzen und die
Bits in Gruppen zu unterteilen. Irgendwie verstehe ich nicht ganz warum
Du mehr als einen I2C Bus verwenden willst.
Bitte beschreibe genau was Du letztlich bauen willst. Irgendwie hat das
im Augenblick wenig Sinn mit dem PCA9544. Ich blick da nicht ganz durch
was Du dabei bezweckst.
Es macht keinen Unterschied im logischen Ablauf ob Du jetzt zwei PCA9536
oder einen PCF8574 oder PCA9554. Wenn Du z.B. zwei unabhaengighe
Bitgruppen zu je 4-bit haben willst geht das auch indem Du die
Bitgruppen aufteilst und durch OR und ANDING steuerst.
z.B.
bits_high = 15; // Wert von 0-15 erlaubt
bits_low = 15; // Wert von 0-15 erlaubt
// Setz neues Datenwort zusammen
PCA9554_data = (bits_high << 4) + (bits_low & 0x0F);
// Schreibe gemeinsames Datenwort auf PCA9554PCA9554_Write(PCA9554_SLAVE_ADDR, OUTPUT_REGISTER, PCA9554_data);
bits_low ist ein virtueller PCA9536, und
bits_high ist der zweite virtuelle PCA9536
Gerhard
Achim Seeger schrieb:> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint8_t> databyte)> {> i2c_start(slave_address);> i2c_write(cmd);> i2c_write(databyte);> i2c_stop();> }
Was ich hier vermisse, ist daß sich jemand um ACK bzw NAK vom Slave
kümmert. IMHO liefert i2c_start() einen Fehlerstatus. Wenn der Slave
seine Adresse nicht mit ACK quitiert, braucht man garnicht erst
weiterzumachen.
MfG Klaus
Klaus schrieb:> Achim Seeger schrieb:>> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint8_t>> databyte)>> {>> i2c_start(slave_address);>> i2c_write(cmd);>> i2c_write(databyte);>> i2c_stop();>> }>> Was ich hier vermisse, ist daß sich jemand um ACK bzw NAK vom Slave> kümmert. IMHO liefert i2c_start() einen Fehlerstatus. Wenn der Slave> seine Adresse nicht mit ACK quitiert, braucht man garnicht erst> weiterzumachen.
Ich bin der Ansicht es ist im Augenblick noch zu früh dafuer. Entweder
es funktioniert am Bus oder das ganze hängt sich auf. Ist ja nur erster
experimenteller Lerncode.
>> MfG Klaus
Muß weg, Jemand ist an der Tür.
Es hat eigentlich nur den Zweck z.B. 2 Relaisgruppen mit jeweils 4
Relais anzusteuern. Dîe erste Gruppe ist dabei als einfache Relais
geschaltet. Während die zweite Gruppe als Storenschalter arbeitet. Dabei
sind immer 2 Relais zusammengeschaltet und müssen entsprechend ein und
ausgeschaltet werden. Erst Netz weg und dann Umschaltung und wieder Netz
ein. Alles mit Zeitverzögerung. Das andere Projekt ist eine Schaltuhr, 1
Kanal, als externe Quelle. Schaltet nur einen Kanal ein. Die anderen 3
Pins nutze ich dann als Anzeige bzw quittung. Daher auch die Frage nach
dem PCA. Eines noch, so wie es aussieht wird das DIL wohl bald auslaufen
und nur noch SMD geben.
Zu deinem kleinen Code, ich dachte, die Abfrage muss innerhalb sein.
Stimmt du hast recht. Wieder was zum testen und ändern
Eine ACK auswertung habe ich hier noch nicht drin. Bei dem Programm zum
LM75 frage ich es ab. Soll später kommen.
Vielleicht hast du eine Idee wie man es machen kann.
Rückgabe mit return 0 oder 1 und Anzeige dazu?
Wie kann man eine Anzeige dazu machen? über LED und blinken?
Auch wenn mich jetzt einige Leute am besten zum Mond schicken wollen,
oder Tastatur weg nehmen usw., es ist immer noch Multitasking
vorgesehen. Denke dabei an Tasterentprellung von Peter oder anderes.
Klaus schrieb:>> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint8_t>> databyte)>> {>> i2c_start(slave_address);>> i2c_write(cmd);>> i2c_write(databyte);>> i2c_stop();>> }
z.B.:
( zum Code dazu) Auswertung?
ACK=0
return 0
ACK=1
return 1
achim
Hallo Achim,
Achim Seeger schrieb:> Es hat eigentlich nur den Zweck z.B. 2 Relaisgruppen mit jeweils 4> Relais anzusteuern. Dîe erste Gruppe ist dabei als einfache Relais> geschaltet. Während die zweite Gruppe als Storenschalter arbeitet. Dabei> sind immer 2 Relais zusammengeschaltet und müssen entsprechend ein und> ausgeschaltet werden. Erst Netz weg und dann Umschaltung und wieder Netz> ein. Alles mit Zeitverzögerung. Das andere Projekt ist eine Schaltuhr, 1> Kanal, als externe Quelle. Schaltet nur einen Kanal ein. Die anderen 3> Pins nutze ich dann als Anzeige bzw quittung. Daher auch die Frage nach> dem PCA. Eines noch, so wie es aussieht wird das DIL wohl bald auslaufen> und nur noch SMD geben.
Ich will Dir eigentlich raten es doch mit den 8-Bittern zu versuchen.
Macht doch nichts wenn ein paar Bits unbenutzt bleiben. So viel teurer
sind doch die PCA9554 im Vergleich zu einem PCA9536 auch nicht. Ein paar
verschwendete Bits schaden doch niemand und erlaubt
Zukunftserweiterungen.
Abgesehen davon kann man das Datenwort individuell in Bits durch
Software manipulieren und jedes Bit arbeitet dann für sich selbst. Nur
die Refresh-Timing erfolgt zusammen. Im Prinzip sollte ein einzelner
IO-Expander alles für Dich erledigen können. Du mußt halt die Software
etwas ausgeklügelter entwerfen.
>> Zu deinem kleinen Code, ich dachte, die Abfrage muss innerhalb sein.> Stimmt du hast recht. Wieder was zum testen und ändern
Gut.
>> Eine ACK auswertung habe ich hier noch nicht drin. Bei dem Programm zum> LM75 frage ich es ab. Soll später kommen.> Vielleicht hast du eine Idee wie man es machen kann.> Rückgabe mit return 0 oder 1 und Anzeige dazu?> Wie kann man eine Anzeige dazu machen? über LED und blinken?> Auch wenn mich jetzt einige Leute am besten zum Mond schicken wollen,> oder Tastatur weg nehmen usw., es ist immer noch Multitasking> vorgesehen. Denke dabei an Tasterentprellung von Peter oder anderes.
Zur ACK-Auswertung mußt die I2C Library durchsuchen. Die Schreib
Funktion muß das Testen und den ACK Status im Return Status zurückgeben.
Studiere das Manual der I2C Library vom Peter. Da sollte der Gebrauch
des ACK Status dokumentiert sein. Es ist meine Ansicht daß so etwas im
Augenblick Deinen Code nur unnötig kompliziert und dem Codeverständnis
als Angehender nicht sehr dienlich ist.
Das Testen des ACK ist zum Beispiel beim EEPROM schreiben sehr nützlich
weil das Beschreiben meist zwischen 5-10ms dauert. Dazu macht man dann
nach Schreiben des letzten DatenBytes eine Loop und sendet periodisch
ein Write mit der Slave-Address und wartet auf die 1->0 Transition des
ACK Bits. Sobald das EEPROM durch runterziehen des ACK damit
signalisiert daß der Schreibvorgang beendet ist, kann Dein Programm
weitermachen. Meist verbindet man das mit einem TIMEOUT Test um zu
verhindern daß sich das Programm durch irgendein Versagen aufhängt.
Merke: Bei jeden Test wo die Terminierung des Tests ausbleiben könnte,
muß in wirklichen Applikationen ein TIMEOUT-Test integriert werden
welcher den Test mit Sicherheit beendet damit das Programm nach eine
vorbestimmten Zeit nicht permanent in dieser Loop hängenbleibt.
Merke: Beim Schreiben wartet der MASTER auf ein ACK; beim LESEN wartet
der SKLAVE auf ein ACK vom MASTER. Es hängt also vom jeweiligen Betrieb
ab wer wen nach ACK abfragt.
Im Augenblick hat der ACK Test nur beim Sachen wie z.B. EEPROM-BUSY
polling für Dich eine praktische Bedeutung. Mein Rat: Auch Wenn es Klaus
gutgemeint hat, vergiß es für jetzt. Es macht Dir nur das Leben schwer.
(Sorry, Klaus)
Das mit dem LED Blinken geht über I2C auch, obgleich ich das lieber mit
einem direkten Port-Pin im Interupt Timer Betrieb machen würde. I2C Port
Expansion ist eher für etwas langsame Vorgange beabsichtigt wie ein
Relais einschalten, einen Schalter abfragen, oder einen Tuner Chip mit
einer neuen Frequenz zu programmieren. Lese mal die alten Philips/NXP
App Notes zum primären Zweck von I2C Anwendungen. Für schnelle
Reaktionen wenn IO-Expander verwendet werden müssen, nimmt man besser
SPI Typen.
Bei normalen I2C ist die Datengeschwindigkeit bis auf ein paar spezielle
Ausnahmen abgesehen unter oder bis 400kB. Für schnellere
Datengeschwindigkeit brauchst Du spezielle ICs und auch der Bus muß das
noch verkraften können. Durch kapazitive Belastung braucht es schon an
einigem Können und Maßnahmen seitens des Entwicklers so einen schnellen
I2C Bus zuverlässig betreiben zu können. "Don't even think about it!"
rate ich Dir. Wenn Geschwindigkeit von Nöten ist, nimm besser SPI.
Noch ein großer Vorteil von vielen 8-bittigen IO-Expandern ist das
Vorhandensein eines INTERRUPT Ausganges. Mit Hilfe des Interrupts kann
man den MCU unterbrechen wenn sich irgendein HW-Pin am IO-Expander
ändert. Das erspart das ständige Pollen. Den Vorteil hat Dein PCA9536
nicht.
Gerhard
> achim
Hallo Klaus,
mir kommt vor nur die professionellen Entwickler tun das scheinbar. Die
meisten Sourcen die ich bis jetzt von anderen Leuten gesehen habe,
machen das anscheinend nicht. Im Prinzip hast ja recht.
In Hobby Programmen scheint sich meist fast kein Mensch darum zu
scheren. EEPROM Schreib Vorgang Polling ist sonst einer der wenigen
Fälle wo das ACK-Polling bei mit Timeout bei einfachen MCUs Sinn hat und
besser als Warten ist.
Am Ende hängt es halt davon ab wie zuverlässig das Ganze unter allen
Umständen funktionieren soll. Wenn ein MP3-Abspielgerät sich deswegen
aufhängt ist das nicht ganz so schlimm wie in einer professionellen
Anwendung die unter allen Umständen betriebsfähig sein muß.
Gerhard
Klaus schrieb:> Achim Seeger schrieb:>> int8_t PCA9536_Write(uint8_t slave_address, uint8_t cmd, uint8_t>> databyte)>> {>> i2c_start(slave_address);>> i2c_write(cmd);>> i2c_write(databyte);>> i2c_stop();>> }>> Was ich hier vermisse, ist daß sich jemand um ACK bzw NAK vom Slave> kümmert. IMHO liefert i2c_start() einen Fehlerstatus. Wenn der Slave> seine Adresse nicht mit ACK quitiert, braucht man garnicht erst> weiterzumachen.>> MfG Klaus
Guten Morgen an alle und einen schönen Sonntag wünsche ich.
Einen wichtigen Grund gibt es für mich noch. Das ist der IC selber.
Einmal die Grösse. Den kann man sooo schön auf die Leiterzüge löten und
darüber sogar Bauteile legen. Viel wichtiger ist was anderes. Es gibt so
viele Ics und Datenblätter dazu. Die meisten (so wie ich) kommen nur
bedingt damit klar. Beispiel in Form von Codes (lauffähig) findet man
kaum. Das Ergbenis ist immer das gleiche, man verliert die Lust. Das
möchte ich ändern. Eine Erklärung zum IC, mit Anwendung, ein Programm
was läuft und Kommentare dazu. Das gibt genug Raum für eigene Versuche
und Anwendungen. Ich nutze gern einen blöden Spruch:
Ich frage solange bis ich auch die Erklärung verstanden habe
Manche haben mich gross angesehen, was das soll. Dann merkt man wie der
Groschen fällt. Es ist schon fast eine Gabe, komplizierte Zusammenhänge
einfach zu Erklären, so das es ein Anfänger aber auch Fortgeschrittener
verstehen kann. Manche Leute platzen grade zu vor Wissen. Find ich toll.
Doch was nützt einem das grosse Wissen, wenn man es nicht rüber bringen
kann.
Noch mal zum Anfang, Dieser IC gehört zum Bus, möchte ihn deshalb
anwenden und programmieren können. Auch die anderen IC gehören zur
Familie, Einge habe ich schon angewendet und nutze sie, andere warten
noch drauf. Sieh dir Karl Heinz und Falk an. Von denen hab ich schon so
viel Feuer und auch Hilfe bekommen. Ich mach aber weiter. Werde nie die
Qualität haben, habe aber Spass an der Sache
achim
voidtemperfassung()// Temperfassung und Fehlermeldung
2
{
3
ret=i2c_start(lm75_w);// Abfrage LM75
4
i2c_write(0x00);// 0x00 Temperatut
5
i2c_stop();// 0x03 abfrage oberes Temp
6
if(ret==0)// 0x02 abfrage unetre Temp
7
{// Wenn LM75 ein OK sendet...
8
i2c_start(lm75_r);
9
msb_temp=i2c_readAck();// ...speichere oberes Bit
10
lsb_temp=i2c_readNak();// ...speichere unteres Bit
11
i2c_stop();
12
}
13
else// Fehlererkennung
14
{// Wenn LM75 kein OK sendet
15
lcd_command(LCD_CLEAR);// Leere Display
16
_delay_ms(2);// Warte 2ms
17
lcd_printlc(2,6,"LM 75");// "LM 75"
18
lcd_printlc(3,5,"Nicht OK");// "Nicht OK"
19
_delay_ms(2000);// Warte 2s
20
}
21
}
stammt von Falk, habe es nur zu meinen Sachen angepasst. Im ori prüft es
einen LM75 und bringt dann eine Fehlermeldung auf ein Display. Man
könnte hieraus eine universelle Abfrage bauen. Über int ..., Abfrage und
mit return zurück, mehrmalige Abfrage mit unterschiedlichen Adressen und
Fehleranzeige. Ist das msb und lsb dazu notwendig? Hast du eine Idee für
eine einfache Abfrage?
achim
Ein wenig Pseudocode:
if(i2c_start(xxxx) == NAK) {
// der Baustein ist nicht da, er hat kein Power, er ist nicht Ready
// oder die Adresse ist einfach falsch ....
i2c_stop(); // alle am Bus wissen: ich hab fertig
return ERROR;
} else {
// read sensor
.
.
MfG Klaus
Als nächste ist die Abfrage zur Adresse mir drin. Ist der PCA9536 mit
der Adresse nicht angeschlossen leuchtet eine LED am Prozessor, sonst
nicht. Die Auswertung könnte noch verbessert werden, z.B. blinken und
Abfrage weiterer Adressen und Rückgabe mit return und auswertung
1
//#define F_CPU 16000000UL
2
#include"main.h" // Angabe der Adresse und Frequenz
„Und weiter sah ich den Sisyphos in gewaltigen Schmerzen: wie er mit
beiden Armen in einem Mikrocomputer Forum irgendwo auf der Erde die
Tastatur bearbeitete. Ja, und mit Schwielen auf den Fingern, drückte er
immer wieder auf die Absende Taste. Doch sobald er wieder am Bildschirm
schauen wollte, war schon wieder eine Frage da: von neuem schrieb
Sisyphus wieder eine Antwort. Es kamen aber immer wieder neue Fragen und
er schrieb und schrieb, sich anspannend, und es rann der Schweiß ihm von
den Gliedern, und die Müdigkeit senkte sich über sein Haupt hinüber.“
Achim Seeger schrieb:> Guten Morgen an alle und einen schönen Sonntag wünsche ich.> Einen wichtigen Grund gibt es für mich noch. Das ist der IC selber.> Einmal die Grösse. Den kann man sooo schön auf die Leiterzüge löten und> darüber sogar Bauteile legen. Viel wichtiger ist was anderes. Es gibt so> viele Ics und Datenblätter dazu. Die meisten (so wie ich) kommen nur> bedingt damit klar. Beispiel in Form von Codes (lauffähig) findet man> kaum. Das Ergbenis ist immer das gleiche, man verliert die Lust. Das> möchte ich ändern. Eine Erklärung zum IC, mit Anwendung, ein Programm> was läuft und Kommentare dazu. Das gibt genug Raum für eigene Versuche> und Anwendungen. Ich nutze gern einen blöden Spruch:>
Die hersteller geben sich sogar oft sehr grosse mühe mit der erklärung
der Konzepte und korrekten gebrauch ihrer Ics.
> Ich frage solange bis ich auch die Erklärung verstanden habe
Wie lange soll das denn noch so weitergehen? Sisyphus ist im Vergleich
zu dir ein Amateur. http://de.m.wikipedia.org/wiki/Sisyphos>> Manche haben mich gross angesehen, was das soll. Dann merkt man wie der> Groschen fällt. Es ist schon fast eine Gabe, komplizierte Zusammenhänge> einfach zu Erklären, so das es ein Anfänger aber auch Fortgeschrittener> verstehen kann. Manche Leute platzen grade zu vor Wissen. Find ich toll.> Doch was nützt einem das grosse Wissen, wenn man es nicht rüber bringen> kann.
Das entspricht bestimmt nicht den Tatsachen. Die Leute im Forum geben
sich sogar sehr viel mühe und zeit mit dir.
> Noch mal zum Anfang, Dieser IC gehört zum Bus, möchte ihn deshalb> anwenden und programmieren können. Auch die anderen IC gehören zur> Familie, Einge habe ich schon angewendet und nutze sie, andere warten> noch drauf. Sieh dir Karl Heinz und Falk an. Von denen hab ich schon so> viel Feuer und auch Hilfe bekommen. Ich mach aber weiter. Werde nie die> Qualität haben, habe aber Spass an der Sache
Du denkst nur an dich!
> achim
Es grüsst, seufz,
Sisyphus
Hallo
Muss noch mal fragen. Habe jetzt das folgende Stück Code
1
// WTMA lesen
2
i2c_start(adr1_w);// Start Adresse 1
3
i2c_write(0x00);// Register Index
4
//i2c_write(0x00); //
5
i2c_start(adr1_r);// Starte Lesezugriff
6
ander=i2c_readNak();// Schreib Leseergebnis in dn
7
i2c_stop();
8
9
// Ausgabe auf LED am Tastenfeld
10
if(~ander&0x08)
11
{
12
i2c_start(adr2_w);
13
e=0x7e;//7e
14
i2c_write(e);
15
i2c_stop();
16
}
17
else
18
{
19
i2c_start(adr2_w);
20
e=0xff;//ff
21
i2c_write(e);
22
i2c_stop();
23
24
}
Die adr1 ist der PCA9536. Dort möchte ich nur den P3 auslesen. P0 bis P2
sollen LED schalten. Die Anzeige soll an der adr2 erfolgen.
P0 bis P2 gehen ohne Probleme. P3 nicht. Was habe ich vergessen?
achim
@ Achim Seeger (achims)
>P0 bis P2 gehen ohne Probleme. P3 nicht. Was habe ich vergessen?
Ja. Du hast mal wieder vergessen, wie Bitmanipulation funktioniert.
Dabei schreibt man NICHT einfache einen konstanten Wert irgendwie auf
ein Register, sondern setzt oder löscht explizit nur EIN Bit. Da
solltest du in der langen Zeit, in der du dich mit
Mikrocontrollerprogrammierung beschäftigst EIGENTLICH verstanden haben.
Aber du ignorierst es IMMER WIEDER gekonnt. Ausserdem fehlt bei deinem
2. Schreibzugriff die Registeradresse!
Dazu gibt es zwei Wege.
1.) Auslesen vom Ausgangsregister 01, Bitmanipulation des gewünschten
Bits und Rückschreiben des Registers.
2.) Eine lokale Kopie des Rigisters wird im Prozessor gespeichert, dort
wird die Bitmanipulation gemacht und nur das Register geschrieben. Man
erspart sich das Auslesen.
Und nutze doch ENDLICH mal deine Funktionen zum Lesen und Schreiben der
Register des PCA9536 und nutzt NICHT andauernd die grundlegenden I2C
Funktionen!
Wenn ich das DB richtig lese, dann mache ich mit
i2c_write(0x03); // Register Index - input
i2c_write(0x08); // Auswahl Bit
Im Datenblatt steht drin
i2c_write (0x03) // Command Byte - Coniiguration
i2c_write (0x00) // Input Port
Wenn ich dann die Angaben von Tom nehme, geht nichts mehr.
Sorry, komme nicht klar, wenn ich das DB nehme, geht nichts mehr. Nutze
auch die Bitmanipulation, Versteh nicht so richtig
achim
@ Achim Seeger (achims)
Leider muss ich meine mehrfach geäußerte Aussage wiederholen. Deine
Lernerfolge sind gering bis Null!
Dieser Thread beinhaltet 80! Beiträge. Davon sind einige so ausführlich,
dass es ein Blinder sieht, wie es laufen soll!
Beitrag "Re: Denkfehler mit PCA9536 (Problem)"Beitrag "Re: Denkfehler mit PCA9536 (Problem)"
DAS MUSST DU ENDLICH MAL UMSETZEN UND AUFHÖREN RUMZUMURKSEN!
Jaja ich weiß, pädagogisch wertvoll ist mein Beitrag nicht, geht aber
nicht anders!
Du brauchst exakt ZWEI Funktionen, um auf den PCA9536 zuzugreifen! DIESE
musst du EINMAL RICHTIG machen, danach musst du dich NIE MEHR um diese
Details kümmern! Das ist ein Grundprinzip der Informatik (Kapselung).
Und genau DAS wirst du JETZT tun!
Den Inhalt der Funktionen musst DU füllen! Der Rückgabewert sollte 0
sein, wenn kein I2C-Fehler aufgetreten ist, ansonsten ungleich null.
Wenn das irgendwann mal läuft, nutzt du in deinem Hauptprogramm NUR NOCH
diese beiden Funktionen, KEINERLEI direkten I2C Zugriff!
Etwas so.
Danke dir für deine Mühe. Setze mich gleich ran.
In einem Teil der Beiträge von mir hatte ich die Umsetzung der Probleme,
zB Abfragen, Fehler usw reingeschrieben. Da hatte sich aber gleich einer
beschwert. Diese Sachen nutze ich schon bei anderen Projekten. Erst muss
ich es verstehen, dann kann ich anderes machen.
Pädagogische Wertvoll oder nicht, ich will es verstehen und anwenden.
achim
Achim Seeger schrieb:> Hallo Falk> Gerhard hat oben geschrieben:
Gerhard hat viel geschrieben. Unter anderem auch fertige Funktionen für
einen kompletten Read und Write Zyklus.
Wenn er sich auf dein Niveau anpasst, dann ist das noch lange kein Grund
für dich, die Funktionen nicht zu benutzen.
> i2c_start(adr1_w); // adr1_w ist 0x82 = Schreib Modus> i2c_write(0x03); // Index auf CONFIG REGISTER stellen> i2c_write(0x00); // Alle Port Pins auf OUTPUT MODUS stellen> i2c_stop();
ALso die Prinzipielle Sequenz
* start mit Angabe der Adresse des I2C Bausteins und ob gelesen oder
geschrieben werden soll
* write Nummer des Registers oder wie es bei diesem Baustein heisst
'welches Commando'
* write den Wert, der in dieses mit dem Commando ausgewählte Register
soll
* stop
Und jetzt vergleich mal mit der Funktion:
die Logik stimmt auffallend überein!
Zuerst ein start (mit der Adresse), dann das Commando, dann der Wert und
hinten nach noch ein Stop.
D.h. die Funktion macht genau das was deine 4 Zeilen machen. Nur mit
einem kleinen Unterschied: die Funktion macht immer diese 4 Schritte und
vergisst keinen. Was man von dir und deinem Konglomerat nicht sagen
kann.
Nimmt man die Read Funktion von weiter oben noch mit dazu, dann baut
sich dein Programm so um, dass es deutlich einfacher zu lesen ist.
Denn anstelle von deinen 4 Funktionsaufrufen mit der windigen
Kommentierung steht dann nur noch 1 Zeile im Code, die sich so liest
1
PCA9536_Write(PCA9636_ADR,PCA9636_OUT_REG,0xFF);
und da brauch ich noch nicht mal einen Kommentar um zu wissen, dass mit
diesem Funktionsaufruf bezweckt wird, dass wohl der Wert 0xFF ins Output
Register vom PCA9536 geschrieben werden soll. Denn genau deswegen steht
dort PCA9636_OUT_REG, weil das Out(put) Register gemeint ist. Das merk
ich mir viel leichter als irgendeine windige Zahl, die ich dauern
nachschlagen müsste. Und wenn ich ins Config-Register ein 0x00 rein
schreiben will, dann schreibe ich
1
PCA9536_Write(PCA9636_ADR,PCA9536_CFG_REG,0x00);
denn wieder merke ich mir PCA9536_CFG_REG viel leichter als 0x03, bei
dem ich noch einen Kommentar dazu schreiben müsste, dass das das
Config-Register ist. Ist doch uninteressant. Kommentare sind Schall und
Rauch und ehe ich einen Kommentar nach diesem Muster schreibe
1
...
2
i2c_write(0x03);// Index auf CONFIG REGISTER stellen
kommt das auf das genau gleiche raus. Für den Computer. Fr mich nicht,
denn bei
1
PCA9536_Write(PCA9636_ADR,PCA9536_CFG_REG,0x00);
kann ich kaum einen Fehler machen. Der kleinste Tippfehler in
PCA9536_CFG_REG, und der Compiler klopft mir auf die Finger. Der
kleinste Tippfehler in
1
...
2
i2c_write(0x03);// Index auf CONFIG REGISTER stellen
3
...
und nichts oder das falsche passiert.
Aber, egal.
Ist eh Perlen vor die Säue, wenn man in 3 Monaten das Grundprinzip von
I2C nicht begriffen hat. So trivial dieses Prinzip auch ist. Manchmal
glaub ich auch, du weisst überhaupt nicht, was überhaupt Funktionen sind
und wie und warum man sie benutzt bzw. warum man sich welche schreibt.
Hallo Karl Heinz
danke für deine Hilfe. Ich weiss was Funktionen sind. Arbeite selber
damit. Habe nur eins damit gemacht. Habe sie langsam begriffen. Habe es
erst als I2C Funktion geschrieben und dann weiter in eine Funktion
übertragen. Wollte es einfach nur verstehen. Da es unterschiede zum PCF
8574 gibt, wollte ich den Unterschied sehen, verstehen und anwenden.
Habe einfach angefangen und gehe zu Funktionen über. Habe es oben weiter
gemacht. Es gibt viele andere ICs mit ähnlichen Aufruf oder
vergleichbarer Funktion. Da diese auch so benutzt werden, will ich diese
in Zukunft auch begreiffen.
achim
Ich will was lernen, das ist das wichtigste für mich. Lernen bedeutet
Fragen stellen und nach Antworten suchen. Die Antworten (das gelernte)
anwenden und nutzen in eigenen Projekten.
Ich habe keinen Grund sauer auf jemand zu sein. Falk und KH bemühen sich
sehr mir zu helfen und teils meine blöden Fragen zu beantworten und das
zum wiederholten mal. Deshalb steh ich auch zu dieser Aussage.
Danke
Achim
@achim (Gast)
>Ich will was lernen, das ist das wichtigste für mich.
Schön, aber dann musst du endlich mal aufhören, nach deiner "Methode"
des Rumstocherns vorzugehen und einfach mal auf die Lehrer hören! So wie
in der Grundschule! Der Lehrer gibt eine Aufgabe vor, die Schüler führen
diese aus. Und nicht irgend etwas anderes. Und du bist in der
Grundschule, was deine Programmierfähigkeiten angeht.
>Ich habe keinen Grund sauer auf jemand zu sein. Falk und KH bemühen sich>sehr mir zu helfen und teils meine blöden Fragen zu beantworten und das>zum wiederholten mal. Deshalb steh ich auch zu dieser Aussage.
Erspare uns diese immer gleich Lyrik, mach was man dir sagt!
Hausaufgabe: Fülle die Funktionen
int8_t PCA9536_Write(uint8_t i2c_address, uint8_t reg, uint_8
data)
{
}
int8_t PCA9536_Read(uint8_t i2c_address, uint8_t reg, uint_8*
data)
{
}
mit Inhalt und teste sie. Erkläre die Funktion.
DAS und nun DAS ist JETZT deine Aufgabe!
Falk Brunner schrieb:> Hausaufgabe: Fülle die Funktionen>> int8_t PCA9536_Write(uint8_t i2c_address, uint8_t reg, uint_8> data)> {>> }>> int8_t PCA9536_Read(uint8_t i2c_address, uint8_t reg, uint_8*> data)> {>> }>> mit Inhalt und teste sie. Erkläre die Funktion.>> DAS und nun DAS ist JETZT deine Aufgabe!
Die Lese Funktion hat ein Argument zu viel:
Gerhard O. schrieb:> Die Lese Funktion hat ein Argument zu viel:
Wenn Write einen Return Wert hat, der einen Fehler signalisieren kann,
dann ist es nur vernünftig, dasselbe auch mit der Read Funktion zu
machen.
Es ist also kein Argument zu viel.
und nein. Ich teile deine Einschätzung nicht, dass man auf
Fehlerbehandlung bei diesen Funktionen verzichten sollte. Ich lass mich
gerne darauf runterhandeln, dass sie fürs erste ignoriert wird. Aber auf
Dauer bliebt sie nicht aus. Auch nicht bei Achim. Dann muss er seine
Lernkurve halt mal etwas anziehen. Schliesslich ist er jetzt schon lang
genug dabei, dass ihm eigentlich einige grundlegende C-Dinge keine
Probleme mehr machen sollten. Vielleicht sollte er nicht alle paar
Wochen irgendwas neues versuchen, sondern erst mal die Dinge, die er
eigentlich schon beherrschen sollte (es aber nicht tut) soweit
trainieren, dass die im Schlaf sitzen?
Kaum zu glauben, dass Achim schon seit 2 Jahren an der Programmiererei
rumdoktert und nichts wirklich weiter bringt.
Karl Heinz schrieb:> Gerhard O. schrieb:>>> Die Lese Funktion hat ein Argument zu viel:>>> Wenn Write einen Return Wert hat, der einen Fehler signalisieren kann,> dann ist es nur vernünftig, dasselbe auch mit der Read Funktion zu> machen.> Es ist also kein Argument zu viel.
Sorry, ich sah den Zeiger "*data" nicht rechtzeitig der sich da etwas
"unterhändisch" eingeschlichen hatte;-). Jetzt verstehe ich: Der Return
Wert war von Falk immer noch nur für die Fehlerbehandlung reserviert.
>>> und nein. Ich teile deine Einschätzung nicht, dass man auf> Fehlerbehandlung bei diesen Funktionen verzichten sollte. Ich lass mich> gerne darauf runterhandeln, dass sie fürs erste ignoriert wird. Aber auf> Dauer bliebt sie nicht aus.
100% Zustimmung bezgl. Fehlerbehandlung. Ich dachte nur das wäre im
Augenblick noch verfrüht gewesen.
/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */
20
// noch in einen Funktion
21
i2c_start(0x82);/* 0x82 = Schreib Modus */
22
i2c_write(0x03);/* Index auf CONFIG REGISTER stellen */
23
i2c_write(0x00);/* Alle Port Pins auf OUTPUT MODUS stellen */
24
i2c_stop();
25
26
while(1)
27
{
28
29
PCA9536_Write(PCA_WRITE_ADR,CFG_REGISTER,0x00);
30
_delay_ms(500);
31
32
PCA9536_Write(PCA_WRITE_ADR,CFG_REGISTER,0x01);
33
_delay_ms(500);
34
35
PCA9536_Write(PCA_WRITE_ADR,CFG_REGISTER,0x02);
36
_delay_ms(500);
37
38
PCA9536_Write(PCA_WRITE_ADR,CFG_REGISTER,0x04);
39
_delay_ms(500);
40
41
PCA9536_Write(PCA_WRITE_ADR,CFG_REGISTER,0x08);
42
_delay_ms(500);
43
44
}
45
}
Konnte leider den Code nicht testen. Möglch das ich was vertauscht habe,
sorry.
Es müsste ein Lauflicht entstehen. Ein Teil (erster Aufruf muss ich noch
machen)
achim
das wird wohl eher wenig bringen, wenn du dauernd ins
Konfigurationsregister schreibst. Pins die ständig von Input auf Output
umgeschaltet werden und vice versa, machen eher wenig Sinn.
Und warum wird hier
1
intmain(void)
2
{
3
i2c_init();// Starte I2C Bus
4
/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */
5
// noch in einen Funktion
6
i2c_start(0x82);/* 0x82 = Schreib Modus */
7
i2c_write(0x03);/* Index auf CONFIG REGISTER stellen */
8
i2c_write(0x00);/* Alle Port Pins auf OUTPUT MODUS stellen */
9
i2c_stop();
nicht die Ausgabefunktion benutzt, die du so grossspurig angekündigt
hast.
Konsequent sein!
WEnn du eine Funktion hast, die die ein Kommando samt Wert an den
Baustein überträgt, dann wird die auch benutzt. Und zwar überall!
OK. Ist jetzt sicherlich Geschmackssache. Aber das Unwichtigste im Namen
CFG_REGISTER ist der Wortbestandteil 'REGISTER'. Denn das es sich da um
ein Register handelt ist sonnenklar. Nur das 'REGISTER' den weitaus
größten optischen Teil in CFG_REGISTER einnimmt und die eigentlich
wichtige Information ob es das OUT, das IN oder das CFG ist, dabei
optisch untergeht.
Ich hätt mir da andere Namen gesucht. Vielleicht
1
#define OUTPUT_REG 1
2
#define INPUT_REG 2
3
#define CONFIG_REG 3
hier ist die Funktion als der wichtigere Bestandteil im Wortteil recht
prominent vertreten. Während das '_REG' nur noch mehr so ein Anhängsel
ist, damit auch irgendwie das 'Register' im Namen vertreten ist.
Bei Benamungen immer die wichtige Information hervorheben. Die wichtige
INformation ist in diesem Fall, ob es das Output, das Input oder das
Konfigurations - Register ist. Das es sich um ein Register handelt, ist
hingegen nicht so wichtig. Denn das ist das Grundprinzip von I2C, dass
der Master den Slave über Register anspricht.
Im ersten Teil habe ich es richtig geschrieben und dann leider
übersehen.
Auch für den ersten Aufruf habe ich eine Funktion. Wollte es noch
schreiben.
PCA9536_Write(PCA_WRITE_ADR, CFG_REGISTER, 0x00);
Noch das CFG korrigieren, bzw Wert anpassen
Ausser einem Flüchtigskeitsfeheler und einer fehlenden Funktion - habe
Hoffnung.
Für den Rest muss ich weiterlesen.
Frage dazu:
Muss ich beim ersten Aufruf alle Pins auf Ausgang setzen
1
i2c_start(0x82);/* 0x82 = Schreib Modus */
2
i2c_write(0x03);/* Index auf CONFIG REGISTER stellen */
3
i2c_write(0x00);/* Alle Port Pins auf OUTPUT MODUS stellen */
4
i2c_stop();
oder sollte man gleich einen Pins als Eingang lassen?
achim
achim schrieb:> oder sollte man gleich einen Pins als Eingang lassen?
So wie du sie haben willst.
Es macht auch keinen Sinn 300 mal den Chip zu konfigurieren. Da kommt
man nur durcheinander. Wenn du einen oder mehrer Pins auf Input haben
willst, dann bestimm dir das entsprechende Konfigurationsbyte, so dass
sich genau diese Konfiguration ergibt, das setzt du und gut ists.
Habe den Code noch mal auf Fehler getestet. Waren noch ein paar Sachen
drin (Grossschreibung). Jetzt läuft er ohne Probleme. habe auch die
Namen von KH eingesetzt. Es entsteht dabei ein "laufendes Loch" über die
4 Pins.
Die Quarzfrequenz habe ich in einer anderen Datei angegeben.
1
//#define F_CPU 16000000UL
2
#include"main.h" // Angabe der Adresse und Frequenz
Achim Seeger schrieb:> Hallo Gerhard> dein Programm läuft. habe es gerade getestet. Dabei läuft wieder das> "Loch"> achim
Hallo Achim,
danke für die Info. Das freut mich.
Guten Abend,
Gerhard
@ Achim Seeger (achims)
>Habe noch die LED geändert. Jetzt läuft der Punkt
Das hätte man einfacher haben können, ohne es manuell umzurechnen.
Der unäre Operator ~ (bitweise invertieren) ist dein Freund.
PCA9536_Write(PCA_WRITE_ADR, OUTPUT_REG, ~0x01); // L1
_delay_ms(500);
PCA9536_Write(PCA_WRITE_ADR, OUTPUT_REG, ~0x02); // L2
_delay_ms(500);
PCA9536_Write(PCA_WRITE_ADR, OUTPUT_REG, ~0x04); // L3
_delay_ms(500);
PCA9536_Write(PCA_WRITE_ADR, OUTPUT_REG, ~0x08); // L4
_delay_ms(500);
Hallo Gerhard, Hallo Falk
Danke für eure Hinweise
Ich weiss das es viele Wege nach Rom gibt, bin aber doch sehr erstaunt,
was alles möglich ist. An solche Sachen habe ich noch gar nicht gedacht.
Lohnt sich auf jeden Fall es zu machen.
Dein Programm kann ich leider erst heute abend testen. Auf Arbeit kann
ich zwar alles lesen und schreiben, habe aber nicht meine Hardware zur
Verfügung. Dadurch ergeben sich auch Fehler, da ich nichts testen kann.
Da mach ich mal weiter mit dem lesen (PCA).
achim
Dann wollen wir mal anfangen.
Hardware die ich annehme:
- PCA 9536
- Pin 0 bis 2 als Ausgang - schalten LED ein/aus
- Pin 3 - Eingang - entweder +5V oder GND anliegend
Als erstes müssen wir die Sache erweitern:
1
#define PCA_WRITE_ADR 0x82
2
#define PCA_READ_ADR 0x83 // Erweitern um Leseadresse
Beim ersten Aufruf soll man den PCA auf OUTPUT stellen:
/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */
i2c_start(0x82); /* 0x82 = Schreib Modus */
i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */
i2c_write(0x00); /* Alle Port Pins auf OUTPUT MODUS stellen */
i2c_stop();
Damit stelle ich alle 4 Pins auf Ausgang. Brauche aber nur 3 Ausgänge
und 1 Eingang
/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */
i2c_start(0x82); /* 0x82 = Schreib Modus */
i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */
i2c_write(0x07); /* Alle Port Pins auf OUTPUT MODUS stellen */
i2c_stop();
Damit dürfte ich die Pins 0-2 auf Ausgang stellen und Pin 4 auf Eingang
lassen. Ist das nicht besser?
Das Stück stammt von Gerhard
I2C_write(register_index);// Setze lesezugriff Register Index
8
i2c_start(slave_address|0x01);// Starte Lesezugriff mit READ bit gesetzt
9
d=i2c_readNak();// Schreib Leseergebnis in d
10
I2C_stop();
11
returnd;
12
}
Nach Tom soll es so aussehen:
1. I2C Start
2. schreibe Adresse(W)
3. schreibe Register
4. I2CStart
5. schreibe Adresse(R)
4. lese Daten
5. I2C Stop
Dabei geht es um die Schreib und Leseadresse.
Ich übergeb nur eine Adresse. Aber welche, die 82 oder 83? Welches
Register nehme ich? Das in_reg oder out_reg?
Wenn beim lesen nur 2 Werte übergeben werden, welches sind es?
Wenn ich beim ersten Aufruf P0 bis P2 als Ausgang und P3 als Eingang
nutze, welche Werte kommen beim Auslesen?
Habe die Angegebenen Werte nicht getestet, sorry wenn sie nicht stimmen.
achim
@ achim (Gast)
>Als erstes müssen wir die Sache erweitern:>#define PCA_WRITE_ADR 0x82>#define PCA_READ_ADR 0x83 // Erweitern um Leseadresse
FALSCH! Die brauchst du nicht! Denn sie ist IMMER WRITE_ADR +1.
Das bringt nur Verwirrung und Fehlermöglichkeiten!
>int8_t PCA9536_Read ( uint8_t slave_adresse, uint8_t register_index)
Warum hast du EIGENMÄCHTIG den Funktionskopf geändert? Das gehört sich
für Grundschüler schlicht nicht!
> {> int8_t d;> i2c_start (slave_adresse);> i2c_write (register_index);> i2c_start (slave_adresse|0x08);> d=i2c_readNak();> i2c_stop;> return> }
Und was machst du mist deinem Leseergebnis? In den Müll werfen? Im WOM
speichern?
Mann O Mann!
>Der Aufruf erfolgt dann mit:>PCA9536_READ(PCA_WRITE,OUTPUT_REG);
Hör auf mit solchen schnell zusammgezimmerten Mist, den nie ein Compiler
gesehen hat! Lass den Käse, fern deines Bastelkellers. Ich glaub du hast
tagsüber besseres zu tun!
>Beim ersten Aufruf soll man den PCA auf OUTPUT stellen:
Nein, das muss man nicht.
>/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */> i2c_start(0x82); /* 0x82 = Schreib Modus */> i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */> i2c_write(0x00); /* Alle Port Pins auf OUTPUT MODUS stellen */> i2c_stop();
Warum kapierst du es denn eigentlich nicht, dass du verdammt nochmal
deine selbstgebaute Schreibfunktion nutzen sollst und die direkten I2C
Zugriffe sein lassen sollst?
>Damit stelle ich alle 4 Pins auf Ausgang. Brauche aber nur 3 Ausgänge>und 1 Eingang>/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */> i2c_start(0x82); /* 0x82 = Schreib Modus */> i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */> i2c_write(0x07); /* Alle Port Pins auf OUTPUT MODUS stellen */> i2c_stop();>Damit dürfte ich die Pins 0-2 auf Ausgang stellen und Pin 4 auf Eingang>lassen. Ist das nicht besser?
Hier wäre eine biinäre Schreibweise besser lesbar. 0b1000. Das ist aber
0x08.
>Das Stück stammt von Gerhard
Und ist auch richtig. Warum nutzt du es dann nicht?
>Nach Tom soll es so aussehen:
Die ist identisch!
>Ich übergeb nur eine Adresse. Aber welche, die 82 oder 83?
Wenn man schreibt logischerweise die Schreibadresse.
Wenn man liest logischerweise die Leseadresse.
> Welches>Register nehme ich? Das in_reg oder out_reg?
OMG.
Lass dieses Rumgemurks und setzt dich in Ruhe an deine Prgrammierung,
nicht zwischen Mittag un 12:00.
Falk Brunner schrieb:>>Ich übergeb nur eine Adresse. Aber welche, die 82 oder 83?>> Wenn man schreibt logischerweise die Schreibadresse.> Wenn man liest logischerweise die Leseadresse.
Vorsicht. Ich denke, er meinte seine Lesefunktion.
Der übergibt man dieselbe Adresse, mit der man auch die Schfreibfunktion
aufgrufen hat.
Ausserhalb der beiden Funktionen hat der Baustein immer dieselbe
Adresse. Dass beim eigentlichen Lesezugriff dann eine andere Adresse zu
benutzen ist, das weiss die Lesefunktion.
> Lass dieses Rumgemurks
:-)
Alleine diese letzte Frage nach der Adresse zeigt, dass er nichts, kein
Wort, verstanden hat.
Sorry, wenn was falsch angekommen.
Hatte den Teil von Gerhard gelesen ohne die Antwort von Falk
mitzubelommen.
Karl Heinz schrieb:> Ausserhalb der beiden Funktionen hat der Baustein immer dieselbe> Adresse. Dass beim eigentlichen Lesezugriff dann eine andere Adresse zu> benutzen ist, das weiss die Lesefunktion.
Mit dieser Angabe sieht es weitaus besser aus.
Karl Heinz schrieb:>> int8_t PCA9536_Read ( uint8_t slave_adresse, uint8_t register_index)>> {>> int8_t d;>> i2c_start (slave_adresse);>> i2c_write (register_index);>> i2c_start (slave_adresse|0x08);>> Warum hier |0x08 ?
mit der 0x08 wollte ich nur den Pin 3 auslesen. Da die 3 anderen auf
Ausgang stehen bleiben sollen. Bei Gerhard steht dort 0x01
Falk Brunner schrieb:>>/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */>> i2c_start(0x82); /* 0x82 = Schreib Modus */>> i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */>> i2c_write(0x00); /* Alle Port Pins auf OUTPUT MODUS stellen */>> i2c_stop();>> Warum kapierst du es denn eigentlich nicht, dass du verdammt nochmal> deine selbstgebaute Schreibfunktion nutzen sollst und die direkten I2C> Zugriffe sein lassen sollst?
Damit wollte ich nur die Werte zeigen. Die Funktion zum ersten Aufruf
nutze ich so wie geschrieben.
Falk Brunner schrieb:>> {>> int8_t d;>> i2c_start (slave_adresse);>> i2c_write (register_index);>> i2c_start (slave_adresse|0x08);>> d=i2c_readNak();>> i2c_stop;>> return>> }>> Und was machst du mist deinem Leseergebnis? In den Müll werfen? Im WOM> speichern?
Das Leseergebnnis speichere ich in d
Falk Brunner schrieb:>>int8_t PCA9536_Read ( uint8_t slave_adresse, uint8_t register_index)>> Warum hast du EIGENMÄCHTIG den Funktionskopf geändert? Das gehört sich> für Grundschüler schlicht nicht!
Das ist die Stelle, wo ich die Antwort übersehen habe
Gerhard O. schrieb:> // Lesefunktion:>> int8_t PCA9536_Read(uint8_t slave_address, uint8_t register_index)> {> int8_t d;>> I2C_start(slave_address); // Addressiere Device> I2C_write(register_index); // Setze lesezugriff Register Index> i2c_start(slave_address | 0x01 ); // Starte Lesezugriff mit READ> bit gesetzt> d=i2c_readNak(); // Schreib Leseergebnis in d> I2C_stop();>> return d;> }
Ich geh von diesem Code aus. das ist die Funktion die ich nutzen will.
Es steht alles drin, ist mir klar.
achim (beim lesen - alles noch mal)
Achim Seeger schrieb:> Sorry, wenn was falsch angekommen.> Hatte den Teil von Gerhard gelesen ohne die Antwort von Falk> mitzubelommen.>> Karl Heinz schrieb:>> Ausserhalb der beiden Funktionen hat der Baustein immer dieselbe>> Adresse. Dass beim eigentlichen Lesezugriff dann eine andere Adresse zu>> benutzen ist, das weiss die Lesefunktion.>> Mit dieser Angabe sieht es weitaus besser aus.>> Karl Heinz schrieb:>>> int8_t PCA9536_Read ( uint8_t slave_adresse, uint8_t register_index)>>> {>>> int8_t d;>>> i2c_start (slave_adresse);>>> i2c_write (register_index);>>> i2c_start (slave_adresse|0x08);>>>> Warum hier |0x08 ?>> mit der 0x08 wollte ich nur den Pin 3 auslesen. Da die 3 anderen auf> Ausgang stehen bleiben sollen.
Oh Mann.
Einmal probier ich das noch.
Die Sequenz zum Lesen eines Wertes aus einem bestimmten Register lautet:
1
Start mit der Angabe 'zum Schreiben'
2
als Commando wird das Register übergeben, aus dem zu lesen ist
3
4
Neustart mit der Angabe 'zum Lesen'
5
Auslesen des Wertes
6
7
Stop
Das steht genau so im Datenblatt und ist mitlerweile in diesem Thread
mindestens 300 tausend mal erwähnt worden! Ich träume schon davon, dass
man bei diesem Baustein zum Auslesen aus einem register erst mal mittels
Write die Registernummer übergibt und dann auf Lesen umschaltet! Dabei
interessiert mich dieser Baustein überhaupt nicht!
Und jetzt lies den Code von Gerhard nochmal. Ich formatiere den auch
noch ein bischen um
// **** I2C starten, und zwar zum Schreiben starten!
7
// *******************
8
I2C_start(slave_address);// Addressiere Device
9
10
// **** nachdem der Baustein jetzt weiss, dass wir was schreiben wollen
11
// **** erwartet er ein 'Kommando', die Registernummer
12
I2C_write(register_index);// Setze lesezugriff Register Index
13
14
// *******************
15
// **** I2C starten, und zwar zum Lesen starten!
16
// *******************
17
i2c_start(slave_address|0x01);// Starte Lesezugriff mit READ bit gesetzt
18
19
// **** nachdem der Baustein vom vorhergehenden weiss, welches Register
20
// **** gelesen werden soll, versuchen wir das mal:
21
// **** lieber Baustein, her mit dem Byte!
22
d=i2c_readNak();// Schreib Leseergebnis in d
23
24
// ******************
25
// ***** gut so, kannst dich wieder schlafen legen
26
// ******************
27
I2C_stop();
28
returnd;
29
}
Lies den Kommantar, behalte im Hinterkopf, dass es zuerst 'I2C auf
schreiben' einstellen heissen muss, damit man die Registeradresse
übergeben kann und dann 'I2C auf Lesen einstellen' heissen muss, damit
man den Wert dann auch wirklich lesen kann.
Behalte weiters im Hinterkopf, dass beim Konfigurieren auf Sschreiben,
das niederwertigeste Bit auf 0 sein muss (das ist bei I2C IMMER so) und
beim Konfigurieren auf Schreiben das niederwertigste Bit (das ist das
mit der Nummer 0, ganz rechts in einer üblichen Bitschreibweise) auf 1
sein muss (auch das ist bei I2C IMMER so!).
Warum steht da also | 0x01 ?
Karl Heinz schrieb:> Warum steht da also | 0x01 ?
Hat das irgendwas damit zu tun, welches Bit dich interessiert? Nein,
nicht die Bohne.
Welches Bit dich interessiert, das holst du dir ausserhalb dieser
Funktion aus dem Ergebnis der Funktion raus
1
if(PCA9536_Read(PCA_ADRESSE,INPUT_REG)&0x08)
das unterscheidet sich in nichts davon, wie man zb von einem AVR Port
das eine Bit rausholt, an dem zb ein Taster hängt
1
if(PINB&0x08)
nur das wir das normalerweise nicht so schreiben, sondern so
1
if(PINB&(1<<PB3))
aber das ist nur eine andere Schreibweise, wie man die 0x08 anders
ausdrücken kann. Abgesehen von der Schreibweise ist es exakt und 100%
genau das gleiche Prinzip. Da gibt es einen 'Lieferanten', der 1 Byte
liefert. In dem einen Fall ist es das
1
PINB
welches das Byte von den AVR-Portbits besorgt. Im anderen Fall ist es
der PC_dingsbums Baustein, der vom AVR mittels I2C nach dem Wert seiner
Pins befragt wird
1
PCA9536_Read(...)
Aber egal, wo dieser Wert herkommt, das interessierende Bit, mit der
Bitnummer 3, wird mittels Bitoperationen 'freigestellt' ....
Achim Seeger schrieb:>>>/* PCA9536 auf OUTPUT MODUS umstellen - Nur einmal notwendig! */>>> i2c_start(0x82); /* 0x82 = Schreib Modus */>>> i2c_write(0x03); /* Index auf CONFIG REGISTER stellen */>>> i2c_write(0x00); /* Alle Port Pins auf OUTPUT MODUS stellen */>>> i2c_stop();>>>> Warum kapierst du es denn eigentlich nicht, dass du verdammt nochmal>> deine selbstgebaute Schreibfunktion nutzen sollst und die direkten I2C>> Zugriffe sein lassen sollst?>> Damit wollte ich nur die Werte zeigen. Die Funktion zum ersten Aufruf> nutze ich so wie geschrieben.
Und warum kannst du das dann nicht auch hier im Forum als
1
PCA9536_Write(....,OUTPUT_REG,0x00);
schreiben? Zu simpel? Zu einfach?
>>> {>>> int8_t d;>>> i2c_start (slave_adresse);>>> i2c_write (register_index);>>> i2c_start (slave_adresse|0x08);>>> d=i2c_readNak();>>> i2c_stop;>>> return>>> }>>>> Und was machst du mist deinem Leseergebnis? In den Müll werfen? Im WOM>> speichern?>> Das Leseergebnnis speichere ich in d
Schön.
d ist aber eine lokale Variable. Nachdem die Funktion beendet wird, löst
sich die aber in Luft auf.
> Ich geh von diesem Code aus. das ist die Funktion die ich nutzen will.> Es steht alles drin, ist mir klar.
Das eigentlich Traurige ist, dass man dich mit der groben Kelle auf
derartige Dinge hinweisen muss. Und das nach 2 Jahren AVR Programmierung
und mindestens 3 Monaten Beschäftigung mit I2C. Auf 2 Funktionen, die
eine ist 4 Zeilen lang, die andere 6 (oder so). Trotzdem schaffst du es
nicht, dir aus den 4 Zeilen bzw. den 6 Zeilen die wesentlichen Dinge
herauszulesen. Noch nicht mal, wenn man dich mit der groben Kelle darauf
hinweist und dir alles x-mal haarklein darlegt. Wenn du jetzt Alzheimer
hättest, dann wäre das ja noch verständlich. Aber so ....
@ Achim Seeger (achims)
>>> int8_t PCA9536_Read ( uint8_t slave_adresse, uint8_t register_index)>>> {>>> int8_t d;>>> i2c_start (slave_adresse);>>> i2c_write (register_index);>>> i2c_start (slave_adresse|0x08);>>>> Warum hier |0x08 ?>mit der 0x08 wollte ich nur den Pin 3 auslesen.
Und wie kommst du darauf, dass du dazu die I2C Adresse vermurksen
sollst?
> Da die 3 anderen auf>Ausgang stehen bleiben sollen. Bei Gerhard steht dort 0x01
Aha. Das wird seinen Sinn haben. Nämlich um aus der Adresse 0x82 per
ODER-verknüpfung die 0x83 zu machen. Und siehe da, es ist die I2C
Leseadresse des ICs!
>> Warum kapierst du es denn eigentlich nicht, dass du verdammt nochmal>> deine selbstgebaute Schreibfunktion nutzen sollst und die direkten I2C>> Zugriffe sein lassen sollst?>Damit wollte ich nur die Werte zeigen. Die Funktion zum ersten Aufruf>nutze ich so wie geschrieben.
Welche Werte denn? Wen interessiert das? Warum tust du nicht, was man
dir wohlwollend sagt?
>>> {>>> int8_t d;>>> i2c_start (slave_adresse);>>> i2c_write (register_index);>>> i2c_start (slave_adresse|0x08);>>> d=i2c_readNak();>>> i2c_stop;>>> return>>> }>>>> Und was machst du mist deinem Leseergebnis? In den Müll werfen? Im WOM>> speichern?>Das Leseergebnnis speichere ich in d
Welche nach Verlassen der Funktion wegggeworfen wird. Stichwort: Lokale
Variable. Archim, du hast nicht die leiseste Ahnung von Programmieren,
geschweige denn von C und Funktionen. Und das wird sich auch in den
nächsten 10 Jahren nicht nennenswert ändern.
Nur der Vollständigkeit halber weil Falk die Lesefunktion mit Zeiger-
Uebergabe vorgeschlagen hat:
Bitte nicht ablenken lassen - Ist nur als Beispiel gedacht.
1
/* Das folgende Programm demonstriert die Wertuebergabe mit einer
2
Zeigervariable wie von Falk vorgeschlagen - Nicht getestet
3
4
*/
5
6
//#define F_CPU 16000000UL
7
#include"main.h" // Angabe der Adresse und Frequenz
Hallo Gerhard
Das letzte Prg läuft leider nicht. Einige Fehler habe ich gefunden.
Meistens Gross geschrieben oder einen Buchstaben/Zeichen zu viel. Leider
komme ich mit diesen Fehlern nicht klar. Vielleicht könntest du es dir
noch mal anschauen.
Warning 4 previous definition of 'PCA9536_Read' was here
Warning 2 previous declaration of 'PCA9536_Read' was here
Warning 5 passing argument 3 of 'PCA9536_Read' makes pointer from
integer without a cast [enabled by default]
Warning 8 incompatible implicit declaration of built-in function
'printf' [enabled by default]
Warning 7 implicit declaration of function 'printf'
[-Wimplicit-function-declaration]
Warning 6 expected 'uint8_t *' but argument is of type 'int8_t'
Error 1 conflicting types for 'PCA9536_Read'
Error 3 conflicting types for 'PCA9536_Read'
achim
@ Achim Seeger (achims)
>Das letzte Prg läuft leider nicht. Einige Fehler habe ich gefunden.
Welche denn?
>Meistens Gross geschrieben oder einen Buchstaben/Zeichen zu viel. Leider>komme ich mit diesen Fehlern nicht klar. Vielleicht könntest du es dir>noch mal anschauen.
Warum tust DU das nicht? Der letzte BEitrag von gerhard war KEIN
fehlerfreies, getestetes Programm sondern eine Skizze! Denn dort sind
zwei Funktionen mit GLEICHEM Namen aber VERSCHIEDENEN Parametern drin!
Das geht nicht durch den Compiler! Logisch.
int8_t PCA9536_Read(uint8_t slave_address, uint8_t register_index);
int8_t PCA9536_Read(uint8_t i2c_address, uint8_t reg, uint_8 *pdata);
Also muss man sich entscheiden, welche Version man will und die andere
löschen!
Achim Seeger schrieb:> Hallo Gerhard> Das letzte Prg läuft leider nicht. Einige Fehler habe ich gefunden.> Meistens Gross geschrieben oder einen Buchstaben/Zeichen zu viel. Leider> komme ich mit diesen Fehlern nicht klar. Vielleicht könntest du es dir> noch mal anschauen.>> Warning 4 previous definition of 'PCA9536_Read' was here> Warning 2 previous declaration of 'PCA9536_Read' was here
Und, hast du dir die Stellen mal angesehen, oder hast du dir gleich
gedacht: Oooch, da gibt es eine Fehlermeldung, ab ins Forum damit
Was fällt hier auf?
Rischtisch.
Da gibt es 2 Zeilen mit jeweils einem Protoypen für PCA9536_Read.
Beide unterscheiden sich aber. Nur eine kann richtig sein.
Eine ist also überflüssig und Gerhard hat sie nur vergessen
rauszulöschen.
> Warning 8 incompatible implicit declaration of built-in function> 'printf' [enabled by default]
printf kannst du sowieso nicht benutzen.
Benutze die Ausgabefunktkion deiner Wahl. Gerhard kann nicht wissen, ob
du eine UART oder ein LCD hast.
Ich hab dir das vor Jahren schon mal gesagt, als du in kürzester Zeit
ein Beispiel nach dem anderen zu jeweils einem anderen Thema rausgehauen
hast: Das hat keinen Sinn. Du musst die Grundlagen lernen. Deine
Programmiersprache ist dein Handwerkszeug, das musst du beherrschen.
Jetzt tritt genau das ein. Du kannst von allem ein bischen was aber
nichts vernünftig. Am allerwenigsten deine Programmiersprache.
mindestens 2 Jahre Zeit vergeudet.
int8_t*pdata;// Erzeuge eine Zeiger Variable die auf die Speicher Adresse von PCA9536_data
4
// hinzeigen wird.
5
// Zu diesem Zeitpunkt ist der Wert noch nicht definiert.
6
int8_tPCA9536_data;// Deklariere den eigentlichen Datenspeicher
7
pdata=&PCA9536_data;// Uebergebe der Zeigervariable pdata die Speicher Adresse von PCA9536_data
er muss lernen, dass ein Pointer in einer Funktionsargumentliste nicht
zwangsläufig auch bedeutet, dass der Aufrufer eine Pointer Variable
braucht. Das verkompliziert nur alles.
Wenn eine FUnktion ein Pointer Argument nimmt
1
voidfoo(int*pPtr)
2
...
dann gibt es 2 Möglichkeiten.
Entweder übernimmt die Funktion eine größere Menge Daten, zb in einem
Array und der Pointer wurde deshalb benutzt, weil man die größere Menge
Daten nicht zur Übergabe an die Funktion kopieren möchte oder kann
Oder die Funktion will einen Pointer haben, weil man als Aufrufer die
Information bereitstellen muss, wo die Funktion ihr Ergebnis
hineinstellen soll.
Du Unterscheidung, welcher Fall vorliegt ist eigentlich immer recht
leicht zu treffen und eindeutig. Das hilft aber nichts. Da muss er
durch. Das sind Basic-Skills die er sich aneignen muss.
Eine Funktionsschnittstelle, bei der völlig klar ist, dass die Funktion
über den Pointer einen Wert in eine Speicherbereich des Aufrufers
ablegen will
1
voidfoo(int*pResult)
2
{
3
*pResult=8;
4
}
benutzt man am besten so, dass man auch beim Aufrufer ganz klar sieht,
dass man durch Übergabe der Adresse einer Variablen, diese der Funktion
zur Veränderung bereitstellt
1
intmain()
2
{
3
intjkl;
4
5
foo(&jkl);
6
}
durch Einführung einer zusätlichen Pointervariablen verschleierst du
diese simple Tatsache nur
1
intmain()
2
{
3
intjkl;
4
int*ptrToJkl;
5
6
ptrToJkl=&jkl;
7
8
foo(ptrToJkl)
9
}
sieh dir Achim an. Der kann Programmfluss noch nicht mal über 4 Zeilen
hinweg korrekt analysieren. Wenn du dem dann auch noch Pointer Variablen
unterjubelst, in denen sich die Adresse der zu ändernden Variable
wiederfindet, dann verwirrt ihn das mehr, als es ihm nützt. So könnte
man sagen, dass er durch den Adress-Of Operator in
1
intmain()
2
{
3
intjkl;
4
5
foo(&jkl);
6
}
wenigstend direkt an der Aufrufstelle sieht, dass die Funktion foo
irgendwas mit der Variablen jkl machen wird. Denn der Aufruf sieht nicht
so aus, wie die anderen.
Es hilft nichts. Da muss er durch! Nach 3 Jahren C programmieren sollte
er eigentlich schon viel, viel weiter sein. Da sollte er eigentlich hier
zu den Experten gehören, die anderer Leute Code korrigieren.
@ Karl Heinz (kbuchegg) (Moderator)
>Es hilft nichts. Da muss er durch! Nach 3 Jahren C programmieren sollte>er eigentlich schon viel, viel weiter sein. Da sollte er eigentlich hier>zu den Experten gehören, die anderer Leute Code korrigieren.
8-)
Deinen Indealismus möchte ich mal haben! Der Achim macht das nur nebenei
als Hobby. Klar sollte man auch da nach 3 Jahren DEUTLICH weiter sein,
aber dazu haben wir uns schon genug geäußert. Ich weiß auch nicht, was
ihn dabei immer noch antreibt es zu tun, obwohl er kein Land sieht. Ich
glaube das hier trifft es verdammt gut!
Beitrag "Re: Denkfehler mit PCA9536 (Problem)"
Hallo Falk
habe das Prg für Gerhard getestet. Einige Fehler wurden angezeigt, die
ich korrigiert habe. Diese Fehler habe ich erkannt. Einige Sachen
versteh ich (noch) nicht. Lasse mir etwas Zeit zum lesen und verstehn,
soweit möglich. Werde aber erst deine anderen Aufgaben erledigen und so
lange weiter machen bis das lesen klappt und diesen teil verstanden habe
und anwenden kann. Das sind schon fast genügend Aufgaben. Eine
zusätzlich Herausvorderung ist nicht schlecht, aber nicht alles auf
einmal.
KH und du hast mir genügend neues gebracht.
achim
Noch was zu deinem letzten Teil. Habe mich nicht 3 Jahre, jeden Tag
damit beschäftigt. Aus persönlichen Grund war auch eine längere Pause
dabei. Dann habe ich was mit dem AT1284p gemacht.
Ja, ich betreibe es als Hobby und habe bei 0 angefangen, so richtig bei
0. Musste alles lernen und vieles erkämpfen um es zu verstehen. Ein Buch
hilft bis zu einer bestimmten Stelle weiter, dann kommen Programme von
andern und die Hardware dazu. Nicht zu vergessen, immer neue Fragen
stellen und auf Hilfe hoffen. Musste auch die Erfahrung machen, was
free.. dabei bedeutet. Einge Hersteller bringen was auf den Markt und
sagen einfach dazu, friss oder stirb. Hab mich für "friss.."
entschieden.
Das jetzige Ziel heist, ein lauffähiges Programm zu schreiben (mit
Funktionen)
achim
Achim Seeger schrieb:> Ja, ich betreibe es als Hobby und habe bei 0 angefangen, so richtig bei> 0. Musste alles lernen und vieles erkämpfen um es zu verstehen. Ein Buch> hilft bis zu einer bestimmten Stelle weiter
Nicht bis zu einer bestimmten Stelle.
EIn Buch hilft dir komplett durch.
Allerdingss eher nicht auf einem µC, denn da gibt es einige Sonderdinge.
Aber auf dem PC.
C lernt man am besten mit einem Buch und einer freien
Entwicklungsumgebung auf dem PC!
Dort geht es richtig fix, dass man die grundlegenden Sprachelemente alle
intus hat. Auch Übungsbeispiele schreiben gestaltet sich auf dem PC viel
einfacher. Warum? Weil man da eine Konsole zur Verfügung hat; ein printf
einfach aus dem Stand heraus funktioniert. Und das ist schon mal die
halbe Miete.
Klar bleibt da dann noch vieles zu lernen: grundlegende
Sprachkonstrukte, Arrays, Strings, Funktionen, Funktionsargumente und
das weite, weite Feld von dynamische Allokierung und exzessiver Arbeit
mit Pointer. Aber so ungefähr nach dem ersten Drittel des Buches,
manchmal auch erst nach der Hälfte (je nach Buch) hat man das Rüstzeug,
um in die Spezialitäten der µC-Programmierung einzutauchen. Den Level
hat man aber auf dem PC in ein paar Wochen bis Monaten erreicht. Unter
anderem auch deshalb, weil die Fehlersuche sich um Größenordnungen
einfacher gestaltet. Und weil man viel, viel mehr einfache Testprogramme
schreibt. Übung macht den Meister.
Hier hängst du seit Wochen an einer simplen Ausgabe. Eine Ausgabe, die
du zwar auf einem PC so nicht so einfach machen kannst. Nur hättest du
in der Zeit auf dem PC schon längst ein paar 100 Zeilen Code für 10
andere kleinere Testprogramm geschrieben gehabt. Du hättest in derselben
Zeit massenhaft Übung in der C-Programmierung bekommen und müsstest
nicht einen 2 Frontenkrieg - Ausgabebaustein / C-Schwächen - führen.
@ Achim Seeger (achims)
>free.. dabei bedeutet. Einge Hersteller bringen was auf den Markt und>sagen einfach dazu, friss oder stirb. Hab mich für "friss..">entschieden.
Bla. Die Hersteller haben als Zielgruppe Fachleute, keine Bastler. Und
erst recht keine Bastler bei nahe 0.
>Das jetzige Ziel heist, ein lauffähiges Programm zu schreiben (mit>Funktionen)
Das wirst du nicht wirklich erreichen, weil du seit Anfang an nur
runmurkst und wild was zusammenkopierst. Du hast praktische keine
soliden Grundlagen drauf, das geht bei EINFACHSTEN Dingen wie Funktionen
und Parametern los. Das wird NIE was. Tut mir leid, das muss ich einfach
so hart sagen.
Mach es wie die meisten, nim ein C-Grundlagenbuch. Lies es OHNE Seiten
zu überspringen! Arbeite ALLE Beispiele durch! So lange, bis du die
einzelnen Kapitel WIRKLICH verstanden hast und WIRKLICH selber, OHNE
Hilfe ähnliche Sachen programmieren kannst.
Aber ich glaube nicht, dass du das schaffst, dazu fehlt dir schlicht das
Talent und die Lernfähigkeit. Das sage ich nicht, um dich runter zu
machen, sondern aus objektiver Betrachtung. Tu dir selber einen Gefallen
und such dir ein Hobby, das deinen Talenten und Fähigkeiten entspricht.
Das ist keine Schande, sondern normal. Ich kann auch nicht Klavier
spielen und Schlittschuh laufen und bei Quantenmechanik kann ich auch
nicht mitreden. Nicht mal bei C++!
Falk Brunner schrieb:> Mach es wie die meisten, nim ein C-Grundlagenbuch. Lies es OHNE Seiten> zu überspringen! Arbeite ALLE Beispiele durch! So lange, bis du die> einzelnen Kapitel WIRKLICH verstanden hast und WIRKLICH selber, OHNE> Hilfe ähnliche Sachen programmieren kannst.
Und ganz wichtig.
Nicht bei den Beispielen im Buch stehen bleiben!
Sich selber Beispiele ausdenken. Gerade mit Arrays gibt es viele, viele
einfache Beispiele, die genauso Spass machen und interessante Ergebnisse
bringen.
Das schlimmste was man machen kann, das ist die Beispiele vom Buch von
der beigelegten CD in die Entwicklungsumgebung kopieren, compilieren
lassen, laufen lassen und sagen 'Super, hab ich verstande'. Bei so etwas
hat man genau gar nichts verstanden. Und ja, man muss auf die Schnauze
fallen. Man muss die Fehlermeldungen vom Compiler sehen. Man muss
typische Fehler machen und die typischen Fehlermeldungen typischen
Fehlerszenarien zurodnen können. Das erfordert, dass man Fehler macht.
Das erfordert, dass man sich auch mal verläuft.
Lesen alleine reicht nicht! Du musst programmieren! Du musst aktiv sein
und schnelles Feedback haben. All das hast du aber auf deinem Niveau vom
µC nicht. Denn das dauert viel zu lange, wenn du einen ganzen Monat nur
damit verbringst, ein paar popelige LED an einem I2C Baustein gezielt
zum Leuchten zu kriegen. In demselben Monat hättest du auf dem PC eine
halbe Adressverwaltung inklusive Drucken geschrieben und dabei das Thema
'Funktionen' mehr als intus gekriegt. Inklusive der Tatsache, dass dich
diese Fehlermeldungen nur mehr ein müdes Lächeln gekostet hätten. Denn
die Meldungen hättest du in diesem Monat mindestens zig mal gesehen und
gelernt was sie bedeuten.
Und leider muss ich Falk recht geben, wenn er sagt
> Du hast praktische keine soliden Grundlagen drauf, das geht> bei EINFACHSTEN Dingen wie Funktionen und Parametern los.
wobei das schon geschmeichelt ist. Denn wie sich herausstellt, geht es
bei noch einfacheren Dingen los. Das kleine Einmaleins der µC
Programmierung sind die Bitoperationen. Wie werden sie benutzt, was
bedeuten sie, wie erreicht man Dinge. Eben die klassischen Dinge, die
man mit ein paar LED an einem oder 2 Ports bis zur Vergasung übt. Von
dort bis zu Funktionen ist es noch ein weiter Weg, aber wie sich gezeigt
hat, ist es auch mit Bitoperationen und dem erkennen der prinzipiellen
Systematik nicht weit her. Verständnis für Binärzahlen, Bits, .... ich
hatte stellenweise in diesem Thread schon das Gefühl, das sind Bücher
mit 7 Siegeln.
@ Karl Heinz (kbuchegg) (Moderator)
>Sich selber Beispiele ausdenken. Gerade mit Arrays gibt es viele, viele>einfache Beispiele, die genauso Spass machen und interessante Ergebnisse>bringen.
ja, aber ein Heft mit Übungsaufgaben ist besser. Das gibt es an jeder
Uni und jeder Schule, die Programmieren lehrt. Sowas braucht man.
>Das schlimmste was man machen kann, das ist die Beispiele vom Buch von>der beigelegten CD in die Entwicklungsumgebung kopieren, compilieren>lassen, laufen lassen und sagen 'Super, hab ich verstande'. Bei so etwas>hat man genau gar nichts verstanden.
Richtig. Nur selber tippen macht geistig fett! Man darf nur die
Aufgabenstellung haben, den Rest muss man SELBER TIPPEN und debuggen!
Und man kann diesen Lernprozess nicht endlos zerhacken! Man muss eine
gewisse Zeit AM STÜCK in EIN Thema investieren, um es zu verstehen. 10x
1/2 Stunde an einem Thema arbeiten ist deutlich SCHLECHTER als 1x 3
Stunden!
> Und ja, man muss auf die Schnauze>fallen. Man muss die Fehlermeldungen vom Compiler sehen. Man muss>typische Fehler machen und die typischen Fehlermeldungen typischen>Fehlerszenarien zurodnen können. Das erfordert, dass man Fehler macht.>Das erfordert, dass man sich auch mal verläuft.>Lesen alleine reicht nicht!
GENAU!
>Du musst programmieren! Du musst aktiv sein>und schnelles Feedback haben. All das hast du aber auf deinem Niveau vom>µC nicht. Denn das dauert viel zu lange, wenn du einen ganzen Monat nur>damit verbringst, ein paar popelige LED an einem I2C Baustein gezielt>zum Leuchten zu kriegen. In demselben Monat hättest du auf dem PC eine>halbe Adressverwaltung inklusive Drucken geschrieben und dabei das Thema>'Funktionen' mehr als intus gekriegt.
So siehts aus.
Wer hat ein Heftchen mit Übungsaufgaben? Meins aus der Studienzeit ist
längst verschwunden, die Aufgaben waren aber gut und auch nicht zu
schwer. Im C-Klassiker "Programmieren in C" und die diversen Kopien
haben nur wenig Übungsaufgaben.
Karl Heinz schrieb:> Gerhard, das ist keine gute Idee
Hallo Karl Heinz,
Danke für Deine Erklärungen bzgl. meines Beitrags.
Ich hatte wegen dem letzten Beitrag sowieso schon ein schlechtes
Gewissen und den Moderator gestern noch gebeten meinen Beitrag wieder zu
löschen. Leider war es dafür zu spät. Die erwähnten Fehler von Achim,
habe ich beim Nachlesen auch bemerkt. Da war es dann leider schon zum
Berichtigen zu spät.
Ich kann leider nicht direkt die Demoprogramme testen weil ich nur mit
CodevisionAVR arbeite. Gcc-AVR habe ich nirgendwo installiert. Habe
keine Ahnung wie man GCC-AVR mit den üblichen Ausgaben auf den Uart
zugreift. Das heisst, ich müsste das mal recherchieren:-)
Ich fing auch erst um 2000 herum C zu erlernen. Das war sowieso lustig.
Damals entwickelte ich in der Firma PIC Sachen und unter anderem eine
kleine Steuerplatine zum Schalten von 20 Netzsteckdosen. In meiner
damaligen (Programmier) Unerfahrenkeit dachte ich nicht in parallel mit
der Programentwicklung und wählte die 20 Ausgabepins für ein bequemes
PCB Layout. Dadurch mußte mein (armer) Kollege der das Programm für
meine Bord schreiben mußte, komplizierte Pin lookuptables verwenden um
die gewünschte Bitfolge zu erhalten. Durch diesen Fauxpas meinerseits
packte mich das Interesse selber embedded Programmieren in C zu
erlernen. So suchte ich die alte Prototype Bord und fing an mit dem
Programm meines Kollegen Zu experimentieren, Änderungen zu machen und
nach und nach alle Fehler zu erkennen und zu beheben. Mit einem guten
Buch bewaffnet lernte ich so mit C umzugehen. Da ich immer schon sehr
gut Hardwarefehler suchen konnte macht mir die Programm Fehlersuche auch
keine großen Schwierigkeiten mehr. Für mich war dieser Weg gangbar. Ich
masse mir nicht an ein guter Programmierer zu sein. Gewisse Sachen
könnte ich nicht durchziehen. Ein komplettes FAT traue ich mir z. B.
natürlich nicht zu unabhängig zu entwickeln. (Bitte jetzt nicht lachen).
Jedenfalls weiß ich von mir selber dass man nicht aufgeben darf. Da muß
man durch.
Guten Abend noch,
Gerhard
Gerhard O. schrieb:> Karl Heinz schrieb:>> Gerhard, das ist keine gute Idee>> Hallo Karl Heinz,>> Danke für Deine Erklärungen bzgl. meines Beitrags.
Kein Problem. Deswegen sitzen wir ja mit mehreren Leuten an den
Beiträgen, damit wir uns gegenseitig korrigieren und unterstützen. Nimms
bitte nicht persönlich.
> Ich kann leider nicht direkt die Demoprogramme testen weil ich nur mit> CodevisionAVR arbeite. Gcc-AVR habe ich nirgendwo installiert. Habe> keine Ahnung wie man GCC-AVR mit den üblichen Ausgaben auf den Uart> zugreift. Das heisst, ich müsste das mal recherchieren:-)
Es gibt da keine üblichen Ausgaben. Man kann zwar der Runtime eine
putchar Funktion unterjubeln, so dass printf und Konsorten wieder
funktionieren. Aber ehrlich: Kein Mensch macht sich diese Mühe. Es lohnt
einfach nicht.
Wenn du von der Annahme ausgehst, dass es ein LCD oder eine UART gibt,
denn geh auch von der Annahme aus, dass es eine String-Ausgabe gibt, die
so ähnlich wie puts oder putString heisst (also dann: uart_puts oder
lcd_puts). Das solle eigentlich jeder erkennen können, was damit gemeint
ist. Zugegeben, auch mit printf sollte eigentlich jeder klarkommen und
wissen, dass das als "generische Ausgabefunktion" anzusehen ist, die je
nach persönlichen Verhältnissen anzupassen ist. Tja. Sollte.
> keine großen Schwierigkeiten mehr. Für mich war dieser Weg gangbar. Ich> masse mir nicht an ein guter Programmierer zu sein.
Was ich so gesehen habe: Du brauchst dein Licht nicht unter den Scheffel
zu stellen.
> könnte ich nicht durchziehen. Ein komplettes FAT traue ich mir z. B.> natürlich nicht zu unabhängig zu entwickeln. (Bitte jetzt nicht lachen).
:-) Niemand lacht.
(Ist aber auch nur: Doku raussuchen, erst mal am Papier verstehen wies
funktioniert, sich die Daten einer bestehenden FAT raussuchen und mal
nachvollziehen wie die Datenwege durch die Bytes laufen. Hat man das,
sieht alles gleich ganz anders aus. Brauch ich dir aber nicht sagen :-)
Karl Heinz schrieb:>> Danke für Deine Erklärungen bzgl. meines Beitrags.>> Kein Problem. Deswegen sitzen wir ja mit mehreren Leuten an den> Beiträgen, damit wir uns gegenseitig korrigieren und unterstützen. Nimms> bitte nicht persönlich.
Ich möchte nur noch kurz dazu bemerken, dass ich mit dem extra Zeiger
nur demonstrieren wollte wie man einen Zeiger erzeugt und mit der
Variabel koppelt. Sonst hätte ich das nicht gemacht. Im Nachhinein gebe
ich Dir recht, es war nicht gerade zur Klarheit fördernd. Leider machte
ich den Beitrag in der Mittagspause und war am Ende unter großem
Zeitdruck. Deshalb die paar Fehler im Code. Jedenfalls vielen Dank für
die Feedback.
Schönes Wochenende noch,
Gerhard
@ Gerhard O. (gerhard_)
>Ich möchte nur noch kurz dazu bemerken, dass ich mit dem extra Zeiger>nur demonstrieren wollte wie man einen Zeiger erzeugt und mit der>Variabel koppelt.
Ob DAS gerade für den OP zweckdienlich ist?
>Zeitdruck. Deshalb die paar Fehler im Code. Jedenfalls vielen Dank für>die Feedback.
Der
Die
Das
Feedback
?
Falk Brunner schrieb:> @ Gerhard O. (gerhard_)>>>Ich möchte nur noch kurz dazu bemerken, dass ich mit dem extra Zeiger>>nur demonstrieren wollte wie man einen Zeiger erzeugt und mit der>>Variabel koppelt.>> Ob DAS gerade für den OP zweckdienlich ist?
Ja, ich weiß.
>>>Zeitdruck. Deshalb die paar Fehler im Code. Jedenfalls vielen Dank für>>die Feedback.>> Der> Die> Das> Feedback>> ?
Im Duden steht es müßte im Singular "das Feedback" heissen. Danke!
Falk Brunner schrieb:> Im Duden? Ok, dort stehen auch Fremdwörter. Früher (tm) war es noch eine> (die) Rückmeldung ;-)
Ja, Feedback ist dort aufgeführt;-)
http://www.duden.de/rechtschreibung/Feedback
Allerdings trifft das Wort Rückmeldung auch nicht ganz wie ich es
gemeint hatte. Wenn es unbedingt ein deutsches Wort sein sollte, dann
würde ich jetzt nach etwas Überlegung eher so formulieren:
"Vielen Dank für Deine Überlegungen oder Kritik..."
So gesehen war Feedback eher etwas fehl am Platz.
Falk Brunner schrieb:> Auch eine Rückmeldung kann Überlegungen oder Kritik enthalten.> Rückmeldungen sind nicht auf Maschinen begrenzt.
Im modernen Kontext assoziiert man aber Rückmeldung meistens doch mit
Maschinen oder mit dem Resultat irgendeiner Aktivität. In einem Roman
findet man das Wort Rückmeldung wahrscheinlich eher seltener.
Rückmeldung hat für mich fast Militärischen Charakter.