Только работать оно не будет. Всякий раз будет читаться предыдущий канал.ARV писал(а):что за кошмарный код?! ну хоть примерно как-то так надо:
как-то так...
три вольтметра на одной меге16
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
- Реклама
- Сообщения: 884
- Зарегистрирован: Пн июл 08, 2013 22:59:45
если вы внимательно посмотрите, то float все закоментированы, это были начальные разработки, для наглядности, а потом я переписал под умножение, вычисления кошмарные, потому что напряжение идёт не с делителя, а с операционного уселителя, который в свою очередь тоже по хитрому подключён, вообщем вычисления станут позже ещё кошмарнее, с использованием интерполяции, и тем не менее это как раз работает, а не работает обычный делитель напряжения (это где 15/8), вернее работает, но до переключенияARV писал(а): далее, что за ужасные вычисления у вас?
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
Вы учли это?
In Free Running mode, always select the channel before starting the first conversion. The channel
selection may be changed one ADC clock cycle after writing one to ADSC. However, the
simplest method is to wait for the first conversion to complete, and then change the channel
selection. Since the next conversion has already started automatically, the next result will reflect
the previous channel selection. Subsequent conversions will reflect the new channel selection.
In Free Running mode, always select the channel before starting the first conversion. The channel
selection may be changed one ADC clock cycle after writing one to ADSC. However, the
simplest method is to wait for the first conversion to complete, and then change the channel
selection. Since the next conversion has already started automatically, the next result will reflect
the previous channel selection. Subsequent conversions will reflect the new channel selection.
- Сообщения: 758
- Зарегистрирован: Вс фев 10, 2013 15:26:00
Не тратьте силы, возьмите молоток побольше!ещё кошмарнее, с использованием интерполяции
По таблице(ам)...
- Сообщения: 884
- Зарегистрирован: Пн июл 08, 2013 22:59:45
столько много буржуйских буковок... как я понял смысл сводиться к тому что первое преобразование не точное, я пробовал сделать задержку, вернее пропуск нескольких итераций, та же фигня один вольтметр считает правильно, другой нетvdavid писал(а):Вы учли это?
- Реклама
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
Смысл сводится к тому, что смену канала нужно делать по окончании преобразования, например в прерывании. Но следует понимать, что фактически канал переключится только на следующем преобразовании.kelod писал(а): столько много буржуйских буковок...
- Сообщения: 884
- Зарегистрирован: Пн июл 08, 2013 22:59:45
я пробовал после изменения канала ставить счётчик, что бы измерения были не сразу,в течении нескольких итераций цикла,нечего не изменилось, откуда то берётся дополнительное напряжение или дополнительные тики ацп
видите при запуске некоторое время напряжение 12,00, а потом неожиданно становиться 14.41
я может быть ошибаюсь, но мне кажется что контроллер не переключается обратно на нулевую ножку, а так и остаётся на 1
видите при запуске некоторое время напряжение 12,00, а потом неожиданно становиться 14.41
я может быть ошибаюсь, но мне кажется что контроллер не переключается обратно на нулевую ножку, а так и остаётся на 1
- Вложения
-
- 16_3_1.rar
- (34.65 КБ) 143 скачивания
-
- GccApplication2.hex
- (30.61 КБ) 286 скачиваний
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
Для начала уберите free running mode и переключайте каналы при нулевом состоянии бита ADEN. Преобразование всякий раз запускайте вручную.kelod писал(а):я пробовал после изменения канала ставить счётчик
мой код будет отлично работать, в строгом соответствии с даташитом. удачи всем неверующим!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 884
- Зарегистрирован: Пн июл 08, 2013 22:59:45
kelod, может он не работает именно у Вас ? Вам не приходило это в голову ? 
- Сообщения: 884
- Зарегистрирован: Пн июл 08, 2013 22:59:45
сделал так:vdavid писал(а): Для начала уберите free running mode и переключайте каналы при нулевом состоянии бита ADEN. Преобразование всякий раз запускайте вручную.
Код: Выделить всё
ADCSRA |= (1 << ADEN) // разрешение АЦП
//|(1 << ADSC) // запуск преобразования
//|(1 << ADATE) // непрерывный режим работы АЦП //|(1 << ADFR) // непрерывный режим работы АЦП
|(1 << ADPS2)|(1 << ADPS1)|(0<< ADPS0) // предделитель на 64 (частота АЦП 125kHz)
|(1 << ADIE); // разрешение прерывания
ADMUX |= (1 << REFS1)|(1 << REFS0); // внутренний ИОН 2,56V
//|(0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(0 << MUX0); // вход ADC0
unsigned char buffer[6];
unsigned char buffer1[1];
unsigned int fq_tek;
flag_volt=1;
int koy=2,
rma=83,
pgr=31;
while(1)
{
switch(flag_volt)
{
case 0:
{
//akk1=0;
break;
}
case 1:
{
ADCSRA |= (0 << ADEN);
ADMUX |= (0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(0 << MUX0); // вход ADC0
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADSC);
akk1=akk*15*pow(8,-1);
flag_volt=2;
break;
}
case 2:
{
ADCSRA |= (0 << ADEN);
ADMUX |= (0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(1 << MUX0); // вход ADC0
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADSC);
temp1=( rma*( (1200*pow(100,-1))-((temp1*koy)*pow((4*100),-1) - (pgr*pow(1000,-1))) )/ (((temp1*koy)*pow((4*100),-1))- (pgr*pow(1000,-1))) );
flag_volt=1;
break;
}
case 3:
{
temp2=akk;
flag_volt=1;
break;
}
}
Код: Выделить всё
ISR (ADC_vect)
{
akk = ADC;
}
Alex, может и только у меня, а как починить?
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
Надеюсь akk объявлена как volatile?
Ну и ожидать окончания преобразования тоже нужно. Вот так должно заработать:
Все, что добавил пометил комментарием //*
Ну и ожидать окончания преобразования тоже нужно. Вот так должно заработать:
Код: Выделить всё
volatile char ADCReady; //*
volatile int akk; //*
ADCSRA |= (1 << ADEN) // разрешение АЦП
//|(1 << ADSC) // запуск преобразования
//|(1 << ADATE) // непрерывный режим работы АЦП //|(1 << ADFR) // непрерывный режим работы АЦП
|(1 << ADPS2)|(1 << ADPS1)|(0<< ADPS0) // предделитель на 64 (частота АЦП 125kHz)
|(1 << ADIE); // разрешение прерывания
ADMUX |= (1 << REFS1)|(1 << REFS0); // внутренний ИОН 2,56V
//|(0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(0 << MUX0); // вход ADC0
unsigned char buffer[6];
unsigned char buffer1[1];
unsigned int fq_tek;
flag_volt=1;
int koy=2,
rma=83,
pgr=31;
while(1)
{
switch(flag_volt)
{
case 0:
{
//akk1=0;
break;
}
case 1:
{
ADCSRA |= (0 << ADEN);
ADMUX |= (0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(0 << MUX0); // вход ADC0
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADSC);
ADCReady=0; //*
while(!ADCReady); //*
akk1=akk*15*pow(8,-1);
flag_volt=2;
break;
}
case 2:
{
ADCSRA |= (0 << ADEN);
ADMUX |= (0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(1 << MUX0); // вход ADC0
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADSC);
ADCReady=0; //*
while(!ADCReady); //*
temp1=( rma*( (1200*pow(100,-1))-((temp1*koy)*pow((4*100),-1) - (pgr*pow(1000,-1))) )/ (((temp1*koy)*pow((4*100),-1))- (pgr*pow(1000,-1))) );
flag_volt=1;
break;
}
case 3:
{
temp2=akk;
flag_volt=1;
break;
}
}
и прерывание по окончанию
Код:
ISR (ADC_vect)
{
ADCReady=1; //*
akk = ADC;
}- Сообщения: 884
- Зарегистрирован: Пн июл 08, 2013 22:59:45
к сожалению не работает
, причём если с двумя ножками вторая показывает адекватное значение, первая нет, то с тремя получается что то ужасное, причём если запускать по шагам, то первое измерение более менее нормальное, а на втором круге вылетает вся эта котовасия...
- Вложения
-
- GccApplication2.hex
- (31.07 КБ) 288 скачиваний
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
Так под третью вообще код не написан фактически. И зачем нам hex. Выкладывайте .c. У Вас это все в симуляторе или в железе?kelod писал(а):к сожалению не работает, причём если с двумя ножками вторая показывает адекватное значение, первая нет, то с тремя получается что то ужасное, причём если запускать по шагам, то первое измерение более менее нормальное, а на втором круге вылетает вся эта котовасия...
И зачем нужен pow(8,-1)? Просто разделить на 8 религия не позволяет?
Что вижу я: зачем прерывание? вы все равно ждете его срабатывания ждите флаг от АЦП ADIF. Выкиньте непрерывное преобразование, используйте одиночное и будет вам счастье. Дальше строки:Вы знаете что такое логические операции? В таком случае переключение с 1-го на 0-й канал происходить не будет. Почитайте про логическое или. Сбрасывайте биты так: дальше устанавливайте нужный канал.
Код: Выделить всё
while(!ADCReady);Код: Выделить всё
ADMUX |= (0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(0 << MUX0);
ADMUX |= (0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(1 << MUX0);Код: Выделить всё
ADMUX &=~ (1 << MUX3)|(1 << MUX2)|(1 << MUX1)|(1 << MUX0);- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
Ну, в дальнейшем вместо while(!ADCReady); можно будет написать while(!ADCReady) sleep_cpu(); для уменьшения шумов.eess9 писал(а):зачем прерывание? в
Тогда после цикла switch лучше. Установили канал, обработали данные и уснули. По прерыванию проснулись, пошли на новый виток цикла while и снова попали в switch. Просто лучше вызвать сон раз в одном месте, предварительно убедившись, что сделано абсолютно все, чем тыкать команды сна где придется.
- Сообщения: 410
- Зарегистрирован: Чт ноя 13, 2008 16:33:42
eess9, Конечно Вы правы. Еще лучше все это оформить в виде функции, как советовал ARV.


