Страница 2 из 2
Re: ATmega8 2 АЦП
Добавлено: Чт авг 02, 2012 10:22:11
Angmar
ILYAUL писал(а): -
Ошибка
Что пишет?
Хидеры "avr/io.h", "avr/iom8.h" и соответствующие им библиотеки присутствуют и целые?
Re: ATmega8 2 АЦП
Добавлено: Чт авг 02, 2012 12:04:26
siamds
Уважаемый shurikss123!
У меня появилось свободное время и если Вы желаете, я напишу для Вас программу обмена между ПК и МК. Напишите как можно подробней алгоритм работы устройства, которое Вы хотите контролировать, или контролировать и управлять.
Re: ATmega8 2 АЦП
Добавлено: Чт авг 02, 2012 17:44:37
shurikss123
Angmar писал(а):ILYAUL писал(а): -
Ошибка
Что пишет?
Хидеры "avr/io.h", "avr/iom8.h" и соответствующие им библиотеки присутствуют и целые?
Хидеры есть, компилятор по моему стежит
Re: ATmega8 2 АЦП
Добавлено: Пт янв 18, 2013 11:42:50
Bringer
Попробовал прошивку ADC_Mega8.rar [158.87 KiB] на макетной плате.
пошла когда строку
register static unsigned char input_index=0;
заменил на
static unsigned char input_index=0;
использовал CodeVisionAVR C Compiler v: 2.05.03
Re: ATmega8 2 АЦП
Добавлено: Сб июн 08, 2013 19:26:45
ZiperRUS
Здравствуйте велекодушно
Скачал проект написанный
siamds всё работает и то что мне как раз нужно.))))
только непонятно мне как работает функция PripareData(CARDINAL Data) в этом проекте.
void PrepareData(CARDINAL Data)
{
BYTE i;
for(i=0; i<6; i++)
{
byDisplay[5-i] = Data % 10 + 48;
Data /= 10;
}
}
я так понимаю она принимает параметр значени от 0 до 1024 результат преобразования АЦП и заполняет буфер который потом выводиться на экран. непоминаю как работают выделенные строчки в ней

кто знает разьесните поподробней пожалуйста так как планирую се такой измеритель спаять в блок питания и переделать переписать код под себя хочу очень даже сильно. ( не то чтоб уж так прям наглухо сильно , просто охото сильно знать принцип работы так как столнулся с ютим впервые за свои 28 лет жизни на плянете земля)
Зарание велекодушно благодарю.
проект прилогаю
Re: ATmega8 2 АЦП
Добавлено: Пн июн 10, 2013 12:57:28
ibiza11
byDisplay[5-i] = Data % 10 + 48;
эта строчка находит остаток от деления Data на 10, прибавляет к ней 0х30 и помещает результат в массив byDisplay[](Посмотрите таблицу знакогенератора дисплея. Код знака "0" соответствует числу 0х30)
после этой строчки содержимое Data не изменится.
Data /= 10;
а эта строчка уже делит содержимое Data на 10, после нее в Data будет лежать целочисленный результат деления Data на 10.
В итоге этот код в цикле заполняет массив byDisplay[] КОДАМИ цифр выводящихся на дисплей. В ячейках с меньшим индексом будут находится коды цифр старших знакомест.
Соответственно, если вывести на дисплей в таком порядке : byDisplay[0], byDisplay[1], byDisplay[2], byDisplay[3], byDisplay[4], byDisplay[5] - то на дисплее получим число, соответствующее значению переменной Data.
Re: ATmega8 2 АЦП
Добавлено: Ср дек 11, 2013 15:49:06
pobeda
подскажите пожалуйста, может кто-нибудь поможет, очень нужно((((( есть программа, нужно каждую строчку откоментитть что она делает, понимаю что бред, но очень нужно
#include <mega8.h>
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#define BYTE unsigned char
#define WORD unsigned short int
#define CARDINAL unsigned long int
#include <lcd.h>
char byDisplay[6]; // буфер данных, для вывода на экран
char Counter;
char Count =6;
CARDINAL U;
CARDINAL I_izm;
CARDINAL R;
void PrepareData(CARDINAL Data)
{
BYTE i;
for(i=0; i<6; i++)
{
byDisplay[5-i] = Data % 10 + 48;
Data /= 10;
}
}
//Вывод экранного буфера на дисплей
void PrintBuf(void)
{
int i;
for(i=0; i<7; i++)
{
lcd_putchar(byDisplay);
}
}
#define ADC_VREF_TYPE 0xC0
unsigned int read_adc(unsigned char adc_input) // Чтение-Преобразование кода АЦП
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0x7f); // Выбираем канал для АЦП в adc_input,0x7f - источник опорного напряжения
ADCSRA|=0x40; // Старт преобразования
while ((ADCSRA & 0x10)==0); // Ждем конца преобразованиия флаг ADIF станет = 0
ADCSRA|=0x10;
return ADCW;
}
//Подпрограмма обработки прерывания по переполнению T1
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
WORD tmp;
TCNT1H=0xFF; // Перезагрузить значение Timer 1
TCNT1L=0x3C;
if (Counter++ >= Count)
{
Counter = 0;
lcd_gotoxy(0,0); //вывод напряжения
PrepareData(U / Count);
byDisplay[0] = byDisplay[2];
byDisplay[1] = byDisplay[3];
byDisplay[2] = '.';
byDisplay[3] = byDisplay[4];
byDisplay[4] = byDisplay[5];
byDisplay[5] = 'V';
byDisplay[6] = '';
PrintBuf();
lcd_gotoxy(0,1); //вывод тока измеренныя
PrepareData(I_izm / Count) ; // read_adc(0)/10.24*256
byDisplay[0] = byDisplay[2];
byDisplay[1] = byDisplay[3];
byDisplay[2] = '.';
byDisplay[3] = byDisplay[4];
byDisplay[4] = byDisplay[5];
byDisplay[5] = 'A';
byDisplay[6] = '';
PrintBuf();
lcd_gotoxy(7,0); //вывод сопротивления
PrepareData(R / Count) ; // read_adc(0)/10.24*256
byDisplay[0] = byDisplay[2];
byDisplay[1] = byDisplay[3];
byDisplay[2] = '.';
byDisplay[3] = byDisplay[4];
byDisplay[4] ='';
byDisplay[5] = 'O';
byDisplay[6] = 'm';
PrintBuf();
R = 0;
U = 0;
I_izm = 0;
}
else
{
U += read_adc(1) * 3; //читаю в переменную инфу из АЦП
I_izm += read_adc(0); // число в скобках обозначает номер входа
R +=(read_adc(1) * 3/read_adc(0))*100;//вычисляем сопротивление
};
}
void main(void) //Основная функция "main", с которой начинается выполнение всей
//программной процедуры
{
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0xFA;
TCNT1L=0xE9;
TIMSK=0x04;
ACSR=0x80;
SFIOR=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x82;
lcd_init(16); //инициализация на 16 символов
#asm("sei")
while (1)
{
//Place your code here
};
}
Re: ATmega8 2 АЦП
Добавлено: Чт фев 20, 2014 08:11:11
kk042fjv
Здравствуйте!
Занимаюсь изучением АЦП. Писать программу для АЦП научился, теперь хочу научиться как делать усреднение показаний (например снимать штук 30 показаний и среднее выводить на экран). Может у кого-нибудь есть похожий исходник? Очень надо.
Re: ATmega8 2 АЦП
Добавлено: Чт фев 20, 2014 09:40:46
ibiza11

скоро начнут просить исходник "как сложить два числа"
Re: ATmega8 2 АЦП
Добавлено: Чт фев 20, 2014 19:22:47
kk042fjv
ibiza11 писал(а):
скоро начнут просить исходник "как сложить два числа"
Был бы программист не спрашивал бы
Re: ATmega8 2 АЦП
Добавлено: Пт фев 21, 2014 12:41:20
ibiza11
зуб даю, что вопросы опять возникнут, поскольку вы "не программист"
Код: Выделить всё
void adc_init(void){
ADMUX = 0; // опора Vref, ADLAR = 0, канал = 0
ADCSRA |= (1<<ADEN)|(1<<ADFR)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //вкл АЦП, Free Runnig Mode, предделитель 128
}
unsigned short get_adc_result(void){
while(!(ADCSRA & (1<<ADIF))); // ожидание преобразования
ADCSRA |= (1<<ADIF); // сброс флага
return (unsigned short)(ADCH<<8)|(ADCL);
}
void main(void){
adc_init();
unsigned short ADCResult, ADCSumm = 0;
unsigned char i = 0;
while(1){
while(i<30){
ADCSum += get_adc_result();
i++;
}
ADCSum /= 30;
/* вот здесь надо забирать результат интегирования */
i = 0;
ADCSum = 0;
}
}
Re: ATmega8 2 АЦП
Добавлено: Сб дек 06, 2014 19:43:04
shadivl
Здравствуйте.
Я делаю схему управления пятью сервоприводами на atmega8. На каждый привод приходится свой переменный резистор. Соответственно я должен снять данные с АЦП, обработать их и подать управляющий сигнал на сервы. Так вот, кусок программы, ответственный за управляющий сигнал, работает нормально, а вот с АЦП какие-то проблемы. То ли прерывание не срабатывает, то ли ещё что-то, но в Протеусе, да и в железе, на изменение сопротивления серва никак не реагировала. Помогите понять, в чём причина.
Сервы подключены к PD0-PD4, резисторы - к PC0-PC4. Пишу в CVAVR.
- code.c
- (2.94 КБ) 519 скачиваний
Re: ATmega8 2 АЦП
Добавлено: Сб дек 06, 2014 22:49:01
zero648
Наверное проблема здесь:
SIG[a]=65010-(ADCW*0,1221); //Чтение результата АЦП преобразования, 0,1221 - уравнивающий коэффициент
значение ADCW нужно сначала присвоить вещественной переменной, а уже потом работать с этой переменной, т.е. умножать на число с плавающей точкой, а иначе это умножение дает ноль и результат всегда один и тот же.
Re: ATmega8 2 АЦП
Добавлено: Вс дек 07, 2014 08:20:40
shadivl
Переписал, но никакой реакции. Я в конце добавил строку, которая инвертирует PB0 при срабатывании прерывания АЦП. Однако ничего не происходит, порт своё значение не меняет. Похоже, по какой-то причине прерывание не срабатывает.
Код: Выделить всё
interrupt [ADC_INT] void adc_isr(void)
{
float cont;
if (schet==12500) //считывние около 5 раз в секунду
{cont=(float)ADCW;
SIG[a]=65010-(int)(cont*0,1221); //Чтение результата АЦП преобразования, 0,1221 - уравнивающий коэффициент
if (SIG[a]>63046) SIG[a]=63046; //ограничение длительности сигнала
if (a==4){a=0;
schet=0;} //Проверяем значение счётчика
else a++;
ADMUX=a; //Готовимся считывать сигнал с другого канала
delay_us(10); //Выдержка времени для стабилизации входного напряжения
ADCSRA|=0x40; //Старт АЦП преобразования
}
else schet++;
PortB=(~PortB)&0b00000001;//Ирвертирование PB0 для проверки работы прерыванния
}
Re: ATmega8 2 АЦП
Добавлено: Вс дек 07, 2014 09:36:38
COKPOWEHEU
shadivl писал(а):Похоже, по какой-то причине прерывание не срабатывает.
Код: Выделить всё
interrupt [ADC_INT] void adc_isr(void)
{
float cont;
if (schet==12500) //считывние около 5 раз в секунду
{
ADCSRA|=0x40; //Старт АЦП преобразования
}
else schet++;
PortB=(~PortB)&0b00000001;//Ирвертирование PB0 для проверки работы прерыванния
}
То есть повторное преобразование запускаете только если schet строго равен 12500, при всех остальных значениях АЦП остановлен, не выполняет преобразований и не генерирует прерываний. Интересно, почему же они не возникают.
Re: ATmega8 2 АЦП
Добавлено: Вс дек 07, 2014 10:13:26
shadivl
Вытащил строку из условия - не работает
Код: Выделить всё
if (schet==12500) //считывние около 5 раз в секунду
{cont=(float)ADCW;
SIG[a]=65010-(int)(cont*0,1221); //Чтение результата АЦП преобразования, 0,1221 - уравнивающий коэффициент
if (SIG[a]>63046) SIG[a]=63046; //ограничение длительности сигнала
if (a==4){a=0;
schet=0;} //Проверяем значение счётчика
else a++;
ADMUX=a; //Готовимся считывать сигнал с другого канала
delay_us(10); //Выдержка времени для стабилизации входного напряжения
}
else schet++;
PORTB=(~PORTB)&0b00000001;
ADCSRA|=0x40; //Старт АЦП преобразования
Попробовал вообще без переменной schet - тоже не работает
Код: Выделить всё
cont=(float)ADCW;
SIG[a]=65010-(int)(cont*0,1221); //Чтение результата АЦП преобразования, 0,1221 - уравнивающий коэффициент
if (SIG[a]>63046) SIG[a]=63046; //ограничение длительности сигнала
if (a==4) a=0; //Проверяем значение счётчика
else a++;
ADMUX=a; //Готовимся считывать сигнал с другого канала
delay_us(10); //Выдержка времени для стабилизации входного напряжения
PORTB=(~PORTB)&0b00000001;
ADCSRA|=0x40; //Старт АЦП преобразования
Re: ATmega8 2 АЦП
Добавлено: Вс дек 07, 2014 11:38:06
COKPOWEHEU
Если АЦП настроен на непрерывное преобразование, зачем выставлять флаг начала?
В чем проверяете?
Задержка в прерывании не нужна.
Re: ATmega8 2 АЦП
Добавлено: Вс дек 07, 2014 14:08:16
shadivl
Re: ATmega8 2 АЦП
Добавлено: Чт мар 09, 2017 10:17:35
TIOSA
Ситуация следующая…. Взят код для двух каналов ADC для ATMega8…(от ув. siamds),
пытаюсь добавить вывод на LCD разницу значений (adc_data[0]- adc_data[1]). Помогите реализовать сие.
Re: ATmega8 2 АЦП
Добавлено: Сб мар 11, 2017 11:38:16
COKPOWEHEU
Форматирование отсутствует
ADCSRA|=0x40; //Старт АЦП преобразования
Плохая идея использовать магические числа.
(ADC_VREF_TYPE & 0xff)
Это зачем? Тем более что очевидные вещи прокомментированы а физический смысл этой константы и допустимые значения - нет.
delay_us(10); //Выдержка времени для стабилизации входного напряжения
Задержки в прерывании - плохая идея.
register static unsigned char input_index=0;
резервировать регистр только для прерывания? Учитывая использование задержки - скорость не требуется, а тогда зачем?
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
А чего указали последний канал вместо количества? Остальные записи были бы проще. Другое дело что в общем случае между используемыми аналоговыми каналами могут быть цифровые.
ch_1= adc_data[0]; //Запись в переменную ch_1 результата ADC 1-го канала
ch_2= adc_data[1]; //Запись в переменную ch_2 результата ADC 2-го канала
А если в середине присвоения возникнет прерывание АЦП и изменит значение массива?
ADCSRA=0xCB;
Про магические числа я уже писал.
пытаюсь добавить вывод на LCD разницу значений (adc_data[0]- adc_data[1])
В чем конкретно проблема? Не можете вычислить разность? Не можете вывести знаковое число на дисплей?