Die Informationen von Rubber Duck sind korrekt, aber unvollständig.
Ich benötige eine große Menge an digitalem PWM-Ausgang für die Steuerung von Hobbyzügen.
Also habe ich 4 x 74HC595 an mein At Mega angeschlossen, das über 0,5 ms mit einem 2-kHz-Bitmuster gespeist werden muss. unterbricht.
Meine serielle Verschiebungsfunktion, die 32 Bit in die Register verschiebt, benötigt 562 us pro Zyklus. Unmöglich.
Ich habe eine optimierte Version von digitalWrite und Read erstellt, für die wir 328 benötigen. Jetzt ist es möglich, mit 2 kHz zu PWM. Der Trick ist, dass meine optimierte Funktion die letzten 2 Pins einschließlich ihrer Bitmasken und Outports speichert; und ich überspringe die Timer-Prüfung. Es ist threadsicher. Für ein einzelnes digitalWrite dauert dies etwas länger. Durch wiederholtes Schreiben auf Datapin und Clockpin wird der Standard Arduino digitalWrite um ca. 42% verbessert.
Übrigens: Mit der digitalWriteFast-Bibliothek ergibt sich ein Ergebnis von 45,8 µs, eine wirklich enorme Verbesserung. Diese Bibliothek verarbeitet jedoch nur Schreibvorgänge, wenn die PIN-Nummer zur Kompilierungszeit bekannt (und damit fest!) Ist. Dies ist bei meiner LiquidCrystal-Bibliothek nicht der Fall, bei der entweder 4 oder 8 Bits parallel über 4 aufeinanderfolgende Pins in die Abschirmung geschrieben werden.
Ich habe mein optimiertes digitalWrite nur für meine Anwendung einschließlich LiquidDisplay verwendet, als ich die Bibliothek C: \ Users \ Dell \ Downloads \ arduino-1.8.5 \ hardware \ arduino \ avr \ cores \ arduino in einen Unterordner im Ordner von my kopiert habe Anwendung, genannt
C: \ Benutzer \ Dell \ Google Drive \… \… .. \ AppFolder \ Bibliotheken .
Als ich in beiden Ordnern die Datei wiring_digital.c durch meine optimierte Version ersetzte , funktionierte es.
Ich konnte es nicht zum Laufen bringen, als ich nur die Datei wiring_digital.c in der Arduino-Bibliothek ersetzte (der LiquidCrystal übernahm die Standardfunktion woanders).
Das Hinzufügen von nur wiring_digital.c im Unterordner meiner Anwendung führte zu einer Vielzahl von Verknüpfungsfehlern.
Daher habe ich den gesamten Arduino-Ordner (der nicht so groß ist) in meinen Unterordner in der Anwendung kopiert und er kann problemlos kompiliert werden. Keine sehr elegante Lösung, da die gesamte Bibliothek repliziert wird. Aber es funktioniert.
Schlussfolgerung zum Überschreiben einer Arduino-Kernfunktion:
• Fügen Sie Ihre geänderten Funktionen (.c und / oder .h) in die Arduino-Bibliothek ein und kopieren Sie diese Bibliothek vollständig in den Unterordner "Bibliotheken" in Ihrem Anwendungsordner. Dann verwenden auch alle anderen Bibliotheken Ihre eigene geänderte Funktion.
Fazit Leistung digitalWrite in einer echten 32-Bit-Serienverschiebung:
• Ein optimiertes generisches digitalWrite und Read übertrifft das Standardmodell mit 42% deutlich, wenn 2 Pins wiederholt verwendet werden. • digitalWriteFast (mit bestimmten Pins zur Kompilierungszeit) übertrifft das Standard-digitalWrite in einer echten 32-Bit-Shift-Anwendung mit 92% (ist 12,2-mal schneller).
Hoffe das hilft anderen Arduino Anwendern… ..
//**********************
void digitalWrite(uint8_t pin, uint8_t val)
//**********************
{
uint8_t
timer,
bit,
port;
volatile uint8_t *out; // volatile because bitmask may be changed by (higher) interrupt
uint8_t oldSREG;
static uint8_t pin1 = 0,
pin2 = 0;
static bool p1 = true; // boolean toggle memory
static uint8_t // Store 2 sets of port/out adresses static
// timer1, //now exclued. Safety threat?
bit1,
*out1,
// timer2,
bit2,
*out2;
oldSREG = SREG; // CLI for thread proof function
cli();
if ( (pin == pin1) || (pin == pin2) )
{
if (pin == pin1) //Compiler optimizes this excellent (see ASM listing)
{
if (val == LOW)
{
*out1 &= ~bit1;
} else
{
*out1 |= bit1;
}
}
else
if (pin == pin2)
{
if (val == LOW)
{
*out2 &= ~bit2;
} else
{
*out2 |= bit2;
}
}
SREG = oldSREG;
}
else //normal clumsy digitalWrite operation
{
SREG = oldSREG; //Enable interrupts again
timer = digitalPinToTimer(pin);
bit = digitalPinToBitMask(pin);
port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
// if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
if (p1) // Save this port, bit and out, also atomic
{
pin1 = pin;
bit1 = bit;
out1 = out; // save the pointer, not the value
}
else
{
pin2 = pin;
bit2 = bit;
out2 = out; // save the pointer, not the value
}
p1 = !p1;
SREG = oldSREG; //enable interrupts
}
}
//**********************
int digitalRead(uint8_t pin)
//**********************
{
uint8_t
oldSREG,
timer,
bit,
port;
static uint8_t pin1 = 0;
bool readBit;
static uint8_t // Store 2 sets of port/out adresses static
// timer1, //now exclued. Safety threat?
port1,
bit1;
oldSREG = SREG;
cli();
if (pin == pin1)
{
readBit = (*portInputRegister(port1) & bit1);
SREG = oldSREG;
return readBit;
}
else
{
SREG = oldSREG;
timer = digitalPinToTimer(pin);
bit = digitalPinToBitMask(pin);
port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
// if (timer != NOT_ON_TIMER) turnOffPWM(timer);
oldSREG = SREG;
cli();
pin1 = pin; //Atomic operation pin - bit combi must be correct
bit1 = bit;
port1 = port;
SREG = oldSREG;
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}
}