Реализация прерываний и таймеров на плате Arduino Uno
Я пытаюсь реализовать прерывания на плате Arduino Uno. Моя цель — синтезировать волны и воспроизводить их через разъем 3,5 мм. Вот что у меня есть на данный момент, на основе предоставленного мне кода. Я урезал его до довольно примитивной версии, чтобы выявить неисправность. Мой аудиоразъем подключен к контакту 9, который, как мне сказали, является контактом ШИМ для этой платы. Однако из аудиоразъема вообще ничего не воспроизводится. Я был бы очень признателен за любой совет или помощь! :)
#include "avr/pgmspace.h"
#define NUM_OSC 1 // количество осцилляторов
#define MAXVOL 255 // максимальная громкость каждого осциллятора
const byte sine256[256] PROGMEM = {
128,131,134,137,140,143,146,149,152,156,159,162,165,168,171,174,
176,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216,
218,220,222,224,226,228,230,232,234,236,237,239,240,242,243,245,
246,247,248,249,250,251,252,252,253,254,254,255,255,255,255,255,
255,255,255,255,255,255,254,254,253,252,252,251,250,249,248,247,
246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220,
218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179,
176,174,171,168,165,162,159,156,152,149,146,143,140,137,134,131,
128,124,121,118,115,112,109,106,103,99, 96, 93, 90, 87, 84, 81,
79, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39,
37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 18, 16, 15, 13, 12, 10,
9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 8,
9, 10, 12, 13, 15, 16, 18, 19, 21, 23, 25, 27, 29, 31, 33, 35,
37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76,
79, 81, 84, 87, 90, 93, 96, 99, 103,106,109,112,115,118,121,124
};
const byte square256[256] PROGMEM = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
};
const byte* const wave_table[] = {sine256, square256, triangle256, sawtooth256};
// информация о текущем состоянии одного осциллятора
struct OscillatorState
{
unsigned int phaseStep; // частота этого осциллятора
unsigned int volume; // множитель громкости для этого осциллятора
unsigned int phaseAccu; // аккумулятор, который проходит через этот осциллятор
// старший байт = текущий индекс образца
const byte* waveform; // какая форма волны
};
volatile OscillatorState oscillators;
volatile byte valOut;
//********* процедуры прерывания ******
// настраиваем таймер 1 для выполнения фазовой коррекции PCM на номинальной частоте 31372,549
void setupTimer()
{
// Предделитель тактовой частоты таймера 1 на : 1, установите WGM22 на ноль, а WGM12,13 для корректной фазы PCM
TCCR1B = (TCCR1B & 0b11100000) | 0b00001;
// установите его для очистки режима сравнения и сопоставления на обоих контактах, а также для коррекции фазы PCM (WGM21 и WGM20)
TCCR1A = (TCCR1A &0b00001100)| 0b10100001;
// устанавливаем прерывания переполнения включенными для таймера 1
TIMSK1 |= (1<<TOIE1);
Serial.println("hello");
}
// при каждом переполнении таймера 1 устанавливаем следующее значение выборки для ШИМ
ISR(TIMER1_OVF_vect)
{
oscillators.phaseAccu += oscillators.phaseStep;
valOut = highByte(pgm_read_byte(oscillators.waveform + highByte(oscillators.phaseAccu)) * oscillators.volume);
OCR1A = valOut; // заменено ... = valOut[0]; // запись на вывод 9
}
unsigned int hzToPhaseStep(float frequency)
{
float phaseStep = frequency * 2.0886902978652881446683197032183; // (pow(2,16) * частота) / 31376,6
return (unsigned int)phaseStep;
}
void setup()
{
delay(1000);
Serial.begin(9600);
OCR1A = 0;
oscillators.waveform = wave_table[2];
oscillators.phaseAccu = 0;
setupTimer();
oscillators.volume = 200;
oscillators.phaseStep = hzToPhaseStep(440.00);
}
void loop()
{
}
0
Смотрите также:
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату