gpt4 book ai didi

c - 如何计算 ADC 读数的平均值?

转载 作者:行者123 更新时间:2023-12-04 00:20:45 25 4
gpt4 key购买 nike

目的是将最新的 10 个 ADC 读数存储在一个数组中,然后计算它们的平均值以供其他地方使用。每次更新时删除最旧的。

关于 LED 时序,如果 ADC 读数在下面写的边界内,它必须将时序从 1s 切换到 0.25s,如何正确实现?我知道我的方法有效,但可以做得更好。至于 LED,如果按下开关,它们必须改变模式,如您所见,它们确实如此,但我再次确信它可以通过另一种更简单的方式完成!

以下是我的代码,我也确信有很多错误和足够的优化空间,我很乐意接受它!

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

#include <avr/io.h>
#include <avr/interrupt.h>
unsigned int timecount0;


unsigned int adc_reading;

volatile uint32_t timing = 1;
volatile uint32_t accumulator = 0;
volatile uint16_t average = 0;
volatile uint16_t samples = 0;


#define LED_RED PORTB = ((PORTB & ~0b00001110)|(0b00000010 & 0b00001110))
#define LED_GREEN PORTB = ((PORTB & ~0b00001110)|(0b00001000 & 0b00001110))
#define LED_BLUE PORTB = ((PORTB & ~0b00001110)|(0b00000100 & 0b00001110))
#define LED_RGB PORTB = ((PORTB & ~0b00001110)|(0b00001000 & 0b00001110))

#define DELAY_COUNT 6

volatile uint8_t portdhistory = 0xFF;


void Timer0_init(void)
{
timecount0 = 0; // Initialize the overflow count. Note its scope
TCCR0B = (5<<CS00); // Set T0 Source = Clock (16MHz)/1024 and put Timer in Normal mode

TCCR0A = 0; // Not strictly necessary as these are the reset states but it's good
// practice to show what you're doing
TCNT0 = 61; // Recall: 256-61 = 195 & 195*64us = 12.48ms, approx 12.5ms
TIMSK0 = (1<<TOIE0); // Enable Timer 0 interrupt


PCICR |= (1<<PCIE0);
PCMSK0 |= (1<<PCINT0);
sei(); // Global interrupt enable (I=1)

}


void ADC_init(void)
{
ADMUX = ((1<<REFS0) | (0<<ADLAR) | (0<<MUX0)); /* AVCC selected for VREF,ADLAR set to 0, ADC0 as ADC input (A0) */
ADCSRA = ((1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(7<<ADPS0));
/* Enable ADC, Start Conversion, Auto Trigger enabled,
Interrupt enabled, Prescale = 32 */
ADCSRB = (0<<ADTS0); /* Select AutoTrigger Source to Free Running Mode
Strictly speaking - this is already 0, so we could omit the write to
ADCSRB, but included here so the intent is clear */
sei(); //global interrupt enable
}


int main(void)
{
ADC_init();
Timer0_init();


DDRD = 0b00100000; /* set PORTD bit 5 to output */
DDRB = 0b00111110; /* set PORTB bit 1,2,3,4,5 to output */


sei(); // Global interrupt enable (I=1)


while(1)
{
if(!(PIND & (1<<PIND2)))
{
PORTD = PORTD |= (1<<PORTD5);
PORTB = PORTB |= (1<<PORTB4);
if(average>512)
{
PORTB = PORTB |= (1<<PORTB5);
}

}
else
{

PORTD = PORTD &= ~(1<<PORTD5);
PORTB = PORTB &= ~(1<<PORTB4);
}




}

}

ISR(TIMER0_OVF_vect)
{

TCNT0 = 61; //TCNT0 needs to be set to the start point each time
++timecount0; // count the number of times the interrupt has been reached


if(!(PIND & (1<<PIND3)))
{

if (timecount0 >= 0) // 40 * 12.5ms = 500ms
{
PORTB = ((PORTB & ~0b00001110)|(0b00000000 & 0b00001110));
}

if (timecount0 >= 8*timing)
{
LED_RED;
}

if (timecount0 >= 16*timing)
{
LED_GREEN;
}

if (timecount0 >= 24*timing)
{
PORTB = ((PORTB & ~0b00001110)|(0b00000110 & 0b00001110));


}
if (timecount0 >= 32*timing)
{
PORTB = ((PORTB & ~0b00001110)|(0b00001000 & 0b00001110));


}
if (timecount0 >= 40*timing)
{
PORTB = ((PORTB & ~0b00001110)|(0b00001010 & 0b00001110));

}

if (timecount0 >= 48*timing)
{
PORTB = ((PORTB & ~0b00001110)|(0b00001100 & 0b00001110));



}

if (timecount0 >= 56*timing)
{
PORTB = ((PORTB & ~0b00001110)|(0b00001110 & 0b00001110));


}

if (timecount0 >= 64*timing)
{

timecount0 = 0;

}

}
else
{
if (timecount0 >= 0)
{

PORTB = ((PORTB & ~0b00001110)|(0b00000000 & 0b00001110)); //ALL OFF
}

if (timecount0 >= 8*timing)
{
LED_RED;
//PORTB = ((PORTB & ~0b00001110)|(0b00000010 & 0b00001110)); //RED
}

if (timecount0 >= 16*timing)
{
LED_GREEN;


}

if (timecount0 >= 24*timing)
{
LED_BLUE;



}
if (timecount0 >= 32*timing)
{

timecount0 = 0;

}
}

}

ISR (ADC_vect) //handles ADC interrupts

{

adc_reading = ADC; //ADC is in Free Running Mode
accumulator+= adc_reading;


if ((adc_reading > 768) & (adc_reading <= 1024))
{
timing = 10;

}

if ((adc_reading >= 0) & (adc_reading<= 768) )
{
timing = 2.5;

}


samples++;

if(samples == 10)
{
average = accumulator/10;
accumulator = 0;
samples = 0;
}


}




最佳答案

根据您的处理器,您可以保持 ISR() 的速度并避免昂贵的 /,%

LED 的东西,我会在定时器中断中处理。

#define N 10
volatile unsigned sample[N];
volatile unsigned count = 0;
volatile unsigned index = 0;
volatile unsigned sum = 0;

ISR (ADC_vect) {
if (count >= N) {
sum -= sample[index];
} else {
count++;
}
sample[index] = ADC;
sum += sample[index];
index++;
if (index >= N) {
index = 0;
}
}

unsigned ADC_GetAvg(void) {
block_interrupts();
unsigned s = sum;
unsigned n = count;
restore_interrupts();
if (n == 0) {
return 0; //ADC ISR never called
}
return (s + n/2)/n; // return rounded average
}

我推荐 low pass filter 的整数版本。比上一个 N 的平均值。

关于c - 如何计算 ADC 读数的平均值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60878795/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com