Ich habe schon einmal im µC Forum gepostet, aber leider habe ich mich
nicht genau ausgedrückt und es kam zu Missverständnissen. Da ich denke
das Ganze ist hier eh etwas besser aufgehoben ist, nochmal der zweite
Versuch. Ich hoffe jemand kann mir einen Tipp geben, wie ich den von
Bosch gelieferten undvollständigen Code mit meinen I²C Funktionen
verheiraten kann. Zur Vereinfachung habe ich nur die Read Funktion
angeben und alles drumherum rausgelöscht. In den Kommetaren habe ich
durch "Bosch" Zeilen bezeichnet, die eben fertig waren und mit "Bucky"
die meinen.
PS: Ihr seit meine letzte Hoffnung, sitze schon seit vielen Stunden
dran. Wenn es nicht klappt muss ich alles neu schreiben ohne
Funktionszeiger... :-(
Beschreibung:
Die Init Funktion in der bmp085.c Datei soll meine Read Funktion beutzen
um auf den Chip per TWI zuzugreifen. Dies geschieht über Pointer und
Funktionspointer. Wie verbinde ich meine bus_read funktion mit dem
Bosch-Code der diese in der bmp085_init() aufrufen möchte? Hier der Code
so kurz wie es eben ging:
1
main.c:
2
3
#include"RS232.h"
4
#include"TWI_Master.h"
5
#include"bmp085.h"
6
7
intmain(void)
8
{
9
TWIM_Init(368000);
10
RS232_Init();
11
//hier würde ich das Struct aus der bmp085.h generieren
hm, man sieht ja nur die Hälfte.
Deshalb mal die Vermutung: bmp085_init benötigt nicht nur
eine struct mit irgendwas drin, sondern eine vernünftig vorbelegte
struct.
Du hast ja bereits eine Funktion bus_read.
Je eine ähnliche Funktion wirst du noch zum Schreiben und
für delay_msec brauchen.
Alle drei müssen dann mit einer Zuweisung oder beim Initialisieren
der struct eingetragen werden, und dann mit dieser gefüllten struct
wird bmp085_init aufgerufen.
Also etwa in der Art:
1
intmain(void)
2
{
3
TWIM_Init(368000);
4
RS232_Init();
5
//hier würde ich das Struct aus der bmp085.h generieren
6
bmp085_tmybmp;
7
8
mybmp.bus_read=bus_read;
9
// analog für bus_write und delay_msec...
10
11
bmp085_init(&mymbp);//structpointer übergeben
12
}
Ist jetzt so meine Vermutung....
In der Doku zu bmp085_init sollte vielleicht mehr dazu stehen,
was sie wirklich braucht und was die Funktionen machen müssen;
da habe ich keine Ahnung.
Eine Doku ist nicht vorhanden und der ganze Programmcode ist natürlich
viel länger, es gibt bereits eine Funktion fürs bus_write, etc. Aber er
steigt halt schon beim ersten bus_read aus. Das eine leere Struct
übergeben wird ist korrekt, über die bmp_init wird diese dann gefüllt
mit parametern aus dem chip.
Wenn ich in "comres +=
p_bmp085->BMP085_BUS_READ_FUNC(p_bmp085->dev_addr, BMP085_CHIP_ID__REG,
&data, 1); " das "p_bmp085->" raus nehme geht es auch, er greift auf
meine bus_read direkt zu. Wenn es aber über den Struct und den darin
erstellten Funktionszeiger gehen soll steigt er aus. Ich stelle mir es
wie folgt vor:
-ich erstelle ein Struct des Typs bmp085_t: bmp085_t mybmp;
-es existiet nun neben den ganzen Calibrierparameter-Variablen auch ein
Funktionspointer für die bus_read funktion mit genau meinen Parametern:
"BMP085_BUS_RD_RETURN_TYPE (*bus_read)( BMP085_BUS_RD_PARAM_TYPES );"
-ich rufe bmp085_init auf und es wird irgendwann vom Bus gelesen:
"comres += p_bmp085->BMP085_BUS_READ_FUNC(p_bmp085->dev_addr,
BMP085_CHIP_ID__REG, &data, 1); "
-wegen p_bmp085-> wird in das struct mybmp geschaut, hier sollte der
Funktionspointer bus_read hinterlegt sein
- hier steigt das Programm nun aus, da die Verbindung zwischen dem
Funktionspointer und meiner bus_read Funktion fehlt. Diese Verbindung
will mir trotz intensiver Literaturrecherche nicht gelingen.
Verständlich? Oder habe ich zu viel Code herausgelöscht (Urheberrecht)?
Evtl. könnte ich es per mail an einzelne geben für eine bessere
Übersicht...
p_bmp085->BMP085_BUS_READ_FUNC ist NULL, zumindest wurde es in obigem
Codefragment nicht initialisiert. D.h. er springt an den Reset-Interrupt
(der liegt i.d.R. bei 0x00).
HTH
Bucky 2k schrieb:
> Das eine leere Struct> übergeben wird ist korrekt, über die bmp_init wird diese dann gefüllt> mit parametern aus dem chip.
Aber damit die Funktion auf den Chip zugreifen kann, muss der
Funktionszeiger vorher eingetragen worden sein. So wie Klaus es schon
geschrieben hat:
1
bmp085_tmybmp;
2
mybmp.bus_read=bus_read;
3
bmp085_init(&mymbp);
> Wenn ich in "comres +=> p_bmp085->BMP085_BUS_READ_FUNC(p_bmp085->dev_addr, BMP085_CHIP_ID__REG,> &data, 1); " das "p_bmp085->" raus nehme geht es auch, er greift auf> meine bus_read direkt zu. Wenn es aber über den Struct und den darin> erstellten Funktionszeiger gehen soll steigt er aus.
Eben weil der Funktionszeiger nicht initialisiert ist.
> Ich stelle mir es wie folgt vor:>> -ich erstelle ein Struct des Typs bmp085_t: bmp085_t mybmp;>> -es existiet nun neben den ganzen Calibrierparameter-Variablen auch ein> Funktionspointer für die bus_read funktion mit genau meinen Parametern:> "BMP085_BUS_RD_RETURN_TYPE (*bus_read)( BMP085_BUS_RD_PARAM_TYPES );"
Aber er existiert nicht "irgendwie automatisch", du musst ihn da schon
reinschreiben.
> - hier steigt das Programm nun aus, da die Verbindung zwischen dem> Funktionspointer und meiner bus_read Funktion fehlt. Diese Verbindung> will mir trotz intensiver Literaturrecherche nicht gelingen.
Ernsthaft? Nirgendwo in deiner Literatur steht, wie man einem
Funktionszeiger einen Wert zuweist?
Siehe oben.
g457 schrieb:
> p_bmp085->BMP085_BUS_READ_FUNC ist NULL, zumindest wurde es in obigem> Codefragment nicht initialisiert. D.h. er springt an den Reset-Interrupt> (der liegt i.d.R. bei 0x00).>> HTH
Das wäre ja noch schön.
In Wirklichkeit ist es noch schlimmer: der Inhaöt ist zufällig!
Ebenso wie die beiden anderen Zeiger.
Wäre die struct global, dann wäre alles mit 0 initialisiert.
Hier ist es dagegen eine automatische Variable, daher nicht
mit einem definierten Wert vorbelegt.
Bucky 2k schrieb:
> ...> - hier steigt das Programm nun aus, da die Verbindung zwischen dem> Funktionspointer und meiner bus_read Funktion fehlt. Diese Verbindung> will mir trotz intensiver Literaturrecherche nicht gelingen.
Ich habe netterweise bereits recherchiert.
Die Verbindung ist die Zeile, die ich oben hingeschrieben hatte:
1
mybmp.bus_read=bus_read;
Das bedeutet: an das Element bus_read der Struktur mybmp
(also an mybmp.bus_read) wirde die Adresse deiner Funktion
bus_read zugewiesen.
Das Gleiche musst du noch für die anderen beiden Funktionen
machen.
Mit dem Aufruf der init-Funktion machst du den
bmp085-Funktionen deine Funktionen bekannt.
Ich gehe schwer davon aus, daß es nicht reicht,
nur die read-Funktion einzutragen.
Dringende Empfehlung: Alle drei Funktionen definieren und
in der struct eintragen, und dafür sorgen, daß sich die
Funktionen bemerkbar machen, wenn sie aufgerufen werden
(für jede der Funktionen eine eigene LED, oder Logausgabe
o.s.ä.).
Ansonsten ist es nötig, mehr Infos zu bekommen.
Was zum Beispiel heißt "... steigt er aus"?
Wie soll man mit Quelltextfragmenten und solchen
Beschreibungen etwas erraten?
Weitere Empfehlung: erstmal unabhängig vom konkreten
Problem mit Funktionszeigern warm werden!
Z.B. mit den Funktionen bsearch und qsort aus der
Standardbibliothek kann man schön spielen.
> ...
Bucky 2k schrieb:
> bmp085.h:>> //Prototyp Bus-Lesefunktion Bucky> char bus_read(unsigned char device_addr, unsigned char register_addr,> unsigned char *register_data, unsigned char read_length);>
Dieser Prototyp gehört da nicht rein!
Die bmp085.h geht dich nichts an (die ist von Bosch). Also lass sie in
Ruhe.
Deine Funktion bus_read residiert in read_write.c
Ergo mach ein Header File read_write.h dafür. Dort kommt dann der
Prototyp rein.
Klaus Wachtler schrieb:
> Ich habe netterweise bereits recherchiert.> Die Verbindung ist die Zeile, die ich oben hingeschrieben hatte:>
1
>mybmp.bus_read=bus_read;
2
>
>>
Entschuldige, ich habe gestern nach dem Heimkommen noch schnell die
Fragen beantworten wollen und die entsprchende Zeile überlesen.
Auch habe ich versucht den Funktionszeiger zu initialisieren, das etwas
fehlte war mir ja bewusst (und das er deshalb an den Anfang des
Programms sprang). Nur habe ich es aus der FAQ und aus dem C von A bis Z
Buch nicht umsetzen können, es kamen immer Compilerfehler. DIe FAQ
schlägt ja z.B. dies vor, oder habe ich da ganz falsch geschaut:
typedef void (*VoidFnct)( void );
mit
VoidFnct MeineFunktionen[] = { Funct1, Funct2 };
und den Aufruf
MeineFunktionen[0]();
Dies konnte ich nicht adaptieren und ist ja auch abweichend vom
gemachten Vorschlag hier...
Vielen Dank jedenfalls für die Hilfe in diesem Thread, es hat mir viel
weitere Arbeit erspart wenn es heute Abend dann hoffentlich
funktioniert...
Bucky
Klaus Wachtler schrieb:
> Ich habe netterweise bereits recherchiert.> Die Verbindung ist die Zeile, die ich oben hingeschrieben hatte:>
1
>mybmp.bus_read=bus_read;
2
>
>> Ich gehe schwer davon aus, daß es nicht reicht,> nur die read-Funktion einzutragen.>> Dringende Empfehlung: Alle drei Funktionen definieren und> in der struct eintragen, und dafür sorgen, daß sich die> Funktionen bemerkbar machen, wenn sie aufgerufen werden> (für jede der Funktionen eine eigene LED, oder Logausgabe> o.s.ä.).>> Wie soll man mit Quelltextfragmenten und solchen> Beschreibungen etwas erraten?>> Weitere Empfehlung: erstmal unabhängig vom konkreten> Problem mit Funktionszeigern warm werden!> Z.B. mit den Funktionen bsearch und qsort aus der> Standardbibliothek kann man schön spielen.>>> ...
Das Erraten hat aber ja super geklappt, denn es funktioniert wunderbar!
Mein Problem war, dass ich zwar wusste wie Funktionszeiger
funktionieren, auch wusste wie ich ein Element im Struct adressiere,
aber beides zusammen nicht erkannt habe. Mit mybmp.bus_read = bus_read;
klappt es ich habe irgendwie immer versucht den Zeiger dem Struct als
ganzes zu übergeben und nicht bedacht, dass ich selbstverständlich auch
die Stelle im Struct angeben muss. Tatsächlich muss ich nur bus_read und
bus_write implementieren, der Rest ist bereits im Bosch Code.
Karl heinz Buchegger schrieb:
> Bucky 2k schrieb:>>> bmp085.h:>>>> //Prototyp Bus-Lesefunktion Bucky>> char bus_read(unsigned char device_addr, unsigned char register_addr,>> unsigned char *register_data, unsigned char read_length);>>>> Dieser Prototyp gehört da nicht rein!> Die bmp085.h geht dich nichts an (die ist von Bosch). Also lass sie in> Ruhe.> Deine Funktion bus_read residiert in read_write.c> Ergo mach ein Header File read_write.h dafür. Dort kommt dann der> Prototyp rein.
Ich stimme zu, dass es eigentlich eine neue Headerdatei geben sollte.
Aber Bosch hat direkt einen Platzhalter in der Header vorgesehen, daher
habe ich die Prototypen da rein gepackt:
/**
define for used read and write macros
*/
/** Define the calling convention of YOUR bus communication routine.
\note This includes types of parameters. This example shows the
configuration for an SPI bus link.
*/
Vielen Dank nochmal an alle Helfenden für Ihre Gedult mit jemandem der
C-Programmierung und µC (noch) nicht regelmäßig benutzt und daher nicht
alle Zusammenhänge direkt erkennt, auch wenn die Funktionen für sich
nachgeschlagen und verstanden wurden!!!
Bucky