Hi!
Nachdem ich letztens in Timing Probleme getaumelt bin, habe ich mal versucht schnelle Ein/Ausgaben zu basteln. digitalRead() und digitalWrite() waren deutlich zu langsam.
Getestet auf einem Standard 16MHz UNO.
Versuch 1 zeigte: 54 KHZ Rechteck maximal
void loop()
{
for(;;)
{
digitalWrite(13,!digitalRead(13));
}
}
Versuch 2 zeigte: 100 KHZ Rechteck maximal
void loop()
{
for(;;)
{
digitalWrite(13,1);
digitalWrite(13,0);
}
}
Das ist nicht die Welt!
Mit meinen neuen Pin Funktionen, 2 MHz Rechteck
void loop()
{
for(;;)
{
togglePin(LED);
}
}
Eine Steigerung um Faktor 20.
Die Pinbezeichnung orientiert sich hier nicht an der Arduino Pin Benennung, sondern an den AVR Datenblattangaben. Die jeweiligen Funktionen sind inline deklariert, und daran hält sich der Compiler. Auch wenn die Funktionen, mit ihren Parametern, fett aussehen, wird doch nur ein einziges Assembler Statement in den Code kompiliert. (Ausnahme: setInputPullup() wird zu 2 Statements)
Beispiel, Blink.ino:
#include "Pin.h"
// Standard LED auf dem UNO Board
#define LED PINDEF(B,5) //Pin13, PORTB Bit 5
void setup()
{
setOutput(LED);
}
void loop()
{
togglePin(LED);
delay(1000);
}
Zum Abschluss natürlich noch die Pin.h, mit ihrer ganzen "Magie":
#pragma once
#ifndef __AVR__
#error This FastPin Lib workls only with Atmel AVR
#endif
#ifndef ARDUINO
#include <avr/io.h>
#endif
#define PARAMETERLIST \
volatile __attribute__((unused)) uint8_t * DDR , \
volatile __attribute__((unused)) uint8_t * PORT, \
volatile __attribute__((unused)) uint8_t * PIN , \
uint8_t pin
/*
* Benutzung: Pin für die spätere Verwendung deklarieren
* #define BuildInLED PINDEF(B,5) // die LED auf einem Arduino UNO
*/
#define PINDEF(PORTNR,PINNR) &DDR##PORTNR,&PORT##PORTNR,&PIN##PORTNR,PINNR
static inline void setPin(PARAMETERLIST)
{
*PORT |= (1<<pin);
}
static inline bool getPin(PARAMETERLIST)
{
return (bool) *PIN & (1<<pin);
}
static inline void unsetPin(PARAMETERLIST)
{
*PORT &= ~(1<<pin);
}
static inline void togglePin(PARAMETERLIST)
{
*PIN = (1<<pin);
}
static inline void setOutput(PARAMETERLIST)
{
*DDR |= (1<<pin);
}
static inline void setInput(PARAMETERLIST)
{
*DDR &= ~(1<<pin);
}
static inline void setInputPullup(PARAMETERLIST)
{
*DDR &= ~(1<<pin);
*PORT |= (1<<pin);
}
viel Spaß damit