Hardwarecounter für Frequenzmessung

... und hier ist mein Arduino-Frequenzmessgerät bis 6 MHz !

Es kann auch als Zeit-Messgerät zur Bestimmung von ausführungszeiten im us-Bereich genutzt werden.

// ______________________________________________________________________________________________
// ______________________________________________________________________________________________
//
//
// (C) Helmut Weber 2/2015
//
// Frequenzmessgerät 1kHz bis 6MHz
//
// Für Fortgeschrittene:
//
// An Pin 5 werden positive Pulse per Hardware gezählt
// Innerhalb einer vorgegebenen Zeit gezählte Pulse werden
// dann als Frequenz ausgegeben
// 
// ______________________________________________________________________________________________
// ______________________________________________________________________________________________




//                             Makros zum Setzen, Löschen / Testen von Bits
// ______________________________________________________________________________________________
// set bit
static inline void BIT_SET(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
static inline void BIT_SET(volatile uint8_t *target, uint8_t bit){
	*target |= (1<<bit);
};
 
// clear bit
static inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
static inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit){
	*target &= ~(1<<bit);
};

// test bit
static inline bool BIT_TEST(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
static inline bool BIT_TEST(volatile uint8_t *target, uint8_t bit){
	return(*target & (1<<bit));
};



unsigned int TIM16_ReadTCNT1( void )
{
unsigned char sreg;
unsigned int i;
/* Save global interrupt flag */
sreg = SREG;
/* Disable interrupts */
cli();
/* Read TCNT1 into i */
i = TCNT1;
/* Restore global interrupt flag */
SREG = sreg;
return i;
}

void TIM16_ClearTCNT1( void )
{
unsigned char sreg;
unsigned int i;
/* Save global interrupt flag */
sreg = SREG;
/* Disable interrupts */
cli();
/* Read TCNT1 into i */
TCNT1=0;;
/* Restore global interrupt flag */
SREG = sreg;
}




void setup() {
  Serial.begin(115200);
  pinMode(2,OUTPUT);
  
  
  // Timer 1 wird zum Zähler von Pulsen an Pin 5 (TO1)
  TCCR1A =0;
  TCCR1B =0; 
  TCCR1B |=( (1<<CS10) | (1<<CS11) | (1<<CS12)  );  // Counter: external clock rising edge 
  TCNT1 =0;
  

}


/*
// Messung von Befehlsausführungszeiten
void loop() {
unsigned long m;
unsigned int cnt, tim;
char buf[20];
unsigned long i;
  cnt=TIM16_ReadTCNT1();
  tim=1000000/cnt;
  Serial.println(cnt);
  Serial.print("pro loop: ");  
  sprintf(buf,"%d.%d us\n",tim/10,tim%10);
  Serial.print(buf);
  m=micros();
  m+=100000;                            // Messung für 100000us
  TIM16_ClearTCNT1(); 
  // Messung in 100 ms = 10000us
  // Die Pulse werden hier selbst erzeugt.
  while (micros()<m) {
    //BIT_SET(&PORTD,2);                  // 3.5us / loop
    //BIT_CLEAR(&PORTD,2);
    //    oder
    digitalWrite(2,HIGH);               // 13.5 us 
    digitalWrite(2,LOW); 
  }
  delay(100);
}
*/
// Messung von Frequenzen

unsigned int x=1;

void loop() {
unsigned long m;
unsigned int cnt, tim;
char buf[20];
unsigned long i;

  cnt=TIM16_ReadTCNT1();
  delay(100);
  dtostrf( (float)cnt/(float)x, 8,3,buf);
  Serial.print(buf); Serial.println(" kHz  ");  //Serial.print(cnt); Serial.print("  "); Serial.println(x);
  if (cnt<3000)   { if (x<1000) x*=10; }
  if (cnt>30000) { if (x>1) x/=10; }
  m=micros();
  
  if(TIFR1&(1<<TOV1)) { if (x>1) x/=10; TIFR1 |= (1<<TOV1); }
  // 100KHz -6MHz
  //m+=10000;
 
 m+=(unsigned long)x*(unsigned long)1000; 
  
  TIM16_ClearTCNT1(); 
  // Messung in 100 ms = 10000us
  // Die Pulse werden hier selbst erzeugt.
  while (micros()<m) {
  }
}