Все грустнее. Я ццс не знаю, мне проще на асме написать. Давайте я опишу сам принцип, а напишете Вы уже сами.
1. Откуда брать wav файл с нужной частотой и разрядностью. Неро - редактор wav файлов - сохранить как... Выбираем pcm, частоту 11025, разрядность 8 бит.
Затереть кодом тишины (0х80) в сохраненном файле нужно начало и конец,где идет служебная инфа. Дальше - все зависит от того, куда Вы инфу пихать будете - если в код на си, то преобразовать файл в текст можно программой
http://www.imeda.nm.ru/whothere/ отсюда. Если собираетесь заливать на какой-то носитель, то просто копируете.
2. Частота ШИМ.
Выбирается по 3 критериям
а)должна быть как можно большей
б)разрядность - 8 бит
в) в результате деления на целое число должна получиться частота квантования (например 11025).
Пример - у ссылке выше частота квантования 22050, частота клока 40 мегагерц - поэтому частота ШИМ выбирается 22050 * 7 (наше целое число ) = 154350 Герц. Для этой частоты PR2 вычисляется по формуле
1/( [PR2+1] *4* 1/40 000 000
что будет 63 с копейками. Реальная частота получится
(копейки в регистр занести не можем) 156250. Т.е. реальная частота квантования будет уже 156250/7 = 22321 Герц - вместо 22050. Ошибка в 200 Герц крамольной не является, на слух незаметно.
3. Настройки ШИМа - у тм2 есть прескалер и постскалер. В прескалер заносим 0, а в постскалер - это самое число 7. Таким образом, разрешив прерывание тм2, мы получим его с частотой 22321 Герц. В этом прерывании (не забываем, у нас 8 бит разрешения) старшие 6 бит, прочитанных из памяти, грузим в CCPR1L, а младшие 2 бита - в CCP1CON.
Например, так
Код:
|
// прочитанный из памяти байт находится в temp
//tmpCPP будет копироваться в CCP1CON
TMR2IF=0;
tmpCPP=temp;
//копируем для младших битов
tmpCCP=‹‹4;
// получили значение 2 младших битов
tmpCCP|=12;
// в регистре CCP1CON находится режим ШИМ, мы затерли
// при сдвиге , восстановили его, приб 0хС
temp››=2;
// получаем старшие 6 разрядов
CCPR1L=temp;
// копируем их в CCPR1L
CCP1CON=tmpCCP;
// отдаем младшие 2 разряда |
4. Эта схема будет работать, но будет воспроизводиться паразитная гармоника в 5,5 килогерц.
Чтобы этого избежать, выдачу проводят в 2 раза чаще,выдавая промежуточный вариант как среднее арифметическое предыдущего и текущих значений.
Цитата от IgorV
Код:
|
Ресамплирование на удвоение частоты получил как B[j]= ( A[j] + A[j-1] )/2
Где А - самплы исходной частоты, B - самплы вставляемые между исходными. Используются все.
Итого удвоение частоты. Кажущаяся чушь и примитивность реально оказывается гребенчатым фильтром
для частоты в половину от исходной. Т.е. Если самплы А были для выборки 11кГц, то писк на
частоте 5.5кГц подавляется прилично. Но возникает новый на частоте 11кГц, т.к. частота выборок
стала 22кГц. |
Как это будет работать - при суммировании 2 8-битовых регистров уже нужен 16 битовый , который затем сдвинем вправо на 1 разряд (деление на 2).
Теперь код от IgorV становится более понятным
Код:
|
if(!phase) // первый раз сюда
{
super=last;
temp= *ccptr;
ccptr++;
tmpCCP=(char)super‹‹4;
tmpCCP|=SNDCCP;
*(char*)(&super)››=2;
CCPR1L=(char)super;
CCP1CON=tmpCCP;
phase =1;
cntSnd--;
}
else
{
super=temp+last; // суперсамплинг с подавлением частоты 5.5кГц
last=temp;
super››=1;
tmpCCP=(char)super‹‹4;
tmpCCP|=SNDCCP;
*(char*)(&super)››=2;
CCPR1L=(char)super;
CCP1CON=tmpCCP;
phase=0; |
Думаю, что уже достаточно его комментировал.
В заключенье мой проект - на 628 пике чтение с ммс карточки, частота кварца - 20 мег, частота дискретизации 16 килогерц, частота шима - 64 килогерц, постскалер, соответственно, 2, частота срабатывания таймера - 32килогерца.
В аудио в протеусе звучит ужасно, но в железе - нормально.
Прикрепленный файл:
3842953.rar