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
Die Definition von PORTA ist ungefähr:
1 | #define PORTA (*(volatile uint8_t *)(0x22))
|
Es ist möglich, Zeiger auf diese Ports zu definieren, aber du musst sie dann explizit dereferenzieren:
1 | volatile uint8_t *ports[] = { &PORTA, &PORTB }; |
2 | |
3 | *ports[i] = pins[i]; |
:
Bearbeitet durch User
Wozu möchte man sowas umständliches tun? Bei mir haben haben alle IO-Pins eine zur Laufzeit konstante Funktion, d.h. man kann sie schnell und codesparend bereits zur Compilezeit definieren, z.B.: Beitrag "Re: Codingstyle vs Makros"
Hannes schrieb: > So nun die Frage, kann ich die Ports irgendwie in einem Array definieren > um die Switch case loszuwerden? Dummer weise hast du vergessen, zu sagen, um welche Sprache es sich handelt. Eine C++ Lösung kann ich dir evtl anbieten....
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
Ich sehe keine switch case in deinem Code. Kann mir auch nicht vorstellen, wofür die gut sind....
Wenn du den Eingangstext gelesen hättest wüsstest du das welche existieren. Aber auch gerne nochmal als „Beweis“ Die Teile hinter |= wurden jetzt bereits mit einem anderen Vektor abgelöst. Ich wäre aber gerne die 11. cases los, dafür müsste ich die Ports in nen Vector bekommen.
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.
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.
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.
Hannes schrieb: > Wenn du den Eingangstext gelesen hättest wüsstest du das welche > existieren. Is klar.... Hannes schrieb: > Aber auch gerne nochmal als „Beweis“ Ich brauche keine Beweise/Bilder, du ... Sondern testbaren Code! Aber ich sehe schon, mit uns beiden wird das so nichts.
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)
Hannes schrieb: > Aber auch gerne nochmal als „Beweis“ Es war auch nicht die Frage, daß Dein Code so aussieht, sondern warum er unbedingt so aussehen muß. Warum darf erst im Interrupt entschieden werden, welcher von den 86 Pins gesetzt werden soll?
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.
Peter D. schrieb: > Switch/case arbeitet mit binärer Suche, d.h. Nicht unbedingt. Der gcc entscheidet selber, und in Abhängigkeit von Compileroptionen, wie er es tut. Da kann man schon die ein oder andere Überraschung erleiden.
Scroll nach oben. Deine Frage wird im dritten Post vollständig beantwortet.
:
Bearbeitet durch User
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.