hallo ist es irgendwie (mit vernünftigem aufwand) möglich ein gcc für atmel so zu schreiben dass statt pinnummern eigene labels verwendet werden können? zum beispiel statt PORTB |= (1 << 0) dann SetPin(LAMPE, LOW) ? oder DefinePin(LAMPE, OUTPUT) und auch ReadPin(TASTER) was mir unklar ist, wie könnte ich LAMPE definieren dass nur ein pin referenziert ist? und wie diese funktionen dann effizient auflösen? ev bin ich ja auch grad völlig auf dem holzpfad... ;-) vielen dank
Eine einfache Lösung: #define LAMPE_AN PORTB |= (1 << 0) #define LAMPE_AUS PORTB &=~(1 << 0)
#define LAMPE 1 void SetPin(int PORT,int PIN,int VALUE) { if(VALUE) PORT |= _BV(PIN); else PORT &= ~_BV(PIN); } SetPin(PORTB,LAMPE,1); oder ähnlich, aber das andere ist doch schon recht einfach ;)
besten dank für die schnellen antworten. beim beispiel von philipp hätte ich noch fragen : - SetPin(PORTB,LAMPE,1); PORTB ist ja defniert als _SFR_IO8 (0x05) im iomx8 (für den atmega48) was wird hier genau übergeben? - ~_BV(PIN) : für was steht das _BV ? besten dank
Also mit einer Funktion würd ich da gar nix machen. Die verbraucht Speicher und Rechenleistung bzw. Rechenzeit des µC. Mach es ausschließlich mit #define.... Dann wird alles zur Compilerlaufzeit ausgerechnet. z.B.: #define LAMPE 0 ... PORTB |= 1 << LAMPE; //LAMPE ein PORTB &= ~(1 << LAMPE); //LAMPE aus oder, wenn das noch zu kompliziert ist: #define LAMPE 0 #define LAMPE_EIN PORTB |= 1 << LAMPE #define LAMPE_AUS PORTB &= ~(1 << LAMPE) ... LAMPE_EIN; //LAMPE ein LAMPE_AUS; //LAMPE aus
Die Lösung von Philipp hat aber den Vorteil, dass Hardwarefunktionen von der Software komplett getrennt werden. Das erhöht die Portabilität enorm. In der Regel wird hier auch gleich eine Trennung in HAL (Hardware Abstraction Layer) und Andwendungslayer gemacht. Somit muss bei einem Prozessorwechsel nur noch die HAL angepasst werden, die Anwendung an sich ist dann so Plattformunabhängig, dass nichts mehr daran getan werden muss. Inwieweit das natürlich im Hobbybereich notwendig ist, sei dahingestellt. Weiterer Vorteil ist aber auch, dass man die HAL als Bibliothek einbinden kann und sich somit bei jeden neuen Projekt für diesen Controller rein um die Anwendung kümmern kann.
aha, interessant. gibt es für diese art irgendwo beispiele? mit dem beispiel von philipp habe ich noch irgend ein problem, es will grad nicht so recht... merci
Wenn man alles mit HAL macht, kann man auch gleich Windows nehmen. Dann braucht man halt 2GHz nur damit der Mauszeiger ruckelfrei läuft. HAL macht eigentlich nur Sinn, wenn man weiß dass die Software auf verschiedenen Systemen laufen soll. Ansonsten tun es defines auf jedenfall auch, und sind vermutlich um den Faktor 10 schneller.
Ich hab das spasseshalber mal für ein Projekt (zumindest Ansatzweise) umgesetzt: hal.c:
1 | #include "hal.h" |
2 | |
3 | void initPort(uint8_t port, uint8_t direction) |
4 | {
|
5 | switch(port) |
6 | {
|
7 | case 'a': |
8 | DDRA = direction; |
9 | break; |
10 | |
11 | case 'b': |
12 | DDRB = direction; |
13 | break; |
14 | |
15 | case 'c': |
16 | DDRC = direction; |
17 | break; |
18 | |
19 | case 'd': |
20 | DDRD = direction; |
21 | break; |
22 | }
|
23 | }
|
hal.h:
1 | #include <inttypes.h> |
2 | #include <avr/io.h> |
3 | #include "lcd.h" |
4 | |
5 | void initPort(uint8_t port, uint8_t direction); |
6 | void setPort(uint8_t port, uint8_t value); |
Die hal.h macht man dann der Anwendung bekannt. Dinge, die die Anwendung nicht kennen darf, packt man in ne separate Header, die man auch in der hal.c einbindet (z.B. darf das Definitionsfile für den Controller, z.B. m8def.in, nur der HAL bekannt sein, da ansonsten die Anwendung wieder direkten Zugriff auf die Hardware bekommt.). Das verlangt natürlich eine gewisse Disziplin, das durchzuhalten. Und wie gesagt, ob das im Hobbybereich Sinn macht, sei dahingestellt. Auf den ersten Blick sieht es deutlich nach Mehraufwand auf, aber spätestens beim 2. Projekt amortisiert sich das dann wieder. Man kann diese Trennung auch mal mit einem Betriebssystem vergleichen. Dieses lässt auch keine direkten Zugriffe auf die Hardware zu, sondern kapselt jeglichen Zugriff (sofern überhaupt möglich) in Funktionen, die gleich noch Kontrollfunktion haben. Somit kann man schon im Vorfeld falsche Parameter filtern. Na ja, genug geredet. Falls du noch mehr Infos dazu willst, kannst du ja schreiben. Gruß, ERDI - Soft.
> #define LAMPE 1 > > void SetPin(int PORT,int PIN,int VALUE) > { < if(VALUE) > PORT |= _BV(PIN); > else > PORT &= ~_BV(PIN); > } Das wird so mit Sicherheit nichts. Mit C-Funktionen hast du da keine Chance, da der Compiler das was wie eine Zuweisung aussieht: PORTA = 5; völlig anders behandeln muss, wie eine normale Zuweisung: int i; i = 5; Innerhalb der Funktion, ist diese Unterscheidung aber nicht mehr feststellbar. Wenn man sowas machen will, dann geht der Weg nur über Makros.
HAL heißt nicht, mit Kanonen auf Spatzen schießen zu müssen. Es heißt nur, die Zugriffe formal zu kapseln. Rein syntaktisch besteht zwischen Funktionen und Macros eh kein Unterschied. Es ist also völlig wurst, ob ein Macro zu einem Funtionsaufruf expandiert oder den Befehl direkt ausführt. Eine effiziente Möglichkeit ist das hier: http://www.mikrocontroller.net/forum/read-1-368567.html#368661 Peter
Karl Heinz hat recht mit seiner Anmerkung; Ports als Funktionsparameter funktionieren so nicht; das ist ausführlich abgehandelt im "avr-libc Reference Manual" (Abschnitt "How do I pass an IO port as a parameter to a function"), die u.a. im WinAVR enthalten ist.
> Also mit einer Funktion würd ich da gar nix machen. Die verbraucht > Speicher und Rechenleistung bzw. Rechenzeit des µC. Eine inline-Funktion ist im schlechtesten Fall genauso schnell, wie ein Makro.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.