Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблемы с АЦП ATmega48
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
sergeus
Программа должна оцифровывать сигнал на входе и в зависимости от уровня управляет ШИМ на выходе.

Непонятки с АЦП, оно работает только один раз, а должно работать при каждом вызове подпрограммы оцифровки.

Помогите, пожалуйста. Бьюсь уже несколько часов. Код на WinAVR:

Код
/*    ATmega48, тактирование внутреннее 8 MHz*/

//#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void set_pwm(unsigned char, unsigned char, unsigned char);
int adc_convert(unsigned char);

unsigned int max=1, min=1, average=0;
double factor=0;
unsigned char abc = 0;

ISR(TIMER1_OVF_vect){
  unsigned int input;
  
  input = adc_convert(0);
  if (input > max) max = input;
  
  factor = (double)input/(double)max
  
  OCR0A =  (unsigned char)(0xFF * factor);

  TCNT1 = 65503;                                    // 4mS
}

// ********************  ADC   *****************************

void adc_init(void){
  ADMUX = (0<<REFS1)|(1<<REFS0);                                        // AVCC - 5v
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);                // CK/128
  //ADCSRB = (1<<ADTS2)|(1<<ADTS1)|(0<<ADTS0);                          // timer1 overflow
}

int adc_convert(unsigned char channel){
  unsigned int result;
  
  ADMUX = (ADMUX & 0xF0)|channel;
  ADCSRA |= (1<<ADSC);

  while (!(ADCSRA & (1<<ADSC)));
  
  
  result = ( ((int)ADCH << 8) | (int)ADCL);
  return result;
}



// ********************  PWM   *****************************

void pwm_init(void){
  // Timer0 init
  DDRD |= (1<<PD5)|(1<<PD6);
  TCCR0A |= (1<<COM0A1)|(1<<COM0B1)|(1<<WGM01)|(1<<WGM00);        // Fast PWM
  TCCR0B |= (1<<CS00);                                                // CK/1, F pwm =
  
  // Timer2 init
  DDRB |= (1<<PB3);
  TCCR2A |= (1<<COM2A1)|(1<<WGM21)|(1<<WGM20);                    // Fast PWM
  TCCR2B |= (1<<CS20);                                                // CK/1, F pwm =
}

void set_pwm(unsigned char r, unsigned char g, unsigned char b){
  OCR0A = r;
  OCR0B = g;
  OCR2A = b;
}

void timer1_init(void){
  TCCR1B |= (1<<CS12)|(0<<CS11)|(1<CS10);            // step = 1/8mS
  TIMSK1 |= (1<<TOIE1);                            // int. ovf. enable
  TCNT1 = 65505;                                    // 1000mS
}


int main (void) {
  adc_init();
  pwm_init();                                        // timers 0 & 2 init
  timer1_init();
  
  sei();
  while(1);
}
SasaVitebsk
Вот пишут-пишут разные люди и в разных темах. Всё равно что об стенку горох! Хоть ты где-нибудь на центральной вкладке размести!

Не должно быть ожиданий и задержек в прерывании. Ну не для того они созданы. Разберитесь и осмыслите это. Дальше даже читать ваш код не хочется.

Не ужели нет фантазии как это можно реализовать по-другому?

1 вариант) Есть у вас прерывание TIMER1_OVF. В начале прерывания читаете АЦП и перестартовываете его. Само прерывание должно приходить гарантировано реже чем время измерения по АЦП. Соответственно ждать ничего не надо.

2 вариант) Проверяете завершено ли преобразование и результат размещаете в памяти. Данные берёте из памяти. (То есть развязываете факт измерения и факт принятия решения). В этом случае частота вызова TIMER1_OVF может быть любой.

Можно ещё 10 вариантов придумать.
sergeus
Спасибо, SasaVitebsk!

Дельные советы, задумывался об этом, но не реализовал. Дело было в именах переменных и считывании их регистров АЦП. Сейчас все работает.

Сделаю прерывания, как мне посоветовали. Еще раз спасибо smile.gif
777777
Цитата(sergeus @ May 24 2010, 21:15) *
Код
  result = ( ((int)ADCH << 8) | (int)ADCL);

Еще очень важен порядок чтения байт из регистров, об этом написано в даташите. Если лень читать, можно написать
Код
  result = ADC;

и компилятор сгенерирует правильную последовательность.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.