Запуск АЦП, запускаемый TIMER1_COMPB

Я пытаюсь запустить АЦП на канале 0, вызванном TIMER1_COMPB. Кажется, все работает нормально, но базовая арифметика не работает, а переменные внутри ISR и даже основной цикл не обновляются (x == 2 все время)

Может кто-нибудь объяснить мне, почему это так? Даже летучая переменная не менялась... Ардуино УНО, IDE версии 1.8.6

#define SAMPLES_SIZE  205

const int adc_channel = 0;
const uint16_t t1_load = 0;

// 250 соответствует 8 кГц
const uint16_t t1_comp = 25000; 

uint16_t samples[SAMPLES_SIZE];
volatile uint8_t samplePos = 0;

static int x = 0;

void initADC() {
  // Инициируем режим свободной работы АЦП; f = (16 МГц/прескалер)/13 циклов/преобразование
  ADMUX  = adc_channel; // Выбор канала, регулировка вправо, использование контакта AREF
  ADCSRA = _BV(ADEN)  | // включение АЦП
           _BV(ADSC)  | // запуск АЦП
           _BV(ADATE) | // Автоматический триггер
           _BV(ADIE)  | // Разрешение прерывания
           _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1/13 = 9615 Гц
  ADCSRB = _BV(ADTS2) | _BV(ADTS0);              // Таймер/Счетчик1 сравниваем совпадение B
  DIDR0  = _BV(adc_channel); // Отключаем цифровой вход для вывода АЦП
}

void initTimer() {
  // Сброс таймера 1, управляющий регистр A
  TCCR1A = 0;

// Устанавливаем режим CTC
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

// Устанавливаем прескалер на 8
  TCCR1B &= ~(1 << CS12);
  TCCR1B |= (1 << CS11);
  TCCR1B &= ~(1 << CS10);

// Сбрасываем таймер 1 и устанавливаем значение сравнения
  TCNT1 = t1_load;
  OCR1B = t1_comp;

// Включаем прерывание сравнения Таймера 1
  TIMSK1 = (1 << OCIE1B);
}

void setup() {  
  cli();
  initADC();
  initTimer(); 
  sei();

  Serial.begin(115200);
}

void loop() {
  while(ADCSRA & _BV(ADIE)); // Дождитесь завершения выборки звука
  cli();
  x = x + 2;
  Serial.print(samples[0]);
  Serial.print("\t");
  Serial.println(x);
// for (int i = 0; i < SAMPLES_SIZE; i++) {
// Serial.println(образцы);
// }
// образецПос = 0;

  ADCSRA |= _BV(ADIE);       // Возобновляем прерывание выборки
  sei();
}

ISR(ADC_vect) { 
  int16_t sample = ADC;

  samples[0] = sample;
// образецПос++;
  ADCSRA &= ~_BV(ADIE); // Буфер полон, прерывание выключено

  if(samplePos >= SAMPLES_SIZE) {
    ADCSRA &= ~_BV(ADIE); // Буфер полон, прерывание выключено
  }
}

//ISR(TIMER1_COMPB_vect) {
//}

Заранее спасибо

, 👍-1

Обсуждение

Я не думаю, что ручное преобразование АЦП во время инициализации — это _BV(ADSC) | // ADC start должен быть там. Также образцы должны быть летучими. Я не буду комментировать остальную часть кода, поскольку работа над ним, похоже, еще продолжается., @Gerben


2 ответа


1

Я нашел решение, оно странное, поскольку я включил режим CTC, но оно начало работать нормально, как только я сбросил таймер 1:

ISR(TIMER1_COMPB_vect) {
  TCNT1 = 0;  
}
,

2

Режим Timer1 CTC требует, чтобы вы поместили значение CTC TOP в OCR1A (см. таблицу 15.5 в 328P datasheet). Вы этого не сделали, поэтому таймер работает от 0 до 0xFFFF.

Режим запуска АЦП Timer1 требует, чтобы вы поместили значение запуска АЦП в OCR1B, что вы и сделали, поэтому каждый раз, когда таймер проходит мимо вашего значения запуска (t1_comp), он запускает преобразование АЦП.

Короче говоря, вам нужно установить OCR1A и OCR1B на t1_comp.

,