DigitalRead() und DigitalWrite() sind mir zu langsam und habe nach Recherche einige interessante Seiten zur "direkten Port Manipulation" gefunden!
Ich habe ein Arduino Mega 2560 und würde gerne Pin 52 = PC1 (INPUT) lesen und den digitalen Zustand dieses Pins auf Pin 36 = PC1 (OUTPUT) schreiben.
Mit welchen Befehlen geht das lesen des Pins 52 und das schreiben des Zustands auf Pin 36?
Kann mir da jemand helfen, wie der Programmcode aussieht? Vielen Dank!
DANINO24:
Ich habe ein Arduino Mega 2560 und würde gerne Pin 52 = PC1 (INPUT) lesen und den digitalen Zustand dieses Pins auf Pin 36 = PC1 (OUTPUT) schreiben.
Mit welchen Befehlen geht das lesen des Pins 52 und das schreiben des Zustands auf Pin 36?
Kann mir da jemand helfen, wie der Programmcode aussieht? Vielen Dank!
Kleine Anmerkung: Pin 52 ist PCINT1/PB1 und nicht PC1.
Alsdann ist alles weitere ganz perfekt hier in einzelnen Schritten beschrieben:
(ganze Ports oder einzelne Port-Bits als Ausgang oder Eingang konfigurieren; bei Eingängen ggfs. die Pull-Up-Widerstände einschalten; Ports komplett setzen, Port komplett einlesen; Einzelbits setzen und lesen).
Wenn du danach glaubhaft machst, dass du dann noch Fragen hast (und welche) wird dir hier sicher weitergeholfen (versprochen!)
Diese Anmerkung nur deshalb, weil es meiner Meinung nach keinen Sinn macht, dir 5 oder 10 C-Anweisungen hinzuschreiben, wo dann die Erklärung, was da passiert, einen wesentlich größeren Umfang hat und es anderswo sowieso schon steht.
DigitalRead() und DigitalWrite() sind mir zu langsam
Wie schnell brauchst du denn ?
DigitalWrite und DigitalRead machen, wenn mit konstanten Pin-Nummern und Werten beauftragt, schon per Makro ziemlich "direkte Port-Manipulation".
Schau dir den Quellcode mal an. Da lernst du auch viel über "direct-port-manipulation".
Mein Tip, viel schneller wirst du womöglich nicht, aber evtl. kann dein Problem anders gelöst werden.
void loop()
{
// Lese Pin 52 und Schreibe den Wert nach Pin 36
PORTC = (PORTC & B11111101) | (PINB & B00000010);
}
Jetzt zum Hintergrund:
Ich habe als Input ein Taktsignal, das ca. 1,5 MHz schnell ist. Jetzt wollte ich schauen ob mein Arduino Board schnell genug ist dieses Signal zu verarbeiten. Sprich Taktsignal lesen und auf einen anderen Pin schreiben. Den Pin dann mit einem Oszilloskop betrachten und schauen, ob ich da auch 1,5 MHz erhalten.
Ich vermute mal das es knapp wird. Allerdings nicht wegen der Bitschieberei, die sollte schnell genug sein. Allerdings laufen außerhalb von loop() im eigentlich main() noch einige Serial-Event Abfragen die evtl. vom Compiler nicht wegoptimiert werden, jenachdem was sonst so im Sketch steht und damit wird dann Zeit zwischen den loop() Durchläufen verbraten.
Siehe main.cpp :
#include <Arduino.h>
int main(void)
{
init();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
unsigned long i;
unsigned long zeit;
void setup()
{
DDRB = DDRB & B11111101;
DDRC = DDRC | B00000010;
Serial.print("\nTeste 1000000x direct port mapping\n");
i = 0;
zeit = micros();
}
void loop()
{
if (i >= 1000000)
{
zeit = micros() - zeit;
Serial.print("Dauer: ");
Serial.print(zeit);
Serial.print(" Mikrosekunden = ");
Serial.print(zeit / 1000);
Serial.print(" Millisekunden\n");
while (1);
}
// Lese Pin 15 und Schreibe den Wert nach Pin 3
PORTC = (PORTC & B11111101) | (PINB & B00000010);
i++;
}
Wenn loop() immer wieder neu durchlaufen wird dauert es für 1 Million Lese/Schreib-Zugriffe 4904704 Mikrosekunden, also fast 5 Sekunden.
unsigned long i;
unsigned long zeit;
void setup()
{
DDRB = DDRB & B11111101;
DDRC = DDRC | B00000010;
}
void loop()
{
Serial.print("\nTeste 1000000x direct port mapping\n");
i = 0;
zeit = micros();
for (;;)
{
if (i >= 1000000)
{
zeit = micros() - zeit;
Serial.print("Dauer: ");
Serial.print(zeit);
Serial.print(" Mikrosekunden = ");
Serial.print(zeit / 1000);
Serial.print(" Millisekunden\n");
while (1);
}
// Lese Pin 15 und Schreibe den Wert nach Pin 3
PORTC = (PORTC & B11111101) | (PINB & B00000010);
i++;
}
}
Fast der gleiche Code, allerdings wird loop() nicht mehr verlassen, sondern eine eigene Endlosschleife verwendet.
Dauer für 1 Million Lese/Schreib-Zugriffe ist nun 1383620 Mikrosekunden, also knapp 1,4 Sekunden.
Danke für die tolle Hilfe. Leider ist mein Mega 2560 definitiv zu langsam!
Jetzt überlege ich das Arduino Due mit 84 MHz zu kaufen.
Gibt es hier auch Quellen für die "direkte Port Manipulation" bzw. kann ich das obere Programm leicht umschreiben, um es auf dem Due auszuführen?
Ich befürchte, da sieht es mit Informationen noch mau aus. Zumindest hier im Deutschen Teil hab ich noch nirgends gelesen, dass einer schon den Due hätte.
Rein theoretisch müsste es beim Due auch so gehen und der sollte nach den Spezifikationen mehr als schnell genug dafür sein.
Darf man fragen, was eigentlich das Ziel des Projektes ist? Weil nur das Signal durchschleifen macht ja nicht gerade viel Sinn.
DANINO24:
Danke für die tolle Hilfe. Leider ist mein Mega 2560 definitiv zu langsam!
Für mich erschließt sich noch nicht der Sinn der ganzen Aktion mit dem Lesen und Schreiben der Port-Bits. Geht es nur um das Prinzip, ob man ein 1,5 MHz-Eingangssignal mit einem mit 16 MHz betriebenen 8-Bit Mikrocontroller softwaremäßig verarbeiten kann oder steckt da noch etwas "sinnvolles" dahinter, was du uns noch nicht verraten hast (wobei natürlich auch der Lerneffekt und das Wissen sinnvoll sein kann)
Ich denke, auch wenn du einen schnelleren Controller verwendest und das Lesen und Schreiben der Port-Bits damit halbwegs funktionieren sollte, wirst du spätestens bei einer etwas umfangreicheren Verarbeitung des Eingangssignals an die Grenzen eines Mikrocontollers stoßen.
Das sollte dann meiner Meinung nach der Zeitpunkt sein, über das Konzept generell nachzudenken.
Ich sehe gerade, nachdem ich diesen Beitrag gepostet hatte, dass sich MaFu im Beitrag vorher die gleiche Frage gestellt hat