Запуск АЦП, запускаемый 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) {
//}
Заранее спасибо
@zjor, 👍-1
Обсуждение2 ответа
Я нашел решение, оно странное, поскольку я включил режим CTC, но оно начало работать нормально, как только я сбросил таймер 1:
ISR(TIMER1_COMPB_vect) {
TCNT1 = 0;
}
Режим Timer1 CTC требует, чтобы вы поместили значение CTC TOP
в OCR1A
(см. таблицу 15.5 в 328P datasheet). Вы этого не сделали, поэтому таймер работает от 0 до 0xFFFF.
Режим запуска АЦП Timer1 требует, чтобы вы поместили значение запуска АЦП в OCR1B
, что вы и сделали, поэтому каждый раз, когда таймер проходит мимо вашего значения запуска (t1_comp
), он запускает преобразование АЦП.
Короче говоря, вам нужно установить OCR1A
и OCR1B
на t1_comp
.
- Регистр ADCH Arduino Uno завис на значении 255 при чтении из ISR
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Как правильно использовать volatile переменные в Arduino?
- Как прервать функцию цикла и перезапустить ее?
- 4-битный счетчик вверх и вниз
- Включить и отключить отдельные прерывания
- Управление функцией включения на драйвере микрошагового устройства
Я не думаю, что ручное преобразование АЦП во время инициализации — это
_BV(ADSC) | // ADC start
должен быть там. Такжеобразцы
должны бытьлетучими
. Я не буду комментировать остальную часть кода, поскольку работа над ним, похоже, еще продолжается., @Gerben