Guten Tag
Ich arbeite momentan mit WinAVR und einem ATXMEGA128A1, der ja
bekanntlich 78 IOs hat. Das Programm wird aber auch von Personen
bearbeitet, die zwar C programmieren können aber noch nie mit Atmel MyCs
gearbeitet haben, so dass ich mich wegen der Übersichtlichkeit frage ob
es eine Möglichkeit gibt Outputs quasi wie eine Variable anzusteuern, so
dass bsp. PINA1 mit "LED=1" angesteuert werden könnte. Die Input abfrage
lässt sich ja mit Define so abändern.
1
#define BIT_VALUE( PORT, BIT ) (( (PORT) & (1<<(BIT))) != 0 ) //macht aus dem Byte einzelne Bit
2
3
#define Taste (BIT_VALUE( PINA, PINA0 ))
4
5
voidmain(void)
6
{
7
if(Taste==1){
8
9
...
10
11
}
12
}
Hoffe ihr könnt mir helfen
Freundliche Grüsse
Mathiable
Mathiable schrieb:> Guten Tag>> Ich arbeite momentan mit WinAVR und einem ATXMEGA128A1, der ja> bekanntlich 78 IOs hat. Das Programm wird aber auch von Personen> bearbeitet, die zwar C programmieren können aber noch nie mit Atmel MyCs> gearbeitet haben, so dass ich mich wegen der Übersichtlichkeit frage ob> es eine Möglichkeit gibt Outputs quasi wie eine Variable anzusteuern, so> dass bsp. PINA1 mit "LED=1" angesteuert werden könnte.
Die Möglichkeit gibt es schon. Man kann sich natürlich eine struct
machen, in der mittels Bitfelder ein uint8_t auf 8 Bits aufgedröselt
wird und dann dem Compiler die ganze Maskierung überlassen.
Aber wenn deine Programmierer sowieso nicht so fit sind, ist es
fraglich, ob du dadurch nicht mehr Konfusion erzeugst als es gut ist.
Ich würde die PortPins, ähnlich wie du es bei der Abfrage gemacht hast,
in ein paar Makros verpacken, jeweils mit einem Set und Clear Makro.
Peter Dannegger schrieb:> Ja das geht sogar sehr gut.>> Man braucht dazu ein Macro. Dann kann man die Portpins wie Bitvariablen> ansprechen, also auf 0 oder 1 testen oder setzen.> Hier eine Beispiel:>> http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip>>> Peter
Sieht schon mal vielversprechend aus. Ich werde das mal genauer
studieren. Vielen Dank.
Peter schrieb:> Nicht super effizient, aber auch nicht so> schlimm wie es zunächst aussieht...
Ich habs mal compiliert.
Es ist wirklich doch so schlimm, wie es aussieht.
Das sind riesige Unterfunktionen und elend lange Listen von Argumenten
pro Aufruf:
1
set(AC230_ON_2,L);// drive output low
2
f2:82e3ldir24,0x32;50
3
f4:90e0ldir25,0x00;0
4
f6:61e3ldir22,0x31;49
5
f8:70e0ldir23,0x00;0
6
fa:40e3ldir20,0x30;48
7
fc:50e0ldir21,0x00;0
8
fe:20e8ldir18,0x80;128
9
100:00e0ldir16,0x00;0
10
102:0e943600call0x6c;0x6c<set>
Ich schätze mal, es ereicht die gleiche Langsamkeit bei 8MHz, wie die
Verwendung von Bitmacros bei 32kHz.
Peter
Peter Dannegger schrieb:> Ich habs mal compiliert.> Es ist wirklich doch so schlimm, wie es aussieht.
Möglicherweise würde es helfen, die Funktion als inline zu definieren.
Dann könnte der Optimizer das ganze überflüssige Zeug wegschmeissen.
Naja, Du übertreibst da etwas: 8 MHz / 32 kHz = 250000 ;o)
Und Flashspeicher ist bei einem ATXMEGA128A1 auch reichlich vorhanden!
Mir ist ein pflegeleichter und übersichtlicher Code lieber, auch wenn er
schlussendlich 20% grösser wird...
Man könnte das folgende auch in einem globalen Strukt defninieren, dann
müsste man der set/get Funktion nur noch einen Pointer übergeben
#define PORT_A &PORTA, &DDRA, &PINA
#define PORT_B &PORTB, &DDRB, &PINB
#define PORT_C &PORTC, &DDRC, &PINC
#define PORT_D &PORTD, &DDRD, &PIND
Habe hier zugegebenrmassen nicht gross Kopfzerbrechen bereitet!
Peter schrieb:> Naja, Du übertreibst da etwas: 8 MHz / 32 kHz = 250000 ;o)
8 MHz / 32 kHz = 250
> Mir ist ein pflegeleichter und übersichtlicher Code lieber
Ist wohl Geschmackssache.
Ich finde Variablenzugriffe deutlich besser lesbar als Funktionsaufrufe:
1
if(KEY0==KEY_PRESS)
2
LED0=LED_ON;
> auch wenn er> schlussendlich 20% grösser wird...
Der Aufruf kostet 10 Words, das ist das 10-fache eines SBI-Befehls, also
900% mehr.
Nur 20% mehr für das gesamte Programm dürfte daher kaum hinkommen.
Peter
Vielen Dank für die Antworten. Ich habe nun wie bei Peter Danneggers
Beispiel eine h File geschrieben mit diversen defines und kann nun
"LED=1;" schreiben und es fehlerfrei kompilieren. Ich habe die Hardware
noch nicht fertig, aber wenn noch Fehler auftreten werde ich mich wider
melden.
>eine h File geschrieben mit diversen defines und kann nun>"LED=1;" schreiben und es fehlerfrei kompilieren. Ich habe die Hardware>noch nicht fertig, aber wenn noch Fehler auftreten werde ich mich wider>melden.
Wäre schön wenn du mal ein Beispiel zeigen würdest.
Klaus Falser schrieb:> Möglicherweise würde es helfen, die Funktion als inline zu definieren.> Dann könnte der Optimizer das ganze überflüssige Zeug wegschmeissen.
Ja, mit "__attribute__ ((always_inline))" kommt sogar was brauchbares
raus.
Wie gesagt, es ist Geschmackssache, ob man diese Schreibweise mag.
Peter
Hi,
ich hab mir diesbezüglich auch mal was geschrieben. Wie das als ASM
ausschaut hab ich noch gar nie nachgeschaut. Ist aber eigentlich nur
Bitmanipulation. OK so super ist der Code noch nicht... muss da mal noch
etwas handanlegen und bitte nicht auf das miese Englisch achten. Sollte
wohl doch besser in deutsch Kommentieren ;-)
Möglicherweise hab ich mich an manchen Stellen etwas verkünstelt aber
ich kann noch nicht alle Kniffe beim Makros schreiben. Vielleicht habt
ihr mir da ja mal nen guten Link mit einer Übersicht.
Gruß
Stefan
Also, die Hardware ist nun erstellt und so wie ich es oben geschrieben
habe, funktioniert es nicht. Kenne mich auch überhaupt nicht mit Makros
aus. Was habe ich falsch gemacht?
Mathiable schrieb:> Also, die Hardware ist nun erstellt und so wie ich es oben geschrieben> habe, funktioniert es nicht. Kenne mich auch überhaupt nicht mit Makros> aus. Was habe ich falsch gemacht?
Frische Hardware?
Dann würde ich vorschlagen du benutzt erst mal die klassische,
konventionelle Methode, um zu sehen ob die Hardware korrekt
funktioniert, ehe du da anfängst zu künsteln.
Karl heinz Buchegger schrieb:> Frische Hardware?> Dann würde ich vorschlagen du benutzt erst mal die klassische,> konventionelle Methode, um zu sehen ob die Hardware korrekt> funktioniert, ehe du da anfängst zu künsteln.
War natürlich das erste was ich gemacht habe. Ohne einen vollständigen
Funktions- check, beginne ich erst gar nicht zu Programmieren.
Gut.
Bei Makros ist ein sinnvolles Vorgehen bei der expandierten Fassung
anzufangen.
Dein Programm sehe so aus
1
intmain()
2
{
3
DDRA=0xFF;
4
5
PORTA=(1<<PA0);
6
7
while(1)
8
;
9
}
Jetzt möchtest du den Port erst mal in die Struktur verpacken, so dass
du auf die Bits zugreifen kannst. Dazu musst du die Adresse von PORTA
auf einen entsprechenden Pointer auf die Struktur umcasten um dann über
diesen Pointer auf das entsprechende Member zuzugreifen.
Karl heinz Buchegger schrieb:> klappt das? (testen)>
Nein hat leider nicht geklappt. Kann es etwas damit zu tun haben, dass
es sich um einen XMEGA handelt? Der hat ja teilweise andere Syntax, z.B.
bei der IO Definierung.
Mathiable schrieb:> Karl heinz Buchegger schrieb:>> klappt das? (testen)>>>> Nein hat leider nicht geklappt. Kann es etwas damit zu tun haben, dass> es sich um einen XMEGA handelt?
Das kann durchaus sein.
Da müsste man jetzt mal nachgehen, wie PORTA definiert ist. Das wird ja
auch nur ein Makro sein, welches irgendwo in den Header Files residiert.
Nur der Vollständigkeit halber
(*(volatile struct bits*)&PORTA).b0 = 1;
wird auch nicht gehen, oder? (Ist aus C Sicht identisch zur ->
Schreibweise)
Karl heinz Buchegger schrieb:> Nur der Vollständigkeit halber>> (*(volatile struct bits*)&PORTA).b0 = 1;>> wird auch nicht gehen, oder? (Ist aus C Sicht identisch zur ->> Schreibweise)
Ok, hab’s rausgefunden. Anstelle von PORTA muss PORTA.OUT stehen, das
währe der XMEGA Syntax für die Port Ansteuerung. Funktioniert jetzt
einwandfrei. Vielen Dank.