ATmega32, к её PWM-выходам (OC1A/OC1B) подключен динамик (как в схеме Elm ChaN, прикрепил). На аппаратном SPI висит SD-карта.
С выводом 8-ми битного аудио на один выход PWM всё было окей, но как-то только решил запилить такой варик, чтобы получить 16 бит - появились искажения (к сожалению, звуковые файлы тут не прикрепить, так что дропбокс).
Теперь к подробностям. Эти искажения не такие сильные и на фоне музыки их почти не слышно. На прикреплённой записи я специально выводил... кхм, меандр с очень низкой частотой, а по факту - просто постоянный высокий уровень на выходе ШИМ (0xFFFF). Так вот, уровень этого треска коррелирует с уровнем сигнала (я пробовал также пилу, и громкость треска нарастала и падала). Т.к. максимальная громкость получается когда на выходе 0хFFFF, могу сделать вывод, что этот треск - короткие провалы до нуля.
Кроме того, я по сделанной записи замерил его частоту, и она получилась равной... ровно 256 семплам из буфера. Т.е., этот провал до нуля происходит каждые 256 семплов. Частота треска зависит от заданной частоты дискретизации, т.е. от частоты срабатывания сравнения таймера 2, но это не главное. В основном цикле каждые 256 семплов происходит обращение к SD через pf_read. Когда я закомментил обращения к SD (естественно, оставив первое, чтобы загрузить буфер и тупо выводить его по кругу), весь треск исчез. Т.е., этот чёртов провал по ходу возникает именно в момент обращения к карте памяти по SPI и чтении следующей порции данных.
Честно говоря, теряюсь в догадках, как слаботочный SPI может создавать какие-то наводки на мощные выходы ШИМа. У них даже порты разные, ШИМ на PortD, SPI на PortB. К тому же, как я уже написал, в версии с одним выходом на 8 бит такой проблемы не возникало. Если что, собрано всё на отладочной плате Pinboard, т.е. все фильтры по питанию и прочее стоит. Питается от USB компа.
Недокод:
Код: Выделить всё
#include <avr/interrupt.h>
#include "diskio.h"
#include "pff.h"
#include <util/delay.h>
unsigned char buffer[512]; /* буфер в который копируется инфа с флешки */
volatile unsigned int count; //счетчик скопированных данных
ISR(TIMER2_COMP_vect) //прерывание в котором выводим данные в PWM таймера 1
{
unsigned int temp;
temp = (unsigned int)((buffer[count+1]<<8) + buffer[count] + 32768);
OCR1A = temp & 0xFF; // выводим LSB
OCR1B = temp >> 8; // выводим MSB
count += 2; // устанавливаем указатель на следующий семпл
if (count >= 512) count = 0;// если 512 обнуляем
}
int main()
{
_delay_ms(700);
unsigned int br; /* счетчик чтения/записи файла */
unsigned char buf = 0; //переменная определяющая какая часть буфера читается
FATFS fs; /* Рабочая область (file system object) для логических дисков */
DDRD=(1<<PD5)|(1<<PD4); // устанавливаем пины PWM как выходы
DDRA = 0b00001111; // светодиоды состояния
// Timer/Counter 1 initialization
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10); // clear output pin on compare (OC1A и OC1B), fast PWM 8 bit
TCCR1B=(1<<WGM12)|(1<<CS10); // fast PWM 8 bit + no prescaling (PWM freq = 65k)
OCR1A = 128;
OCR1B = 128;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 2 MHz
// Mode: CTC top=OCR2
TCCR2=(1<<WGM21)|(1<<CS21); // CTC mode, prescaler = 8 // 0x0B;
OCR2=250; //настройка регистра сравнения для 8кГц
//OCR2=91; //для 22кГц
//OCR2 = 63; // для 32 кГц
sei();
// Timer(s)/Counter(s) Interrupt(s) initialization
if(disk_initialize()==0) //инициализируем флешку
{
PORTA = 1;
pf_mount(&fs); //монтируем файловую систему
pf_open("1.WAV"); //открываем вавку
pf_lseek(44); //перемещаем указатель на 44
pf_read(buffer, 512, &br); //в первый раз заглатываем сразу 512байт
PORTA = 2;
TIMSK=(1<<OCIE2); //врубаем музон
while(1)
{
if(!buf && count>255) //если воспроизвелось больше 255 байт,
{
pf_read(&buffer[0], 256, &br);//то читаем в первую половину буфера инфу с флешки
buf=1;
if (br < 256) //если буфер не содержит 256 значений значит конец файла
break;
}
if(buf && count<256)
{
pf_read(&buffer[256], 256, &br); // читаем во вторую часть буфера с флешки
buf = 0;
if (br < 256)
break;
}
}
TIMSK = 0x00; //глушим все
PORTA = 5;
_delay_ms(1000);
pf_mount(0x00); //демонтируем фат
PORTA = 3;
}
else
PORTA = 4;
while (1)
{
PORTA = 15;
}
}
- Вложения
-
- схема.png
- (3.71 КБ) 536 скачиваний


