Воспроизведение wav с помощью PIC - Форум Picbasic.ru
Регистрация | Вход
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Страница 1 из 11
Модератор форума: ivan_fd 
Форум Picbasic.ru » Программирование МК » PicBasicPro » Воспроизведение wav с помощью PIC
Воспроизведение wav с помощью PIC
somlich Дата: Сб, 26.09.2009, 21:39  |                                                                                                                Сообщение # 1
Группа: Проверенные
Ранг:  Начал соображать
Сообщений: 35
Репутация: 0   ±
Замечания:   ±
На сайте с 23.02.2009

Статус: Offline

Понимаю, что тема достаточно избитая, но все равно не пойму. В журнале радио за 2002 год №5,6,8 есть интересная статья "Автомобильный речевой информатор". В ней описывается запись звука в ЕПРОМ и воспроизведение. Еще нашел про речевой информатор "Гном": http://www.radiomaster.net/load/9-49/index.html .
Если с процессом записи WAV в ППЗУ в журнале Радио рассказано вполне доступно, то вот как это воспроизводить с помощью PIC? И какой пик попроще можно использовать? Помогите кто чем может sad
ЯНДЕКС Дата: 26.09.2009
Dmitry Дата: Сб, 26.09.2009, 22:47  |                                                                                                                Сообщение # 2
Группа: Пользователи
Ранг:  Могу и подсказать
Сообщений: 161
Репутация: 6   ±
Замечания:   ±
На сайте с 12.05.2009

Статус: Offline

Да любой, у которого есть ШИМ (PWM по аглицки). Только WAV-ы лучше записывать не в ППЗУ, а во флеш-память с интерфейсом I2C, например серии 24Схх - их полно на любой размер и c ними очень просто работать из PBP командами I2CRead/I2CWrite.
Звук в 8-битном формате читать из флеш-памяти и побайтно с заданной частотой отправлять на ШИМ командой HPWM. На выход ШИМ-а RC-цепочку и на усилитель (а то и сразу на динамик, если громкость не нужна).
somlich Дата: Вс, 27.09.2009, 20:55  |                                                                                                                Сообщение # 3
Группа: Проверенные
Ранг:  Начал соображать
Сообщений: 35
Репутация: 0   ±
Замечания:   ±
На сайте с 23.02.2009

Статус: Offline

Quote (Dmitry)
Да любой, у которого есть ШИМ (PWM по аглицки). Только WAV-ы лучше записывать не в ППЗУ, а во флеш-память с интерфейсом I2C, например серии 24Схх - их полно на любой размер и c ними очень просто работать из PBP командами I2CRead/I2CWrite.
Звук в 8-битном формате читать из флеш-памяти и побайтно с заданной частотой отправлять на ШИМ командой HPWM. На выход ШИМ-а RC-цепочку и на усилитель (а то и сразу на динамик, если громкость не нужна).

Огромное спасибо за пинок в нужном направлении smile

Итак например микросхема: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, дальше получается надо использовать
Code
DEFINE HPWM2_TIMER 1

для соотношения таймера 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 каналами, частоты в обоих каналах должны быть
одинаковыми sad

Еще вопрос, а как правильно рассчитать RC - цепочку cry

Сообщение отредактировал somlich - Вс, 27.09.2009, 20:58
Dmitry Дата: Вс, 27.09.2009, 21:17  |                                                                                                                Сообщение # 4
Группа: Пользователи
Ранг:  Могу и подсказать
Сообщений: 161
Репутация: 6   ±
Замечания:   ±
На сайте с 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
Репутация: 0   ±
Замечания:   ±
На сайте с 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
Группа: Пользователи
Ранг:  Могу и подсказать
Сообщений: 161
Репутация: 6   ±
Замечания:   ±
На сайте с 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
Репутация: 0   ±
Замечания:   ±
На сайте с 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 КГЦ)
Т.е. переключаю его на выход на несколько мкс, потом на вход и опять пауза и так далее, таким образом передаю единицы и нолики.

Поправьте пожалуйста в коде если что не правильно. Память куплю только в пятницу. Пока эксперименты теоретические.

И последний вопрос - а можно в данный тип памяти писать непосредственно с компа, или обязательно посредник -МК???

Прикрепления: hardpwm.bas(2Kb)

Сообщение отредактировал somlich - Пн, 28.09.2009, 23:24
Dmitry Дата: Ср, 30.09.2009, 02:21  |                                                                                                                Сообщение # 8
Группа: Пользователи
Ранг:  Могу и подсказать
Сообщений: 161
Репутация: 6   ±
Замечания:   ±
На сайте с 12.05.2009

Статус: Offline

Да вроде на первый взгляд ошибок не видно. Ну ниче, запуск покажет.
А с компа в память можно писать тем же программатором, что и пики шьет. Winpic800 и Ic-prog умеют. Только надо посмотреть схему включения I2C в программатор - скорее всего data и clock аналогично пику.
somlich Дата: Чт, 01.10.2009, 20:00  |                                                                                                                Сообщение # 9
Группа: Проверенные
Ранг:  Начал соображать
Сообщений: 35
Репутация: 0   ±
Замечания:   ±
На сайте с 23.02.2009

Статус: Offline

Что то я ничего не пойму. Загнал схему ради интереса в протеус. Оказалось, что в базе элементов есть только AT24C1024, а у меня AT24C512. Ну думаю принцип то один. Оказалось, что ничего не работает. Даже простейший пример из хелпа по записи 10 байт и их считывании. Когда читает то пишет FF - то есть пустота. Получается ничего не записывает? Может контрольный байт для связи не тот, использую %10100000??? Уже второй вечер бьюсь. Может протеус виноват?
Dmitry Дата: Чт, 01.10.2009, 22:31  |                                                                                                                Сообщение # 10
Группа: Пользователи
Ранг:  Могу и подсказать
Сообщений: 161
Репутация: 6   ±
Замечания:   ±
На сайте с 12.05.2009

Статус: Offline

Да нет, если читаешь тот же адрес, в который и писал, то должно работать. Контрольный байт правильный, А0. Там еще тонкость есть, надо читать доку на конкретную м/с памяти, у них запись производится блоками, т.е. 8 или 16 или еще сколько-то байтов за один раз (т.е. одной командой). Тоже может быть причиной. А так скорее всего протеус, я поэтому им стараюсь не пользоваться, мало мне своих глюков в программе, чтоб еще и его глюки разгребать. Вот операционники нравится моделировать, там все точно и наглядно. smile
somlich Дата: Чт, 01.10.2009, 22:43  |                                                                                                                Сообщение # 11
Группа: Проверенные
Ранг:  Начал соображать
Сообщений: 35
Репутация: 0   ±
Замечания:   ±
На сайте с 23.02.2009

Статус: Offline

Блин заменил на 24FC512. вроде стало читать что надо. Но вот в динамике треск какой то. да и читает долго. По идее там 1секунда а читает с памяти секунды 3. Это что получается протеус или память медленная?
Dmitry Дата: Пт, 02.10.2009, 20:15  |                                                                                                                Сообщение # 12
Группа: Пользователи
Ранг:  Могу и подсказать
Сообщений: 161
Репутация: 6   ±
Замечания:   ±
На сайте с 12.05.2009

Статус: Offline

Или комп не успевает. Загрузку ЦП протеус сколько показывает?
somlich Дата: Вс, 04.10.2009, 18:25  |                                                                                                                Сообщение # 13
Группа: Проверенные
Ранг:  Начал соображать
Сообщений: 35
Репутация: 0   ±
Замечания:   ±
На сайте с 23.02.2009

Статус: Offline

Да 87% по моему. Да и не думаю что бы мой двухъядерник с 4 га памяти мог, хотя... В общем лучше соберу в железе - будет видно.

Добавлено (04.10.2009, 18.25.27)
---------------------------------------------
Я не знаю уважаемый Dmitry бываете ли вы на микрочиповском форуме, поэтому продублирую wink
Итак собрал быстренько схему. Память 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 (что получилось)

Форум Picbasic.ru » Программирование МК » PicBasicPro » Воспроизведение wav с помощью PIC
Страница 1 из 11
Поиск: