... ich werde noch mit dem Bobbes verrückt. Ich bin am "zusammenbasteln"
einer (wie ich glaube benutzerfreundlichen) Lib für den ultrabilligen
STM8S103F3P6 (Extrembilligboard aus China für einen Euro).
Leider muss ich hier (weil es eine offene Toolchain sein soll) den SDCC
3.5.0 verwenden wobei ich allerdings glaube, dass das nicht mein Problem
ist.
Ich kämpfe mich nun schon für die verschiedenen Peripherieeinheiten
durchs Datenblatt und hänge nun (nachdem ich Clock, GPIO, USART, SPI,
ADC ansprechen kann) am I2C Bus.
Will einfach nicht. Ich bekomme das Teil irgendwie nicht richtig
konfiguriert:
Werte aus meiner Headerdatei für den STM8S103F3:
1
// ------------------- I2C -------------------
2
#define I2C_CR1 *(unsigned char*)0x5210
3
#define I2C_CR2 *(unsigned char*)0x5211
4
#define I2C_FREQR *(unsigned char*)0x5212
5
#define I2C_OARL *(unsigned char*)0x5213
6
#define I2C_OARH *(unsigned char*)0x5214
7
8
#define I2C_DR *(unsigned char*)0x5216
9
#define I2C_SR1 *(unsigned char*)0x5217
10
#define I2C_SR2 *(unsigned char*)0x5218
11
#define I2C_SR3 *(unsigned char*)0x5219
12
#define I2C_ITR *(unsigned char*)0x521A
13
#define I2C_CCRL *(unsigned char*)0x521B
14
#define I2C_CCRH *(unsigned char*)0x521C
15
#define I2C_TRISER *(unsigned char*)0x521D
16
#define I2C_PECR *(unsigned char*)0x521E
17
18
// I2C - Bitadressen
19
20
#define I2C_CR1_PE ( 1 << 0 )
21
#define I2C_CR1_NOSTRETCH ( 1 << 7 )
22
#define I2C_CR2_START ( 1 << 0 )
23
#define I2C_CR2_STOP ( 1 << 1 )
24
#define I2C_CR2_ACK ( 1 << 2 )
25
#define I2C_CR2_POS ( 1 << 3 )
26
#define I2C_CR2_SWRST ( 1 << 7 )
27
#define I2C_ITR_ITEVTEN ( 1 << 1 )
28
#define I2C_OARH_ADDCONF ( 1 << 6 )
und die C-Sequenz, die erst einmal nur zum Testen sein soll um zu sehen,
ob die STM8 Peripherie das korrekt wegsendet (0x90 ist Adresse eines
LM75)
1
I2C_CR1=0;// Power disable, clock stretching enable
2
I2C_FREQR=16;// 16 MHZ F_CPU
3
I2C_CCRL=16;
4
I2C_CCRH=00;
5
I2C_TRISER=17;
6
I2C_OARH|=I2C_OARH_ADDCONF;
7
regread=I2C_SR1;
8
9
I2C_CR1|=I2C_CR1_PE;// I2C Power On
10
I2C_CR2|=I2C_CR2_ACK;// ACK nach Transmit abfragen
11
I2C_CR2|=I2C_CR2_START;// I2C Bus - Startkondition
12
13
I2C_DR=0x90;// zu schickende I2C-Bus Adresse (LM75)
14
15
I2C_CR2|=I2C_CR2_STOP;// I2C Bus - Stop
... auf dem Speicherscope kann ich nur die Startkondition sehen, danach
2,5 µS auf SDA und SCL 0-Pegel gefolgt von der Stopkondition.
Was muss ich anderst machen, damit die Takte und die SDA Leitung etwas
ausspucken (lach , ich überleg immer wieder ob der Chip hinüber ist...
ob die Portpins defekt sind, was ja nicht sein kann, sonst würden die
Start-Stop Konditionen nicht korrekt abgefahren werden.
Was muss ich tun, damit der Chip zum Beispiel den Wert 0x90 sendet ?
Gruß,
Ralph
PS: Bitbanging ist für mich keine Option, denn das hab ich schon am
Funktionieren auf dem STM8 gehabt (icht möchts schon in Hardware
haben)... und ich freue mich auf das nächste Problem das ich haben
werde, wenn ich den CAN-Bus implementieren möchte.
... damit schaltet man den Takt auf Peripherieeinheiten des STM8 (und
das ist schon beim Initialisieren des Systems geschehen (es werden alle
Peripherieeinheiten mit Takt versorgt).
Abgesehen davon denke ich, dass dann auch nicht die Start-Stop Dinge auf
dem I2C Bus funktionieren würden...
Die Initialisierung der PCKENR ist bei mir im sys_init wie folgt:
CLK_PCKENR1 = 0xff;
CLK_PCKENR2 = 0xff;
Juhuu, ich bin mit meinem Problem nicht alleine. Ich versuche zur Zeit
auch, das Chinaboard mit dem STM8 zu verstehen.
Ich hab das CCRL bzw. CCRH Register irgendwie anders verstanden, hier
mein Versuch einer init-Funktion:
1
uint8_tfreq=1;//1MHz
2
uint16_tperiod_time=(1/freq)*1000;//period_time in ns
3
uint16_tresult=5000/period_time;
4
5
I2C->FREQR=freq;
6
I2C->TRISER=(freq+1);
7
I2C->CCRL=(uint8_t)result;
8
I2C->CCRH=(uint8_t)result&0x0F;//first 4 bits of CCR-value
9
10
I2C->OARL=0xA0;//own Address
11
I2C->OARH=0x40;//6th bit must be set by software
12
13
I2C->CR1=0x01;//enable peripheral
Funktioniert allerdings auch nicht. Ich hatte gehofft, wenigstens einen
Clock auf der Leitung zu haben, aber irgendwie passiert gar nichts.
Max M. schrieb:> wenigstens einen> Clock auf der Leitung zu haben, aber irgendwie passiert gar nichts.
Schmunzeln muss: Wenn es den Clock geben würde, würde es fast schon
sicherlich auch die Daten geben. Also ist das "wenigstens" schon etwas
stark untertrieben, das wäre schon verdammt viel !
... so, die erste Erkenntnis: der I2C Bus ist nach der Startkondition
nicht sofort frei und kann das zu sendende Kommando nicht sofort
uebernehmen ...
Also muss noch eine Abfrage her, wann der Bus "frei" ist...
Ralph S. schrieb:> "Entscheident" hier war die Abfrage, ob der I2C-Bus die Startaktion> schon erkannt hat !! while (!(I2C_SR1 & I2C_SR1_SB));
Danke für den Hinweis, bei mir bleibt das Programm da leider hängen und
mag nicht mehr weiter :(
Hat bei mir so funktioniert (und tut es noch).... aaaalerdings:
überprüfe einmal, ob dein Headerfile in dem die ganzen Adressen
deklariert sind so auch stimmen.
Mein Ausgangsheader gehört fälschlicherweise (auch wenn der Dateiname
etwas anderes gesagt hat) zu einem STM8L und nicht zu einem STM8S ...
und da waren einige Adressen schlicht anderst als sie zu einem STM8S
passen. Habe ich also die relevanten Daten frisch aus dem Datenblatt
abgetippt (wobei ich mir fast sicher bin, dass ich bestimmt auch
irgendwo Tippfehler habe, weil ich immer irgendwo irgendwelche
Tippfehler habe).
Leider kann ich dir nicht weiterhelfen als zu sagen dass das so bei mir
funktioniert.
So wie das aussieht (und wie du die einzelnen Bits ansprichst) ist das
wohl nicht der SDCC ... (den ich nicht so wirklich mag, der aber
scheinbar der einzig frei verfügbare Compiler ist).
Wenn ich mal alles fertig habe werde ich es hier einstellen. Für den
ersten Moment ist dir vielleicht geholfen, wenn anstelle der Abfrage ob
die Startcondition schon angenommen wurde eine Delay-Schleife einfügst
(die abhängig vom Takt des I2C Busses ist) solltest du das Versenden auf
einem Oszi sehen können (das war bei mir der erste Versuch).
Nächste Woche... wenn ich mein Bastelequipment wieder zur Verfügung hab,
kann ich weiteres einstellen.... Smile, vielleicht magst ja dann mal das
ganze Paket (dann leider mittels SDCC und eigenem Makefile
ausprobieren).
Gruß zum Wochenfende,
Ralph
Ralph S. schrieb:> So wie das aussieht (und wie du die einzelnen Bits ansprichst) ist das> wohl nicht der SDCC ... (den ich nicht so wirklich mag, der aber> scheinbar der einzig frei verfügbare Compiler ist).
Gerade mit dem aktuellen SDCC ausprobiert: Beides geht, und es wird
sogar der gleiche Code erzeugt:
Ralph S. schrieb:> SDCC ... (den ich nicht so wirklich mag, der aber> scheinbar der einzig frei verfügbare Compiler ist).
Welche Version von SDCC verwendest Du, und was daran magst Du nicht?
Philipp
Ralph S. schrieb:> I2C_CR2 |= I2C_CR2_START; // I2C Bus - Startkondition>> I2C_DR = 0x90; // zu schickende I2C-Bus Adresse (LM75)>> I2C_CR2 |= I2C_CR2_STOP; // I2C Bus - Stop>> ... auf dem Speicherscope kann ich nur die Startkondition sehen, danach> 2,5 µS auf SDA und SCL 0-Pegel gefolgt von der Stopkondition.
Was hast Du denn sonst erwartet? Da fehlen sämtliche Wartezyklen
zwischendurch. Die sollte Dir ein korrekt funktionierendes Peripherial
mittels Statusregister anzeigen.
Jim M. schrieb:> Was hast Du denn sonst erwartet? Da fehlen sämtliche Wartezyklen> zwischendurch. Die sollte Dir ein korrekt funktionierendes Peripherial> mittels Statusregister anzeigen.
... das Problem hat sich ja (wie oben schon gemeldet) bereits erledigt
indem ich die Statusregister abfrage...
Philipp Klaus K. schrieb:> Welche Version von SDCC verwendest Du, und was daran magst Du nicht?>> Philipp
Das ist eine rein subjektive Einstellung. Ich hatte den SDCC früher in
Verwendung zur Programmierung von MCS-51 Controllern. Jetzt habe ich
sehr lange mit GCC und deren Ports nach AVR und ARM-NONE-EABI-GCC
gewerkelt und natürlich sind da dann manche Dinge etwas anderst.
Prinzipiell habe ich das Gefühl, dass der SDCC beim Linken extrem
langsamer als der GCC ist.
Natürlich will ich die Verwendbarkeit des SDCC's nicht schmälern, es
steckt immens viel Arbeit drin. Ich hätte nur nicht gedacht gehabt, dass
ich den SDCC noch einmal anfasse.
Die Sache mit den Bitfields funktioniert natürlich, allerdings ist mir
die Methode Read-Manipulate-Write back sehr in Fleisch und Blut
übergegangen.
By the way: woran liegt es, dass es von GCC keinen Port für STM8 und
MCS-51 gibt?
Liegt es daran, dass es für den MCS-51 schon den SDCC als Quasistandard
gab und sich das nicht "rentiert" hat, dass vielleicht Atmel die
Gemeinde für den GCC gesponsert hat und dasselbe eventuell für die ARM
Controller gilt ? Technisch gesehen wäre ein "MCS51-GCC" doch machbar
gewesen, genauso wie ein "STM8-GCC" oder ein "PIC18-GCC".
Lag es daran, dass das Interesse der freien Gemeinde einfach nicht groß
genug war / ist ?
(nein, ich würde mich nicht in er Lage fühlen, den GCC selbst zu
portieren und selbst wenn, würde ich wohl nicht die Zeit dazu finden)
Ralph S. schrieb:> By the way: woran liegt es, dass es von GCC keinen Port für STM8 und> MCS-51 gibt?> Liegt es daran, dass es für den MCS-51 schon den SDCC als Quasistandard> gab und sich das nicht "rentiert" hat, dass vielleicht Atmel die> Gemeinde für den GCC gesponsert hat und dasselbe eventuell für die ARM> Controller gilt ? Technisch gesehen wäre ein "MCS51-GCC" doch machbar> gewesen, genauso wie ein "STM8-GCC" oder ein "PIC18-GCC".
GCC und SDCC unterscheiden sich unter anderem in der Registerallokation
und im Verhältnis von Instruction Scheduling und Registerallokation
sehr. Dadurch ist der GCC besser für RISC-Architekturen mit relativ
vielen eher gleichartigen Registern geeignet (z.B. ARM, AVR). SDCC kann
dagegen gut mit Architekturen mit wenigen, sehr unterschiedlichen
Registern umgehen (z.B. STM8, S08, Z80).
Philipp
Ralph S. schrieb:> Prinzipiell habe ich das Gefühl, dass der SDCC beim Linken extrem> langsamer als der GCC ist.
Hmm, ich könnte mir die Geschwindigkeit beim Linken 'mal ansehen. Aber
eigentlich verbringt SDCC die meiste Zeit in Registerallokator und
Peephole Optimizer.
Philipp
Philipp Klaus K. schrieb:> Hmm, ich könnte mir die Geschwindigkeit beim Linken 'mal ansehen. Aber> eigentlich verbringt SDCC die meiste Zeit in Registerallokator und> Peephole Optimizer.
Hmmm, wenn ich das so von dir lese: Bist du bei der Entwicklung vom SDCC
mit involviert? (und ich "gestehe" jetzt, dass ich deinen Namen
gegoogelt hab).
Ralph S. schrieb:> Philipp Klaus K. schrieb:>> Hmm, ich könnte mir die Geschwindigkeit beim Linken 'mal ansehen. Aber>> eigentlich verbringt SDCC die meiste Zeit in Registerallokator und>> Peephole Optimizer.>> Hmmm, wenn ich das so von dir lese: Bist du bei der Entwicklung vom SDCC> mit involviert? (und ich "gestehe" jetzt, dass ich deinen Namen> gegoogelt hab).
Ja. Und ich habe gerade fünfmal Coremark auf meinen Notebook für STM8
kompiliert, mit make -j 5. Das benötige jeweils zwischen 9.562 s und
10.507 s insgesamt, einschließlich Linker.
Dann habe Linkeraufruf, der die Dateien des Coremark zusammen linkt, das
nötige aus der Standardbibliothek heraussucht, und eine Intel-Hex-Datei
daraus macht, zehnmal einzeln ausgeführt. Das benötigte jeweils zwischen
0.013 und 0.014 s.
Alle Zeitangaben wurden per time gemessen.
Philipp
P.S.: Ich hatte bisher zwar nie den Eindruck, dass der Linker langsam
sei. Aber es könnte trotzdem irgendwelche Fälle geben, in denen er es
ist.
... dann auf diesem Wege vielen Dank dass es den SDCC gibt. Es freut
mich immer wenn etwas frei verfügbar ist und solche Dinge der
Allgemeinheit zur Verfügung gestellt wird.
Auch wenn ich "GCC Verseucht bin": Ohne den SDCC könnte ich mit dem STM8
so nicht "spielen"
Vielen Dank
Ralph S. schrieb:> Oha .... Asche über mein Haupt: einen GCC für Pic - Controller> gibt es> (smile, dann sollte ich mir auch mal einen Pic Controller beschaffen)
Wo?
Es gibt die 32-Bit PICs, die haben einen MIPS-Kern, was für GCC passt.
Aber für die älteren (14- und 16-Bit) wüßte ich nichts. Da kenne es nur
SDCC ("work in progress", halbwegs brauchbar für 16-Bit, aber bei weitem
nicht so gut wie die anderen SDCC-Backends).
Es gibt da auf Sourceforge ein Projekt "GCC toolchain for Microchip
PIC", das ist aber seit 2006 noch in der Phase "planning", und seit 2013
tat sich da wohl gar nichts mehr.
Philipp
Ralph S. schrieb:> Auch wenn ich "GCC Verseucht bin": Ohne den SDCC könnte ich mit dem STM8> so nicht "spielen"
Nun, der GCC ist SDCC natürlich in mancher Hinsicht weit voraus. Aber im
Vergleich zu den anderen Compilern für STM8 steht SDCC nicht so schlecht
da: http://colecovision.eu/stm8/compilers.shtml
Philipp
P.S.: Falls Du den SDCC 3.5.0 verwendest: Demnächst gibt es SDCC 3.6.0,
da hat sich insbesondere für STM8 und bezüglich der Unterstützung der
C-Standards nochmal einiges getan.
while(!(I2C->SR1&(1<<0)));//check if device received start generation
21
}
Mein Program bleibt im while hängen und es passiert nichts auf SDA und
SCK. Ich finde I2C teilweise etwas komisch, fängt schon damit an, dass
man gezwungen wird, ein Register zu lesen nur damit etwas per Hardware
gesetzt werden kann? Gibts doch bei SPI und UART auch nicht.
Muss man noch irgendwas anderes setzen? Wenn es zu dem STM8 wenigstens
mehr Doku geben würde...Ich hab versucht, die ST I2C Bibliothek zu
kopieren, hat aber auch nicht funktioniert, wobei die meiner Ansicht
nach das selbe machen.
jetzt hab ich meine Sachen nicht zur Verfügung (Wochenende) .....
aaaaber GPIO hab ich definitiv nicht gesetzt gehabt... und weil die
Register ResetValue 0 sind, sind die auf Input....
Hmmmm vielleicht sollte ich vorab mein sehr chaotisches Zeug mal hier
einstellen.... aaaaaber, ich hab bald Urlaub
Hallo Max,
ich habe folgende Quelle benutzt (nur den Basis-Treiber für I2C:
i2c_drv.c/.h) und auf meinen STM8S105S4 adaptiert:
http://hamlab.net/mcu/stm8/ds1307.html (russisch, aber durchaus
selbsterklärend)
Mein Ergebnis zeige ich lieber nicht, ich bin ein mehr als lausiger
Programmierer. Aber es läuft mit einem DS3231M, was allerdings nur dem
unbekannten russischen Autor und seiner übersichtlichen software zu
verdanken ist.
Ohne jetzt den STM8105L zu kennen oder einen anderen. Quellen im Netz
gibts viele... und viele fehlerhafte. Meine Sachen dürften auch genügend
Fehler haben. Grundsätzlich Fehler 1 war: Adressdefinitionen für einen L
Typ passen nicht in allem für einen S Typ. Wenn also irgendwo eine
Quelle eine Datei #include stm8l.h einbindet, dann sind Fehler für stm8s
vorprogramiert. Diese Datei dann dem Datenblatt entsprechend
modifizieren.
Bsp. ist da schon das initialisieren des Systems fehlerhaft und der
Controller läuft mit 4 anstelle mit 16 MHz.
Wie gesagt, ich versuch dass ich das am Montag noch schaff hier
einzustellen. Programme sind für SDCC 3.5
STM8_I2C schrieb:> Also nur das hier:
Danke, das hat mir schon einmal sehr geholfen. Was ich vom Code her
nicht ganz verstehe, ist die Funktion zum Lesen des Registers. In dem
Datenblatt des ICs, den ich auslesen will, steht:
1
the 7-bit I2C address for the device is 0x1D, followed by the R/W bit
Also müsste ich doch das hier zuerst ins DR-Register schieben?
1
I2C->DR=(slaveAddress|0x01)
In dem russischen Code wird aber seltsamerweise 2 mal die Adresse des
Slave gesendet. Müsste das nicht so aussehen:
1
I2C->DR=(slaveAddress|0x01);//hier wird dem Slave mitgeteilt, das wir etwas von ihm lesen wollen
2
//das ganze while usw. hier
3
I2C->DR=registerAddress;//hier wird dem Slave das Register mitgeteilt, das wir lesen wollen
Du musst erst einen Schreibzugriff initieren und ihm die Adresse des
Registers mitteilen. Nun musst du eine Repeated Start Condition setzen
und ihm diesmal seine Adresse mit Lesezugriff senden. Erst dann kannst
du die vorher geschrieben Adresse lesen.
Ah okay.
Immerhin bekomme ich jetzt etwas auf die Leitung. Ich hab versucht, den
russischen Code 1 zu 1 zu kopieren. Leider hängt mein Programm wieder in
einer while-Schleife fest:
1
voidinitI2C(){
2
floatfreq=16;//16MHz
3
longccr=freq/(2*100000);//100kHz I2C clock
4
5
I2C->FREQR=freq;
6
I2C->TRISER=(freq+1);
7
I2C->CCRL=ccr;
8
I2C->CCRH=(ccr>>8)&0x0F;
9
10
I2C->OARL=0xA0;//own Address
11
I2C->OARH=(1<<6);//6th bit must be set by software
... wie gesagt, ich habe meine Sachen nicht hier (und den Registersatz
hab ich jetzt nicht auswendig im Kopf), aaaaaaaber:
Bevor es bei mir lief hab ich einen (sehr dummen) Fehler gemacht gehabt:
Wenn du einen Lesezugriff auf ein I2C Device mittels des STM8 machst,
schickt der Controller zuerst die Adresse (mit gesetztem) Lesebit und
(jetzt kommts): Er geht auch her und taktet schön weiter und liest auch
gleich etwas. Verrückterweise (und ich weiß noch nicht warum) liest er 2
Byte !!!!! .
Diese(s) Byte(s) wird erst dann mittels variable= I2C->DR aus dem Buffer
geholt.
Auf dem Oszilloskop kann man sehen, dass er hierbei aber GRUNDSÄTZLICH 9
!!!!! Taktimpulse sendet (für eine ACK-Abfrage).
Wenn du beim Lesen des DR Registers eine grundsätzliche ACK by Master
sendest, der Slave aber kein ACK erwartet, dann ist dieser eine Impuls
für den Slave schon ein neuer Taktimpuls.
Viele I2C Devices erwarten beim letzten gesendeten kein ACK vom Master.
Du solltest also einen Lesezugriff auf den Slave beim letzten gelesenen
Byte im Stile von I2C_read_nack durchführen.
Danke für deine Antwort, ich hoffe, es ist okay, wenn ich deinen Thread
für meine Fragen benutze?
Ralph S. schrieb:> Wenn du einen Lesezugriff auf ein I2C Device mittels des STM8 machst
In meinem Problem gehts erstmal nur darum, dass ich versuche, ein
Register des I2C Devices zu beschreiben um es zu initialisieren.
Ralph S. schrieb:> Viele I2C Devices erwarten beim letzten gesendeten kein ACK vom Master.
Ich weiß nicht, ob ich das richtig interpretiere, aber meines
anscheinend schon (siehe Anhang)?
Nein, dem Diagramm nach erwartet dein Slave Device wenn von ihm gelesen
wurde KEIN Ack vom Master.
Und schmunzeln muß: ich wußte nicht, dass jemandem ein Thread gehören
kann.
Jetzt aber:
Das hier ist meine Implementierung von I2C mit dem STM8S103F3P6 (Minimal
Evaluation Board aus China).
Ich hoffe dass der Quelltext selbsterklärend ist, ich habe so
ausführlich Kommentare eingefügt wie ich konnte.
Das Zip-File enthält alle zum Übersetzen benötigten Software-Module
inkl. einem Makefile
----------------------------------------------------------------------
Makefile
der im Makefile verwendete Compiler ist SDCC 3.5.0. Es wird eine
Linux-Distribution vorrausgesetzt. Das Makefile ist mit Kommentaren
versehen und es sollte leicht möglich sein es für eigene Zwecke
zu modifizieren, vllt. in Verwendung mit einer IDE ?!?)
Optionen:
make
eine Intel-Hexdatei (mit der Endung .ihx) wird erstellt
make clean
"räumt auf", insbesondere .rel Dateien (das sind Objektdateien für
den SDCC) werden gelöscht
make flash
bei angeschlossenem (Chinaclone) STLINK/V2 wird die erzeugte .ihx
Datei in den STM8S übertragen
-----------------------------------------------------------------
Quelldateien:
- stm8s.h
Deklaritonen der Register- und Bitadressen für den STM8S103F3P6
- stm8_init.h / stm8_init.c
initialisiert den Systemtakt (16 MHz) und schaltet Takt für die
Peripherieeinheiten ein
- stm8_gpio.h
stellt Makros zu Verwendung mit GPIO Pins zur Verfügung
(setzen als Ein- oder Ausgang, setzen auf 0 oder 1 ( Ausgang ) oder
lesen wenn als Eingang verwendet)
- uart.h / uart.c
Verwendung int. Peripherieeinheit zur Verwendung als serielle
Schnittstelle
- my_printf.h / my_printf.c
eigene Printf-Funktion die auf eine eigene Ausgabefunktion
umgeleitet +
werden muss (sehr spartanisch und "abgespeckt" damit der erzeugte
Code im erträglichen Maße bleibt)
----------------------------------------------------------
i2c_explore.c
Das "Hauptanwendungsprogramm". Demonstriert die Verwendung des
I2C-Busses.
Benötigt eine serielle Schnittstelle zur Bedienung.
Ist eine Verbindung mit einem seriellen Monitorprogramm hergestellt
(Protokoll 19200 Baud, 8N1) so kann der I2C Bus "untersucht" werden. Der
Bus ist durch eingebbare Kommandos steuerbar:
start
es wird die Startkondition des I2C Busses erzeugt
write
der Bus wird beschrieben. Nach dem "write" Komamndo erfolgt eine
Eingabeaufforderung zur Eingabe des Bytes, welches auf dem Bus
geschrieben werden soll.
read
der Bus wird gelesen und der STM8 sendet nach dem Lesen ein ACK
rnack
der Bus wird gelesen, aber der STM8 sendet nach dem Lesen KEIN ACK.
Dieses ist oft dann der Fall, wenn das letzte Byte aus einem Daten-
frame gelesen wird
scan
der Bus wird nach angeschlosssenen I2C Devices abgesucht. Die Adressen
der angeschlossenen Devices werden angezeigt
Extrakommandos:
---------------
lm75
ist ein LM75 (mit Adresse 0x90) im Bus vorhanden, wird die
Temperatur angezeigt
time
ist ein DS1307 RTC-Chip im Bus vorhanden, wird das Datum und die
Uhrzeit ausgegeben
settime
ist ein DS1307 RTC-Chip im Bus vorhanden, so kann Datum und Uhrzeit
eingestellt werden
----------------------------------------------------------------------
stm8_i2c.gif
Schaltplan für den Anschluß von I2C - Devices inklusive Level-Shifter
zur Anpassung von 3,3V und 5V Bus - Devices
------------------------------------------------------------------------
Ich hoffe ich konnte Max (und enventuell anderen) hiermit helfen.
Gruß,
Ralph
Vielen Dank, dass du hier deinen Code bereitstellst! Was ich nicht ganz
verstehe, ist das switch-case in der I2C Initialisierung insbesondere da
der gleiche Kommentar hinter jeder Zeile steht aber doch andere Werte
geschrieben werden?
Okay, in Zip Dateu konnte ich reingucken. Das war original kopiert für
unterschiedliche Bustakte... 0= 100 KHz, 1= 50 KHz, 2= 15 KHz... Die
Register CCRL und CVRH sind Taktteiler....
Es funktioniert immer noch nicht :(
Ich hab mal eine Zeile eingefügt, um zu überprüfen, ob der TX-Buffer
leer wird, aber selbst in diesem while bleibt das Programm stehen:
while(!(I2C->SR1&(1<<0)));//check if device received start generation
5
I2C->DR=slaveAddress;
6
while(!(I2C->SR1&(1<<7)));
7
while(!(I2C->SR1&(1<<1)));//check addr
8
I2C->SR3;
9
while(!(I2C->SR1&(1<<7)));//wait for TX to be empty
10
I2C->DR=regAddr;//send register we want to write
11
while(!(I2C->SR1&(1<<7)));//wait for TX to be empty
12
I2C->DR=data;//send data
13
while(!(I2C->SR1&((1<<7)|(1<<2))));//wait for TX to be empty and BTF to finish byte transfer
14
I2C->CR2|=(1<<1);//generate stop
15
while(I2C->CR2&(1<<1));//wait for stop
16
}
Mit meinem Logic Analyzer hab ich aber überprüft, das definitiv die
Adresse (0x3A) gesendet wird (siehe Anhang), warum da jetzt 9
Flankenwechsel sind, weiß ich nicht.
... das neunte ist der Takt für das Acknowledge !
Wenn du den Bus vom Master beschreibst, antwortet der Slave mit einem
Acknowledge, dass er sich für die weiteren Aktionen auf dem Bus
verantwortlich fühlt.
Wenn du vom Bus liest, mußt du über das CR2 Register festlegen, ob der
STM8 ein Acknowledge lesen soll oder nicht.
Der STM8 generiert auch dann den 9ten Taktimpuls, wenn er dem Slave KEIN
Acknowledge geben soll (er gibt dann halt beim 9ten Impuls einfach kein
ACK).
Seh dir doch einfach den Code von oben an (i2c_write).
Deinem Logicanalyzer zufolge antwortet übrigens dein Slave mit der
Adresse 34h scheinbar nicht, denn sonst würde auf der SDA-Leitung beim
9ten Impuls ein Low-Pegel liegen ! (Hardware überprüfen, Pop-Up
Widerstände drin ? )