PORTs in Array

Gast #5533212
Lesenswert?

Moin,
ich bin momentan dabei einen älteren Code zu kürzen.
in einem Array stehen momentan Zahlenwerte für die Portbezeichnungen und 
die Pins also für PA2 würde drin stehen:

uint8_t pinPorts[100][2] = {{(0),(1<<PA2)}, ...}

Das Ganze dann für alle Pins des atmega2560.

Ausgewertet wird das dann über nen Switch case der für jeden Port einen 
case hat und je nach Port den zugehörigen Pin ein oder ausschaltet.


So nun die Frage, kann ich die Ports irgendwie in einem Array definieren 
um die Switch case loszuwerden?

Ich hätte gerne einen Array Ports[] = {PORTA, PORTB}
Und einen Array Pins[] = {(1<<PA2), (1<<PA1)}

Damit ich dann
int i = 2;

Ports[i] |= Pins[i];

Nutzen kann anstatt 11 cases zu haben.


Viele Grüße Hannes
Gast #5533676
Lesenswert?

Moin,
Sprache ist C

Es geht ja nicht um eine Anfangsdefinition die geschieht durch feste 
Makros. Im späteren Verlauf hängt das ein oder ausschalten aber in einem 
interrupt der möglichst kurz sein sollte. Daher würde ich mir gerne die 
beiden Switch case sparen und eine einfache Alternative haben.

Viele Grüße
Hannes
#5533756
Lesenswert?

Hannes schrieb:
> Ich hätte gerne einen Array Ports[] = {PORTA, PORTB}
> Und einen Array Pins[] = {(1<<PA2), (1<<PA1)}
>
> Damit ich dann
> int i = 2;
>
> Ports[i] |= Pins[i];
>
> Nutzen kann anstatt 11 cases zu haben.

Hast du doch, also mach doch, musst halt deie Array für alle 100 i 
auffüllen.

Ports[] = {PORTA, PORTA, PORTA, .. PORTA, PORTB ..}
Pins[] = {(1<<PA0), (1<<PA1), (1<<PA2)... , (1<<PA7), (1<<PB0)...}

Allerdings kannst du mit dem code gerade mal einen Ausgang setzen 
(high).

Für das Rücksetzen (low) und für das Einlesen (input) brauchst du 
anderen code, der aber auf denselben Arrays aufsetzen kann.

Schau dir mal den source code an, wie der Arduino digitalWrite und 
digitalRead macht.

Allerdings hat der genau so wie dein Code das Problem, das setzen von 
mehreren Pins (8 Datenleitungen zum LCD..) zu immensem Laufzeitaufwand 
aufzublähen.
Moderator Persönliche Seite #5533757
Lesenswert?

Hannes schrieb:
> Daher würde ich mir gerne die beiden Switch case sparen und eine
> einfache Alternative haben.

Case-Switches können sehr kurz sein, nämlich lediglich aus einer 
Sprungtabelle bestehen. Das kannst Du kaum noch toppen. Schau Dir mal 
den erzeugten Assembler-Output an.

Im Zweifelsfall setzt Du in der ISR nur ein Flag und machst Deinen 
Switch in der Hauptschleife.
#5533773
Lesenswert?

Hannes schrieb:
> Im späteren Verlauf hängt das ein oder ausschalten aber in einem
> interrupt der möglichst kurz sein sollte.

Du willst also einem Interrupt Pins übergeben, die zur Compilezeit noch 
nicht bekannt sind.
Dann nimm einfach das Arduino Framework, da ist sowas schon dabei.
Allerdings ist das eben deutlich langsamer als ein direkter Pinzugriff, 
wenn man ihn schon zur Compilezeit festlegen kann.

Man darf switch/case aber auch nicht unterschätzen. Wenn es nur wenige 
Pins sind, z.B. 20, dann wird ein switch/case durchaus schneller sein, 
als erstmal ewig mit Pointern zu jonglieren. Ein Interrupt muß 
zusätzlich den Mehrverbrauch an Registern für die Pointerrechnungen 
sichern und restoren.
Gast #5533781
Lesenswert?

Mein interrupt prüft bei jedem Aufruf ob ein Pin verändert werden soll 
oder nicht. Somit sollte das Programm nicht ewig jonglieren sondern 
genau 2 arrays an einer Stelle bearbeiten.

Die Pins sind beim Compilen definiert aber an den Ausgängen hängen 
schrittmotoren/ Servos/ LEDs/ Sensoren etc. die durch i2c Kommunikation 
geändert werden.

Damit ich keinen allzu großen Delay erhalte, möchte ich die interrupt 
Zeit möglichst klein halten, da stört der Switch case immens. (Ca 7us 
mehr als direkte Anweisung)
#5533831
Lesenswert?

Hannes schrieb:
> Die Pins sind beim Compilen definiert aber an den Ausgängen hängen
> schrittmotoren/ Servos/ LEDs/ Sensoren etc. die durch i2c Kommunikation
> geändert werden.

Also quasi ein I2C-Portexpander.
Für Schrittmotoren würde ich entsprechend viele Instanzen von 
Schrittmotortreibern in einem Timerinterrupt aufsetzen.
Für Servos entsprechend viele Instanzen von PWMs, ebenfalls in einem 
Timerinterrupt.
Und jede Instanz greift direkt auf die benötigten Pins zu, indem man die 
Instanzen als Inline-Funktion definiert mit den Pins als Argument. Das 
dürfte bei 256kB Flash ja kein Problem sein.

Hannes schrieb:
> da stört der Switch case immens. (Ca 7us
> mehr als direkte Anweisung)

Das wären ja 112 Zyklen bei 16MHz, kommt mir reichlich viel vor.
Switch/case arbeitet mit binärer Suche, d.h. bei 86 aufeinanderfolgenden 
Cases ist es nach 7 Vergleichen am Ziel.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren