Пишу программу для считывания уровня напряжения с переменного резистора (от 0 до 5 В).
Микроконтроллер: ATmega16 работает на частоте 16МГц. Вход A0. Разрядность АЦП: 10бит. Считывание одинарное (но вызывается регулярно)
Программа работает, но при считывании уровня 0В выдает в ADCW не 0, а 15. При этом с верхним уровнем никаких проблем нет (1023).
Код программы ниже. Написано в WinAVR последней версии (на нижних версиях результат тот же).
Бьюсь неделю, не могу понять. Пробовал прошивать другой контроллер (8535) - результат тот же

Код
#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>
volatile unsigned int ADC_w = 0;
int
segment_decoder(int num, int point)
{
int result = 0x3F;
switch(num)
{
case 0: result = 0x3F;
break;
case 1: result = 0x06;
break;
case 2: result = 0x5B;
break;
case 3: result = 0x4F;
break;
case 4: result = 0x66;
break;
case 5: result = 0x6D;
break;
case 6: result = 0x7D;
break;
case 7: result = 0x07;
break;
case 8: result = 0x7F;
break;
case 9: result = 0x6F;
break;
default: result = 0x3F;
break;
}
if(point!=0)
{
result = (result | 0x80);
}
return result;
}
ISR(ADC_vect)
{
ADC_w = ADCW;//ADCL;
}
int main(void)
{
_delay_ms(2);
DDRA = 0x00;
DDRB = 0xFF;
DDRC = 0xFF;
DDRD = 0xFF;
PORTA= 0xFF;
PORTB= 0x00;
PORTC= 0x00;
PORTD= 0x00;
SREG |= _BV(7);
ADCSRA |= (1<<ADPS0);
ADCSRA |= (1<<ADPS1);
ADCSRA |= (1<<ADPS2);
ADMUX = 0x40;
ADCSRA |= (1 << ADATE);
ADCSRA |= (1<<ADIE);
ADCSRA |= (1<<ADEN);
sei();
while(1)
{
ADCSRA |= (1<<ADSC);
while(ADCSRA & 0x40)
{
PORTB = segment_decoder( (ADC_w/1000)%10, 0);
PORTD = 2;
_delay_us(10);
PORTD = 0;
PORTB = segment_decoder( (ADC_w/100)%10, 0);
PORTD = 4;
_delay_us(10);
PORTD = 0;
PORTB = segment_decoder( (ADC_w/10)%10, 1);
PORTD = 8;
_delay_us(10);
PORTD = 0;
PORTB = segment_decoder( ADC_w%10, 0);
PORTD = 16;
_delay_us(10);
}
};
return 0;
}
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>
volatile unsigned int ADC_w = 0;
int
segment_decoder(int num, int point)
{
int result = 0x3F;
switch(num)
{
case 0: result = 0x3F;
break;
case 1: result = 0x06;
break;
case 2: result = 0x5B;
break;
case 3: result = 0x4F;
break;
case 4: result = 0x66;
break;
case 5: result = 0x6D;
break;
case 6: result = 0x7D;
break;
case 7: result = 0x07;
break;
case 8: result = 0x7F;
break;
case 9: result = 0x6F;
break;
default: result = 0x3F;
break;
}
if(point!=0)
{
result = (result | 0x80);
}
return result;
}
ISR(ADC_vect)
{
ADC_w = ADCW;//ADCL;
}
int main(void)
{
_delay_ms(2);
DDRA = 0x00;
DDRB = 0xFF;
DDRC = 0xFF;
DDRD = 0xFF;
PORTA= 0xFF;
PORTB= 0x00;
PORTC= 0x00;
PORTD= 0x00;
SREG |= _BV(7);
ADCSRA |= (1<<ADPS0);
ADCSRA |= (1<<ADPS1);
ADCSRA |= (1<<ADPS2);
ADMUX = 0x40;
ADCSRA |= (1 << ADATE);
ADCSRA |= (1<<ADIE);
ADCSRA |= (1<<ADEN);
sei();
while(1)
{
ADCSRA |= (1<<ADSC);
while(ADCSRA & 0x40)
{
PORTB = segment_decoder( (ADC_w/1000)%10, 0);
PORTD = 2;
_delay_us(10);
PORTD = 0;
PORTB = segment_decoder( (ADC_w/100)%10, 0);
PORTD = 4;
_delay_us(10);
PORTD = 0;
PORTB = segment_decoder( (ADC_w/10)%10, 1);
PORTD = 8;
_delay_us(10);
PORTD = 0;
PORTB = segment_decoder( ADC_w%10, 0);
PORTD = 16;
_delay_us(10);
}
};
return 0;
}