#include #include #include void setup_clock() { CLKPR |= (1UL << CLKPCE); //enable setting of prescaler. CLKPR &= ~(15 << CLKPS0); //set prescaler to 1, system clock 8MHz. } void setup_adc() { //enable interrupts sei(); // setup external reference voltage. ADMUX &= ~(3UL << REFS0); ADMUX |= (1UL << REFS0); // set left adjusted ADC result so we can easily only use the upper 8 bits of the result ADCSRB |= (1UL << ADLAR); // enable ADC interrupt ADCSRA |= (1UL << ADIE); } void setup_timers() { //Set channel A to inverted mode TCCR0A &= ~(3UL << COM0A0); TCCR0A |= (2UL << COM0A0); //Set channel B to inverted mode TCCR0A &= ~(3UL << COM0B0); TCCR0A |= (2UL << COM0B0); //Set Fast PWM mode //TCCR0A &= ~(3UL << WGM00); TCCR0A |= (3UL << WGM00); TCCR0B &= ~(1UL << WGM02); //TCCR0B |= (1UL << WGM02); //TCCR0B &= ~(3UL << FOC0B); TCCR0B &= ~(7UL << CS00); TCCR0B |= (1UL << CS00); DDRA |= (1UL << PA7); DDRB |= (1UL << PB2); } void enable_ADC() { PRR &= ~(1UL << PRADC); ADCSRA |= (1UL << ADEN); } void disable_ADC() { ADCSRA &= ~(1UL << ADEN); PRR |= (1UL << PRADC); } void select_ADC_channel(int channel) { ADMUX &= ~(7UL << MUX0); ADMUX |= (channel << MUX0); } uint8_t get_ADC_result() { uint8_t result = ADCL; //conversion would be blocked if we don't also read ADCH although we won't use the upper 2 bits. uint8_t unused = ADCH; (void)unused; return result; } void start_ADC() { ADCSRA |= (1UL << ADSC); } volatile uint8_t fan1; volatile uint8_t fan2; void start_polling_fans() { PRR &= ~(1UL << PRADC); enable_ADC(); select_ADC_channel(ADC1D); start_ADC(); } ISR(ADC_vect) { if(((ADMUX & (7UL << MUX0) >> MUX0)) == ADC1D) { fan1 = get_ADC_result(); select_ADC_channel(ADC2D); start_ADC(); return; } if(((ADMUX & (7UL << MUX0) >> MUX0)) == ADC2D) { fan2 = get_ADC_result(); disable_ADC(); return; } } volatile int b = 0; int main() { setup_clock(); setup_adc(); setup_timers(); OCR0A = 0x80; OCR0B = 0xB0; while(1) { b+=1; } }