Страница 1 из 2
Помогите чайнику с АЦП на avr
Добавлено: Ср янв 22, 2014 19:36:03
dictor
Ребятки, хочу сделать цифровой вольтметр со статической индикацией, на atmega8.
порты D b B использую для вывода на 7сегментники значение целой и дробной части напряжения, мне этого достаточно.
Но вот что то я делаю нетак, потому что рисовать он не хочет, показывает нули.
Видимо что то не правильно в функции обработки ацп, потому что если в программу с момента расчета напряжения присвоить константу, т.е. переменной u, то считает и показывает все правильно.
Вот собственно код программы:
Код: Выделить всё
#include <avr/io.h>
#include <util/delay.h>
DDRB=0b11111111;
DDRD=0b11111111;
char mas[10]={63,6,91,79,102,109,125,7,127,111};// массив кодов соответствующих цифрам на 7-ми сегментном индикаторе
unsigned int u;
float napr;
unsigned char seg1;
unsigned char seg2;
void ADC_init()
{
ADMUX = 0b11100000;//Использование внутреннего ИОНа, ADLAR=1(8 старших битов пишутся в ADCH)
ADCSRA=0b10001011;//АЦП включен,прерывание ацп разрешены, тактовая частота -/8
}
unsigned int ADC_result(void)
{
_delay_us(10);//задержка для стабилизации входного напряжения
ADCSRA|=0x40;//начинаем преобразование (ADSC = 1)
while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
ADCSRA|=0x10;//устанавливаем ADIF
return ADCH;// ADCH содержит значение старших 8 битов значения АЦП
}
void main (void)
{
while (1)
{
u=ADC_result;
napr=u*0,01;// Напряжение вычисляется из кода АЦП в его реальное значение
seg1=napr; //т.к. seg1- пренадлежит к типу char - отбрасывается дробная часть
seg2=((napr-seg1)*10);// Считается значение десятых долей напряжения
PORTB=mas[seg1]; //вывод целой части значения напряжения
PORTD=mas[seg2]; //вывод значения дробной части
}
}
Re: Помогите чайнику с АЦП на avr
Добавлено: Ср янв 22, 2014 20:12:23
pyzhman
Приведите в порядок типы переменных.
Re: Помогите чайнику с АЦП на avr
Добавлено: Ср янв 22, 2014 20:33:28
dictor
pyzhman писал(а):Приведите в порядок типы переменных.
а что собственно с ними нетак?
Re: Помогите чайнику с АЦП на avr
Добавлено: Ср янв 22, 2014 21:10:53
ploop
В упор не вижу, где у вас вызывается ADC_init()
И прекратите использовать магические числа, типа ADMUX = 0b11100000. Все биты именованы, и, как правило, их имена совпадают с даташитовскими.
Пример:
Код: Выделить всё
ADCSRA =
_BV(ADEN) | // Включить АЦП
_BV(ADIE) | // Разрешить прерывание
_BV(ADSC) | // Запустить первое преобразование
_BV(ADATE); // Автопреобразование
И без комментариев код читается, если чтец хоть раз в даташит заглядывал.
Re: Помогите чайнику с АЦП на avr
Добавлено: Ср янв 22, 2014 21:45:15
dictor
ploop писал(а):В упор не вижу, где у вас вызывается ADC_init()
точно, а где её нужно вызывать, в начале функции main?
Re: Помогите чайнику с АЦП на avr
Добавлено: Ср янв 22, 2014 22:38:59
ploop
Там, где нужно инициализировать АЦП

У вас - перед бесконечным циклом.
Кстати, u=ADC_result; не скомпилится. Надо u=ADC_result();

Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 00:33:33
dictor
Вот, постарался учесть все замечания, все равно - не пашет((
Код: Выделить всё
#include <avr/io.h>
#include <util/delay.h>
char mas[10]={63,6,91,79,102,109,125,7,127,111};// массив кодов соответствующих цифрам на 7-ми сегментном индикаторе
unsigned int u;
float napr;
unsigned char seg1;
unsigned char seg2;
void ADC_init()
{
ADMUX|=(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3)|(1<<REFS1)|(1<<REFS0)|(1<<ADLAR);//Использование внутреннего ИОНа, ADLAR=1(8 старших битов пишутся в ADCH)
ADCSRA|=(1<<ADEN)|(1<<ADIE)|(3<<ADPS0);//АЦП включен,прерывание ацп разрешены, тактовая частота -/8
}
unsigned int ADC_result(void)
{
_delay_us(10);//задержка для стабилизации входного напряжения
ADCSRA|=0x40;//начинаем преобразование (ADSC = 1)
while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
ADCSRA|=0x10;//устанавливаем ADIF
return ADCH;// ADCH содержит значение старших 8 битов
}
void main (void)
{
DDRB=0b11111111;
DDRD=0b11111111;
ADC_init();
while (1)
{
u=ADC_result();
napr=u*0,01;// Напряжение вычисляется из кода АЦП в его реальное значение
seg1=napr; //т.к. seg1- пренадлежит к типу char - отбрасывается дробная часть
seg2=((napr-seg1)*10);// Считается значение десятых долей напряжения
PORTB=mas[seg1]; //вывод целой части значения напряжения
PORTD=mas[seg2]; //вывод значения дробной части
}
}
И вот так код выглядит значительно лучше.
ploop
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 00:38:10
ploop
Проверьте ADCSRA: (пишу по памяти)
ADIE - включает прерывания. У вас не используются. Не нужно значит
АЦП у вас включается, но не запускается преобразование. Как минимум его нужно запустить, установив бит ADSC, а чтобы сам на автомате крутился - ещё ADATE.
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 04:15:37
dictor
Бит ADSC устанавливается в функции ADC_result
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:15:18
dictor
Эхххх...
Решил я воспользоваться генератором начального кода в Codevisionavr.
вот что получилось:
Код: Выделить всё
char mas[10]={63,6,91,79,102,109,125,7,127,111};
unsigned int u;
float napr;
unsigned char seg1;
unsigned char seg2;
unsigned char read_adc(void)
{
delay_us(10);
ADCSRA|=0x40;
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}
void main(void)
{
PORTB=0x00;
DDRB=0xFF;
PORTD=0x00;
DDRD=0xFF;
ADMUX=0xE0;
ADCSRA=0x83;
while (1)
{
u=read_adc();
napr=u*0.01;
seg1=napr;
seg2=((napr-seg1)*10);
PORTB=mas[seg1];
PORTD=mas[seg2];
}
}
но вот теперь я столкнулся с другой проблемой - ацп работает только когда напряжение меньше 0,5 вольта, а при значениях более 0,5 - показывает все равно 0,5
вот как это выглядит:

Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:21:18
pyzhman
Приведите переменные в порядок. По-русски говоря, используйте одного типа. Выкиньте вещественную - нафига она не нужна.
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:22:40
Engineer_Keen
Еще это похоже на зашкал. Для начала AVCC запитать, и ведь наверняка протеус на это ругается.
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:28:24
dictor
Engineer_Keen писал(а):Еще это похоже на зашкал. Для начала AVCC запитать, и ведь наверняка протеус на это ругается.
А чем запитать AVCC? напряжением питания?
О великий!!!
Честь тебе и хвала!
Все заработало!
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:31:10
dictor
pyzhman писал(а):Приведите переменные в порядок. По-русски говоря, используйте одного типа. Выкиньте вещественную - нафига она не нужна.
Сделал так:
Код: Выделить всё
while (1)
{
napr=read_adc()*0.01; // Напряжение вычисляется из кода АЦП в его реальное значение
seg1=napr; //т.к. seg1- пренадлежит к типу char - отбрасывается дробная часть
seg2=((napr-seg1)*10); // Считается значение десятых долей напряжения
PORTB=mas[seg1]; //вывод целой части значения напряжения
PORTD=mas[seg2];
}
}
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:31:55
Engineer_Keen
Для симулятора да, питание подвести +5V или VCC. В реальности можно между ними еще фильтр поставить.
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:34:01
dictor
Engineer_Keen писал(а):Для симулятора да, питание подвести +5V или VCC. В реальности можно между ними еще фильтр поставить.
А в реальной схеме?
И ещё вопрос, если брать за опорное питание напряжение AVCC, то к AREF какой конд цеплять, и куда его второй конец вести?
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 16:40:36
Engineer_Keen
Как делать в реальной схеме написано в даташите (там простая LC-цепочка), но для простых показометров достаточно просто соединить VCC и AVCC как в симуляторе, а вместо фильтра просто усреднять значения программно.
Re: Помогите чайнику с АЦП на avr
Добавлено: Чт янв 23, 2014 17:02:55
dictor
Спасибо всем за поддержку и помощь, без вас бы я ещё год над этиммяукал

Re: Помогите чайнику с АЦП на avr
Добавлено: Пт янв 24, 2014 19:48:50
dictor
Мдаа...
Собрал я схему в железе, а оно чего то гонит снова...
Цифры не отображаются на индикаторах вообще адекватно.
Просто разом мерцают все сегменты индикатора, то ярче, то тусклее, причем при подаче сигнала на ацп изменяется характер мерцаний, но они все равно незакономерны, горя все сегменты, просто с разной яркрстью...
Что бы это могло быть?
Re: Помогите чайнику с АЦП на avr
Добавлено: Сб янв 25, 2014 04:26:08
titoFF
Може данные слишком часто обновляются, цифры меняются часто, а глаз неуспевает...