单片机频率计代码,测量范围在10hz到4khz
时间: 2024-02-24 19:57:21 浏览: 24
以下是一个用于测量10Hz到4kHz范围内信号频率的单片机频率计的代码示例,使用的单片机为ATmega328P。
```c
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define SAMPLE_NUM 100
volatile uint16_t g_captured_value[SAMPLE_NUM];
volatile uint8_t g_captured_cnt = 0;
volatile uint8_t g_overflow_cnt = 0;
ISR(TIMER1_CAPT_vect)
{
g_captured_value[g_captured_cnt++] = ICR1;
if(g_captured_cnt >= SAMPLE_NUM)
{
TCCR1B &= ~(1 << CS10); // Disable Timer1
}
}
ISR(TIMER1_OVF_vect)
{
g_overflow_cnt++;
if(g_overflow_cnt >= 5)
{
TCCR1B &= ~(1 << CS10); // Disable Timer1
}
}
uint32_t GetFrequency(void)
{
uint32_t i;
uint32_t sum = 0;
uint32_t freq = 0;
uint32_t period[SAMPLE_NUM - 1];
for (i = 0; i < SAMPLE_NUM - 1; i++)
{
period[i] = g_captured_value[i + 1] - g_captured_value[i];
sum += period[i];
}
freq = 1000000 / (sum / (SAMPLE_NUM - 1));
return freq;
}
int main(void)
{
DDRB &= ~(1 << DDB0); // Set PB0 as input
PORTB |= (1 << PB0); // Enable pull-up resistor on PB0
TCCR1B |= (1 << ICES1); // Enable input capture on rising edge
TIMSK1 |= (1 << ICIE1) | (1 << TOIE1); // Enable input capture and overflow interrupts
sei(); // Enable global interrupts
while (1)
{
g_captured_cnt = 0;
g_overflow_cnt = 0;
TCCR1B |= (1 << CS10); // Enable Timer1 with no prescaler
while(g_captured_cnt < SAMPLE_NUM)
{
// Wait for input capture
}
uint32_t freq = GetFrequency();
printf("Frequency: %d Hz\r\n", freq);
}
}
```
这个代码使用了Timer1和PB0,通过PB0输入信号,Timer1的输入捕获模式来计算输入信号的频率。其中,通过捕获多个脉冲的时间来计算频率,可以提高测量精度。同时,通过在中断处理函数中禁止Timer1来控制测量时间,从而确保测量频率的范围在10Hz到4kHz之间。另外需要注意的是,这个代码使用了printf函数来输出测量结果,如果不需要可以自行修改。