Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Mirko Pavleski
Published © GPL3+

Simple STM32 Frequency meter from 1Hz to 30 MHz-Arduino IDE

This frequency meter uses an inexpensive STM32 microcontroller, and the frequency range is from 0 to 30 MHz

BeginnerFull instructions provided1 hour4,337
Simple STM32 Frequency meter from 1Hz to 30 MHz-Arduino IDE

Things used in this project

Hardware components

STM32F103C6 or STM32F103C8
×1
8 Digit 7 Seg Display module
×1
Capacitor 100 nF
Capacitor 100 nF
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Schematic

...

Code

Arduino code

C/C++
...
#include <LedControl.h>//https://github.com/wayoda/LedControl/archive/master.zip  
     LedControl lc = LedControl(PB1,PB10,PB11,1);// DIN(PB1), CLK(PB10), CS(PB11)
 
     volatile int  mon_flag;
     unsigned long freq;
     byte fq[8],pd,x;
 
void setup() {
 Serial.begin(9600);
      lc.shutdown(0, false); 
      lc.setIntensity(0,8); // яркость 0-15
      lc.clearDisplay(0); 
    pinMode(PA15,INPUT_PULLDOWN); // вход частотомера
 
    RCC_BASE->APB1ENR|= (1<<2)|(1<<1)|(1<<0); //включить тактирование tim-2,3,4
    RCC_BASE->APB2ENR|= (1<<3)|(1<<11)|(1<<2)|(1<<0)|(1<<4);////включить тактирование port-a-b-c,tim1
    AFIO_BASE->MAPR=(1<<8)|(1<<6); //tim 1 && tim 2 Partial remap
}
 
void loop() {
 freq_meter();
 Serial.println(freq);
  fq[7]= freq/10000000%10;
  fq[6]= freq/1000000%10;
  fq[5]= freq/100000%10;
  fq[4]= freq/10000%10;
  fq[3]= freq/1000%10;
  fq[2]= freq/100%10;
  fq[1]= freq/10%10;
  fq[0]= freq%10%10;
 
  if(freq>=10000000){x=8;}
  if(freq<10000000){lc.setRow(0,7,0);x=7;}
  if(freq<1000000){lc.setRow(0,6,0);x=6;}
  if(freq<100000){lc.setRow(0,5,0);x=5;}
  if(freq<10000){lc.setRow(0,4,0);x=4;}
  if(freq<1000){lc.setRow(0,3,0);x=3;}
  if(freq<100){lc.setRow(0,2,0);x=2;}
  if(freq<10){lc.setRow(0,1,0);x=1;}
 
  for(int i = 0;i < x;i++){
  if(i==3){pd=true;}
  else if(i==6){pd=true;}
  else if(i==9){pd=true;}
  else{pd=false;}
  lc.setDigit(0,i,fq[i],pd);}
}
 
void freq_meter(){  // http://arduino.ru/forum/proekty/generator-s-reguliruemoei-chastotoi-na-arduino#comment-296530
   __asm volatile( "cpsid i" );
   /// Timer2 счёт младших 16 бит
    TIMER2_BASE->CR1=0;//стоп таймер
    TIMER2_BASE->CCER=0; TIMER2_BASE->PSC=0;  TIMER2_BASE->CNT=0; 
    TIMER2_BASE->CCR1=0; TIMER2_BASE->CCR2=0; TIMER2_BASE->CCR3=0; 
    TIMER2_BASE->CCR4=0;TIMER2_BASE->PSC=0;TIMER2_BASE->SR=0;
    TIMER2_BASE->CCMR2=0;
    TIMER2_BASE->CR2=1<<5; //MMS:010 управление подчинённым в режиме "Update" 
    TIMER2_BASE->SMCR= (1<<14);// ECE & TS:000  режим 2 внешнего тактирования & разрешение работы от таймера1
    TIMER2_BASE->ARR=65535; //считать до максимума
    TIMER2_BASE->EGR=1; //перечитать регистры.
    TIMER2_BASE->CR1|=(1<<0);//start timer2
   /// Timer3 счёт старших 16 бит
    TIMER3_BASE->CR1=1<<0;//стоп таймер
    TIMER3_BASE->CCER=0; TIMER3_BASE->PSC=0; TIMER3_BASE->CNT=0; 
    TIMER3_BASE->CCR1=0; TIMER3_BASE->CCR2=0; TIMER3_BASE->CCR3=0; 
    TIMER3_BASE->CCR4=0;TIMER3_BASE->PSC=0;TIMER3_BASE->SR=0;TIMER3_BASE->CR2=0;  
    TIMER3_BASE->CCMR1=0; 
    TIMER3_BASE->SMCR=(1<<2)|(1<<1)|(1<<0)|(1<<4);//SMS:111 && TS:001  такт брать от 2-го таймера  
    TIMER3_BASE->ARR=65535; //считать до 
    TIMER3_BASE->EGR=1; //перечитать регистры.
    TIMER3_BASE->CR1|=(1<<0);//start timer3
 /// настройка времени разрешения на таймере1 для таймера2
    TIMER1_BASE->CR1=(1<<3)|(1<<2);//один импульс, без прерываний
    TIMER1_BASE->CNT=0;
    TIMER1_BASE->CR2=(1<<4);  //MMS:001 сигнал разрешения работы другим таймерам
    TIMER1_BASE->CCER=0;// отключить выходы таймера на физ ноги
    TIMER1_BASE->PSC=F_CPU/36000 -1 ;// 1999; // 72000000/2000= 36000кГц тактовая таймера 
    TIMER1_BASE->ARR=35996;//считать до 36000 (1секунда) 
    TIMER1_BASE->EGR=1; //перечитать регистры.
    TIMER1_BASE->CR1|=(1<<0);
    __asm volatile( "cpsie i" );
    while (TIMER1_BASE->CR1&1) {asm volatile("nop"); if(mon_flag) {return;}  }
    freq = TIMER3_BASE->CNT<<16  | TIMER2_BASE->CNT ; 
}

Credits

Mirko Pavleski

Mirko Pavleski

153 projects • 1301 followers

Comments