Воспроизведение wav с помощью PIC
|
|
somlich |
Дата: Сб, 26.09.2009, 21:39 | Сообщение # 1 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Понимаю, что тема достаточно избитая, но все равно не пойму. В журнале радио за 2002 год №5,6,8 есть интересная статья "Автомобильный речевой информатор". В ней описывается запись звука в ЕПРОМ и воспроизведение. Еще нашел про речевой информатор "Гном": http://www.radiomaster.net/load/9-49/index.html . Если с процессом записи WAV в ППЗУ в журнале Радио рассказано вполне доступно, то вот как это воспроизводить с помощью PIC? И какой пик попроще можно использовать? Помогите кто чем может
|
|
|
|
Dmitry |
Дата: Сб, 26.09.2009, 22:47 | Сообщение # 2 |
Группа:
Пользователи
Ранг:
Могу и подсказать
Сообщений:
157
Замечания:
±
На сайте с 12.05.2009
Статус:
Offline
|
Да любой, у которого есть ШИМ (PWM по аглицки). Только WAV-ы лучше записывать не в ППЗУ, а во флеш-память с интерфейсом I2C, например серии 24Схх - их полно на любой размер и c ними очень просто работать из PBP командами I2CRead/I2CWrite. Звук в 8-битном формате читать из флеш-памяти и побайтно с заданной частотой отправлять на ШИМ командой HPWM. На выход ШИМ-а RC-цепочку и на усилитель (а то и сразу на динамик, если громкость не нужна).
|
|
|
|
somlich |
Дата: Вс, 27.09.2009, 20:55 | Сообщение # 3 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Quote (Dmitry) Да любой, у которого есть ШИМ (PWM по аглицки). Только WAV-ы лучше записывать не в ППЗУ, а во флеш-память с интерфейсом I2C, например серии 24Схх - их полно на любой размер и c ними очень просто работать из PBP командами I2CRead/I2CWrite. Звук в 8-битном формате читать из флеш-памяти и побайтно с заданной частотой отправлять на ШИМ командой HPWM. На выход ШИМ-а RC-цепочку и на усилитель (а то и сразу на динамик, если громкость не нужна). Огромное спасибо за пинок в нужном направлении Итак например микросхема:AT24C512-10PU-2.7 dip8 (EEPROM serial I2C 64Kx8) получается, что в ней 64Кбайта, не КБита? Дальше, у меня в микроконтроллере PIC 16F877 PWM уже используется для генерации сигнала с частотой 36 КГц (для подачи ИК сигнала). Соответственно код: Code 'Настройка pwn МК TRISC.2 = 0 ' CCP1 (PortC.2 = Output) PR2 = 137 CCPR1L = 69 CCP1CON = %00001100 ' Select PWM Mode T2CON = %00000100 ' Timer2 = ON + 1:1 prescale Могу ли я использовать 2 канал PWM в данном МК, и как? Читая справку на команду HPWM вычитал следующее: HPWM Channel,Dutycycle,Frequency Code DEFINE CCP2_REG PORTC ' Определяем порт для второго канала Hpwm DEFINE CCP2_BIT 1 ' Определяем вывод для второго канала Hpwm Этот код настраивает 2 канал PWM, дальше получается надо использовать для соотношения таймера 1 на второй канал PWM (т.к. 2 таймер я использую на первом канале) или этого не надо делать? Вернусь к команде HPWM Channel,Dutycycle,Frequency; Channel получается второй (2), Frequency - частота, мне нужно 8 КГц (т.к. звук я записал на этой частоте), а Dutycycle (скважность) - получается это тот байт который я считал с микросхемы памяти командой I2CRead? Если я правильно понял, то для того чтоб считать 20 байт и отправить их на выход PWM нужно записать код: Code q VAR byte 'Адрес в памяти My_Byte VAR byte 'Байт звука cont CON %10100000 'Константа для связи с микросхемой памяти
FOR q=1 to 20 I2CREAD PORTA.0,PORTA.1,cont,$A0+q,[My_Byte] 'Считываю последовательно с ячейки A0 20 байтов HPWM 2,My_Byte,8000 'Генерирую PWM сигнал на втором канале PWM с частотой 8 КГц next q Чувствую, что что-то не то, но проверить не могу, т.к. память еще не заказал, думаю какую. Вот и мучаюсь - сможет ли один МК генерировать 2 частоты, или для музыки ставить отдельный? В хелпе написано: Параметр Frequency - желательная частота сигнала PWM. На микроконтроллерах с 2 каналами, частоты в обоих каналах должны быть одинаковыми Еще вопрос, а как правильно рассчитать RC - цепочку
Сообщение отредактировал
somlich - Вс, 27.09.2009, 20:58
|
|
|
|
Dmitry |
Дата: Вс, 27.09.2009, 21:17 | Сообщение # 4 |
Группа:
Пользователи
Ранг:
Могу и подсказать
Сообщений:
157
Замечания:
±
На сайте с 12.05.2009
Статус:
Offline
|
Quote (somlich) Frequency - частота, мне нужно 8 КГц (т.к. звук я записал на этой частоте) Неправильно. Частота ШИМ к частоте дискретизации звука не имеет никакого отношения. За исключением того, что она должна минимум в несколько раз превышать максимальную частоту модулируемого сигнала. Иначе будут жуткие искажения. Это из той же серии, что и требование, чтобы частота дискретизации была минимум вдвое больше частоты оцифровываемого сигнала (теорема Котельникова, кажись). Поэтому 36 кГц ШИМ - отличный выбор для звука с максимальной частотой 4 кГц. Quote (somlich) На микроконтроллерах с 2 каналами, частоты в обоих каналах должны быть одинаковыми Кстати, это говорит о том, что таймер, скорее всего, один для обоих каналов ШИМ. А вот частота выполнения цикла чтения I2C и записи байта в ШИМ должна быть в точности равна 8 кГц - иначе звук будет ускоренным/замедленным. Добиться этого можно либо задержками в теле цикла либо прерыванием по таймеру с частотой 8 кГц - это на случай, если в процессе воспроизведения еще чего-то делать надо. Quote (somlich) Еще вопрос, а как правильно рассчитать RC - цепочку надо срезать все, что выше 4 кГц. Частота среза вроде 1/RC, т.е. в данном случае 100 нФ и 2,5 кОм, например.
|
|
|
|
somlich |
Дата: Вс, 27.09.2009, 21:38 | Сообщение # 5 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Quote (Dmitry) Поэтому 36 кГц ШИМ - отличный выбор для звука с максимальной частотой 4 кГц. Ну у меня звук можно записать с минимальной частотой 8КГц. Quote (Dmitry) А вот частота выполнения цикла чтения I2C и записи байта в ШИМ должна быть в точности равна 8 кГц - иначе звук будет ускоренным/замедленным. Добиться этого можно либо задержками в теле цикла либо прерыванием по таймеру с частотой 8 кГц - это на случай, если в процессе воспроизведения еще чего-то делать надо. Получается, что я могу запустить таймер 1 например, рассчитать его частоту равную 8 КГц (понять бы еще как) и в событие по прерыванию от таймера 1 считывать и воспроизводить? Тогда получается мой код рабочий? Единственно, что я не пойму, как правильно написать команду HPWM Почитал инет, нашел программу для расчета timer0, вот, что получилось на мой взгляд: Code 'Настройка pwn МК TRISC.2 = 0 ' CCP1 (PortC.2 = Output) PR2 = 137 ' Set PWM gпериод 36КГц CCPR1L = 69 CCP1CON = %00001100 ' Select PWM Mode T2CON = %00000100 ' Timer2 = ON + 1:1 prescale
'Настройка Timer0 МК примерно 8,06452 КГц INTCON = %00100000 ‘ Enable TMR0 interrupts OPTION_REG = %00000001 ‘ Initialise the prescale 1:4 TMR0 = 101‘ Load TMR0 register ON INTERRUPT GOTO ISR
'основная программа
DISABLE ‘ Disable further interrupts ISR:
считываю отправляю на ШИМ
INTCON.2 = 0 ‘ Re-enable TMR0 interrupts RESUME ‘ Return to main program ENABLE ‘ Enable interrupts Как отправить правильно на ШИМ
Сообщение отредактировал
somlich - Вс, 27.09.2009, 22:11
|
|
|
|
Dmitry |
Дата: Пн, 28.09.2009, 01:55 | Сообщение # 6 |
Группа:
Пользователи
Ранг:
Могу и подсказать
Сообщений:
157
Замечания:
±
На сайте с 12.05.2009
Статус:
Offline
|
Quote (somlich) Ну у меня звук можно записать с минимальной частотой 8КГц. Да у меня тоже. Но это частота оцифровки, т.е. частота, с которой измеряется и фиксируется мгновенная амплитуда сигнала . При этом максимальная частота сигнала (звука то бишь), которую можно передать такой оцифровкой, не может быть более половины частоты оцифровки, т.е. 4 кГц (см. теорему Котельникова). Quote (somlich) что я не пойму, как правильно написать команду HPWM А чем не устраивает тот код, что был в начале: HPWM 2,My_Byte,частота. Тут правда засада, в мануале на PBP написано, что макс. частота не более 32767 Гц. Цитата: The highest frequency at any oscillator speed is 32767Hz. Отсюда вопрос - первый ШИМ на 36 кГц работает не через команду HPWM? А вот этот кусок ,я так понимаю, нужен только при работе с ШИМом напрямую через регистры: TRISC.2 = 0 ' CCP1 (PortC.2 = Output) PR2 = 137 ' Set PWM gпериод 36КГц CCPR1L = 69 CCP1CON = %00001100 ' Select PWM Mode T2CON = %00000100 ' Timer2 = ON + 1:1 prescale т.е. команда HPWM на эти строки не смотрит и конфигурирует ШИМ по своему. Если 36 кГц критично, то, получается, HPWM вам вообще не подходит, а записывать байты в ШИМ2 надо через регистр CCPR2L, предварительно сконфигурировав этот ШИМ вручную. Вот эти строки не нужны, они вообще не для этого процессора: DEFINE CCP2_REG PORTC ' Определяем порт для второго канала Hpwm DEFINE CCP2_BIT 1 ' Определяем вывод для второго канала Hpwm DEFINE HPWM2_TIMER 1 Ага, и насчет прерывания по таймеру, первым делом в ISR надо опять присвоить TMR0 = 101, чтобы счетчик начал отсчет следующего периода с минимальным опозданием. А то у вас там вообще ему ничего не присваивается, т.е. он начнет считать с нуля и частота вызова прерываний будет совсем не 8 кГц
Сообщение отредактировал
Dmitry - Пн, 28.09.2009, 02:08
|
|
|
|
somlich |
Дата: Пн, 28.09.2009, 23:22 | Сообщение # 7 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Вот нашел интересный пример про использование PWM (в прикреплении). Там как раз есть запись в регистр. Получается, что код должен быть следующим: Code 'общие настройки PWM************************************************************ PR2 = 138 'Значение равное частоте 35 971,22302Hz примерно 36КГц T2CON = %00000100 'Timer2 = ON + 1:1 prescale
'настройка PWM канала 1 TRISC.2 = 0 'Выход PWM канала 1 CCP1CON = %00001100 'Select PWM Mode CCPR1L = 69 'Set PWM Duty-Cycle to 50%
'настройка PWM канала 2 TRISC.1 = 0 'Выход PWM канала 2 CCP2CON = %00001100 'Select PWM Mode
'Настройка Timer0 МК примерно 8,06452 КГц *************************************** INTCON = %00100000 'Enable TMR0 interrupts OPTION_REG = %00000001 'Initialise the prescale 1:4 TMR0 = 101 'Load TMR0 register ON INTERRUPT GOTO Time_UP 'Если произошло прерывание то переходим на метку
'объявление переменных ********************************************************** PWM2 VAR CCPR2L 'создаем ссылку на регистры 2 канала PWM MUSIC_START VAR byte[1] 'массив начальных адресов мелодий MUSIC_END VAR byte[1] 'массив конечных адресов мелодий Play VAR bit 'если 0 - не играть, если 1 то играть мелодию Music_N VAR byte 'номер проигрываемой мелодии Addr VAR byte 'счетчик адресов памяти My_Byte VAR byte 'Байт звука cont CON %10100000 'Константа для связи с микросхемой памяти I var byte 'переменная цикла
'запись начальных значений переменных ******************************************* 'начальные и конечные адреса мелодий в памяти ЕЕПРОМ MUSIC_START[0]=$01 MUSIC_END[0] =$3FF
MUSIC_START[1]=$401 MUSIC_END[1] =$10FF
'Определения I/O протов МК ****************************************************** TRISB=1 ' Установить все выводы PORTB на вход TRISA=1 ' Установить все выводы PORTA на вход ADCON1 = %00000110 ' Установим все выводы PORTA как цифровые.
MAIN: 'тело программы ***************************************************************** 'ну например:
if PORTA.0=0 then 'если была нажата кнопка на А0 то Music_N=0 'номер мелодии - 0 Addr=MUSIC_START[0]-1; 'начинаем проигрывать с ячейки $00 play=1 'разрешаем проигрывание мелодий for i=1 to 200 PAUSEUS 1 'противодребезгоавя пауза 200 мкс next I Endif
if PORTA.1=0 then 'если была нажата кнопка на А1 то Music_N=1 'номер мелодии - 1 Addr=MUSIC_START[1]-1; 'начинаем проигрывать с ячейки $400 play=1 'разрешаем проигрывание мелодий for i=1 to 200 PAUSEUS 1 'противодребезгоавя пауза 200 мкс next I Endif
GOTO MAIN
'********************************************************************************* DISABLE 'Disable further interrupts Time_UP: 'Метка обработчика прерывания TMR0 = 101 IF Play=1 then 'если проигрывать разрешено, то: Addr=Addr+1; 'увеличиваем на 1 переменную адреса в памяти IF Addr=MUSIC_END[Music_N] then 'следим, если подошел конечный адрес, то проигрывание заканчиваем play=0 goto End_Play Endif I2CREAD PORTB.0,PORTB.1,cont,Addr,[My_Byte] 'чтение байта из памяти ЕЕПРОМ PWM2=My_Byte 'присваиваем значение байта из памяти регистру второго канала PWM endif End_play: INTCON.2 = 0 'Re-enable TMR0 interrupts RESUME ' Return to main program ENABLE ' Enable interrupts Канал PWM номер 1 я использую для передачи сообщений через ИК (36 КГЦ) Т.е. переключаю его на выход на несколько мкс, потом на вход и опять пауза и так далее, таким образом передаю единицы и нолики. Поправьте пожалуйста в коде если что не правильно. Память куплю только в пятницу. Пока эксперименты теоретические. И последний вопрос - а можно в данный тип памяти писать непосредственно с компа, или обязательно посредник -МК???
Сообщение отредактировал
somlich - Пн, 28.09.2009, 23:24
|
|
|
|
Dmitry |
Дата: Ср, 30.09.2009, 02:21 | Сообщение # 8 |
Группа:
Пользователи
Ранг:
Могу и подсказать
Сообщений:
157
Замечания:
±
На сайте с 12.05.2009
Статус:
Offline
|
Да вроде на первый взгляд ошибок не видно. Ну ниче, запуск покажет. А с компа в память можно писать тем же программатором, что и пики шьет. Winpic800 и Ic-prog умеют. Только надо посмотреть схему включения I2C в программатор - скорее всего data и clock аналогично пику.
|
|
|
|
somlich |
Дата: Чт, 01.10.2009, 20:00 | Сообщение # 9 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Что то я ничего не пойму. Загнал схему ради интереса в протеус. Оказалось, что в базе элементов есть только AT24C1024, а у меня AT24C512. Ну думаю принцип то один. Оказалось, что ничего не работает. Даже простейший пример из хелпа по записи 10 байт и их считывании. Когда читает то пишет FF - то есть пустота. Получается ничего не записывает? Может контрольный байт для связи не тот, использую %10100000??? Уже второй вечер бьюсь. Может протеус виноват?
|
|
|
|
Dmitry |
Дата: Чт, 01.10.2009, 22:31 | Сообщение # 10 |
Группа:
Пользователи
Ранг:
Могу и подсказать
Сообщений:
157
Замечания:
±
На сайте с 12.05.2009
Статус:
Offline
|
Да нет, если читаешь тот же адрес, в который и писал, то должно работать. Контрольный байт правильный, А0. Там еще тонкость есть, надо читать доку на конкретную м/с памяти, у них запись производится блоками, т.е. 8 или 16 или еще сколько-то байтов за один раз (т.е. одной командой). Тоже может быть причиной. А так скорее всего протеус, я поэтому им стараюсь не пользоваться, мало мне своих глюков в программе, чтоб еще и его глюки разгребать. Вот операционники нравится моделировать, там все точно и наглядно.
|
|
|
|
somlich |
Дата: Чт, 01.10.2009, 22:43 | Сообщение # 11 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Блин заменил на 24FC512. вроде стало читать что надо. Но вот в динамике треск какой то. да и читает долго. По идее там 1секунда а читает с памяти секунды 3. Это что получается протеус или память медленная?
|
|
|
|
Dmitry |
Дата: Пт, 02.10.2009, 20:15 | Сообщение # 12 |
Группа:
Пользователи
Ранг:
Могу и подсказать
Сообщений:
157
Замечания:
±
На сайте с 12.05.2009
Статус:
Offline
|
Или комп не успевает. Загрузку ЦП протеус сколько показывает?
|
|
|
|
somlich |
Дата: Вс, 04.10.2009, 18:25 | Сообщение # 13 |
Группа:
Проверенные
Ранг:
Начал соображать
Сообщений:
35
Замечания:
±
На сайте с 23.02.2009
Статус:
Offline
|
Да 87% по моему. Да и не думаю что бы мой двухъядерник с 4 га памяти мог, хотя... В общем лучше соберу в железе - будет видно. Добавлено (04.10.2009, 18.25.27) --------------------------------------------- Я не знаю уважаемый Dmitry бываете ли вы на микрочиповском форуме, поэтому продублирую Итак собрал быстренько схему. Память AT24C512 тем же программатором на 3 резисторах. который использую и для прошивки МК (16F877) В таймере 0 с частотой 8 КГц считываю память и вывожу командой HPWM 1,My_Byte,24000 (с частотами пробовал играться от 8000 8КГц до 24000 24КГц сигнал становится как бы четче) на первый канал PWM МК. Звук записан с частотой 8КГц, моно, 8 бит/с. С выхода PWM1 (PORTC.2) подаю на вход LM386. В итоге в динамике звучит звук непонятного вида (в ссылке shuy_may) По длине вроде примерно такой же. Почему решил, что данные с памяти все таки считываются - т.к. если в программе закоментирвоать считывание то в динамике легкий свист. RC фильтр поставил 10 кОм последовательно и 100нФ - стало очень тихо и еще хуже. Как его расчитать этот фильтр. Или может проблема в другом? http://www.abinsk-school3.jino-net.ru/1/shut.wav (оригинал) http://www.abinsk-school3.jino-net.ru/1/shuy_may.wav (что получилось)
|
|
|
|