Atmega8 рингтондары. MK AVR жүйесіндегі қарапайым дыбыстық сиреналар. Дыбыс модулін пайдалану

Мақалада AVR-де музыкалық синтездің принциптері сипатталған. Қосылған бағдарламалық құрал кез келген midi файлды түрлендіруге мүмкіндік береді көзіДайын әзірлемелерге музыкалық фрагменттерді ойнатуды қосу үшін AVR микроконтроллерлеріне арналған C тілінде. Музыкалық қорапта бағдарламалық құралды пайдалану мысалы қарастырылады.

Алдымен, бәрі қалай жұмыс істейтіні туралы қысқаша бейне:

Бағдарламалық қамтамасыз ету не мүмкіндік береді

ДК бағдарламалық құралы таңдалған midi файлды ойнататын CodeVision AVR үшін C көзін алуға мүмкіндік береді:

1. Жалпы\hxMidiPlayer.h, common\hxMidiPlayer.c файлдарын жобаңызға қосыңыз. ATMega8Example\melody.h, ATMega8Example\melody.c, ATMega8Example\hxMidiPlayer_config.h үлгілерін көшіріп, қосылыңыз.
2. MidiToC.exe файлын іске қосыңыз
3. Midi файлын жүктеңіз.
4. Ойнатқышты орнатыңыз: таңдау жылдамдығы, арналар саны, толқын пішіні, т.б.. Бағдарламалық құрал әуенді AVR ойнататындай етіп ойнатады.
5. “Ойнатқыш конфигурациясын жасау” түймесін басып, көзді hxMidiPlayer_config.h ішіне қойыңыз.
6. “Әуен кодын жасау” түймесін басып, көзді melody.c ішіне қойыңыз
7. Біздің жобада дыбысты PWM немесе сыртқы DAC арқылы шығару үшін Player_Output() әдісін енгіземіз.
8. Таймерді Іріктеу жылдамдығына орнатыңыз және үзілістен Player_TimerFunc() шақырыңыз.
9. Player_StartMelody(&s_melody, 0) қоңырау шалыңыз.

Әуен таймер үзуінен ойналады. Бұл ойнату кезінде микроконтроллер пайдалы жұмысты да орындай алатынын білдіреді.

Бұл қалай жұмыс істейді

Мақаланың қалған бөлігінде мен мұның бәрі қалай жүзеге асырылатынын қысқаша түсіндіруге тырысамын. Өкінішке орай, бұл өте қысқа болмайды - материал өте көп. Егер сізді қызықтырмаса, сіз бірден «Бағдарламалық құрал сипаттамасы» және «Ойнатқыш API» бөлімдеріне өте аласыз.

Музыка деген не

Музыка – әр түрлі жиіліктегі және ұзақтықтағы дыбыстардың тізбегі. Дыбыстың негізгі гармоникасының жиілігі белгілі бір нотаның жиілігіне сәйкес келуі керек. Дыбыстардың тербеліс жиілігі ноталардың жиілігінен ерекшеленетін болса, бізге музыкант «әуес емес» сияқты көрінеді.

Кесте. Жиіліктерге назар аударыңыз, Гц.

Барлық ноталар октаваларға бөлінген, әрқайсысында 7 нота + 5 жарты тон (фортепианодағы қара пернелер). Көрші октавалардағы ноталардың жиілігі дәл 2 есе ерекшеленеді.

Ең қарапайым музыка ойнатқышында әуеннің ноталарының реттілігі (нота + ұзақтығы) және нота жиіліктері бар кесте бар. Дыбысты синтездеу үшін меандрді құрайтын таймер арналарының бірі қолданылады:

Өкінішке орай, мұндай қарабайыр ойнатқышта нақты музыкалық аспаптарға онша ұқсамайтын тұрақты толқын пішіні (шаршы толқын) болады және бір уақытта тек бір нотада ойнай алады.

Нағыз әуен кем дегенде екі бөліктен тұрады (соло + басс) және фортепианода ойналғанда, келесі нота басталған кезде де алдыңғы нота дыбысталуын жалғастырады. Мұны пианино құрылымын есте сақтау арқылы түсіну оңай - әрбір нота жеке жолға сәйкес келеді. Қолдарымызды пернелердің үстіне апару арқылы бір уақытта бірнеше ішектің дыбысын шығара аламыз.

Кейбір микроконтроллерлерде бірнеше таймер арналары бар, оларды бір уақытта бірнеше нотаны ойнату үшін пайдалануға болады. Бірақ әдетте бұл арналар құнды ресурс болып табылады және олардың барлығын пайдалану ұсынылмайды. Әрине, біз жай ғана музыкалық жәшік жасап жатқанымыз болмаса.
Жалпы алғанда, полифонияны және музыкалық аспаптардың әртүрлі дыбыстарын алу үшін дыбыс синтезін қолдану керек.

AVR жүйесінде дыбыс синтезі

hxMidiPlayer аудио синтезін пайдаланады және әртүрлі толқын пішіндерімен полифонияны ойнай алады. Ойнатқыш 8-22 кГц жиіліктегі таймерді үзу өңдеуішіндегі шығыс сигналының амплитудасын есептейді (процессордың қанша қуаты жеткілікті; сонымен қатар толқын пішіні мен арналар санына байланысты).

Дыбыс синтезінің принципін синусоидты синтез мысалы арқылы түсіндіруге болады.

64 өлшемді кестені алайық, оның әрбір ұяшығында синус амплитудасының мәндері * 2 * PI / 64 (бір кезең) нүктелерінде жазылған:

Static const flash uint8_t s_sineTable[ 64 ] = ( 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x93,x95,x909,x 5, 0x95, 0x95, 0x94 , 0x93, 0x93, 0x91, 0x90, 0x8F, 0x8D, 0x8C, 0x8A, 0x88, 0x86, 0x84, 0x82, 0x80, 0x7E, 0x7C, 0x78, 0x70, 0x70, , x7 1, 0x70, 0x6F, 0x6D, 0x6D, 0x6C, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6C, 0x6D, 0x6D, 0x6F, 0x70, 0x71, 0x73, 0x74, 0x78, E70, 00);

128 (0x80) нөлге, 255 (0xff) ең үлкен оң нүктеге, 0 ең үлкен теріс нүктеге сәйкес келеді.

Енді кестеден мәндерді 1000 Гц жиілікте шақырылған таймер үзілісінде сыртқы DAC-ға шығарамыз делік:

Статикалық uint8_t s_index = 0; // Таймер1 шығысын салыстыру Үзіліс қызметінің ретті үзілуін үзу timer1_compa_isr(void) ( SetDac(s_sineTable[ s_index]); if (s_index == 63) ( s_index = 0; ) else ( s_index++; ) )

Нәтижесінде біз не аламыз? Біз 1000/64 Гц жиіліктегі синусоидалы тербелістерді аламыз.

Енді үзілістегі индексті 1-ге емес, екіге көбейтейік.
Әлбетте, шығыс тербеліс жиілігі қазірдің өзінде 1000/64 * 2 Гц болады.

Жалпы, F жиілігін алу үшін кестедегі индексті келесі жолмен көбейту керек:
қосу = F / 1000 * 64

Бұл сан бөлшек болуы мүмкін, бірақ жоғары жылдамдықты алу үшін бекітілген нүктелік арифметика қолданылады.

Кестедегі жазбалар саны және таймер жиілігі синтезделген дыбыстың сапасына әсер етеді. Біздің жағдайда бір кезеңге кестедегі 64 жазба жеткілікті, ал таймер жиілігі 12 кГц. Ең аз рұқсат етілген таймер жиілігі 8 кГц, идеалы 44 кГц.

Әлбетте, таймер жиілігі 12 кГц болғанда, біз ең көбі 6 кГц шаршы толқындарды жасай аламыз, өйткені біз бір периодқа кемінде екі қосқыш жасауымыз керек. Дегенмен, әрбір таймер белгісінде шығыс күйі дұрыс есептелсе, жоғары жиіліктерді әлі де тануға болады.

Кестеге синусоидалы емес тербеліс периодының мәндерін енгізіп, басқа дыбыс алуға болады.

Әлсіреу

Егер музыкалық аспап ішектерге негізделген болса (мысалы, фортепиано), онда пернені басқаннан кейін дыбыс біркелкі өшеді. Табиғи синтезатор дыбысын алу үшін нота басталғаннан кейін тербелістердің амплитудасын біркелкі азайту керек («дірілдерді әлсірету формасына ораңыз - «конверт»).

Ойнатқышта нота басталған сәттен бастап синус амплитудасын (немесе басқа толқын пішінін) азайту үшін пайдаланатын ыдырау кестесі бар.
Мұндай қабықшаға «оралған» «синус» механикалық музыкалық қораптың дыбысына ұқсайды.

Меандр синтезі

Меандр толқынының ерекше пішіні синтезді айтарлықтай жеңілдетуге мүмкіндік береді. Бұл жағдайда кестелер пайдаланылмайды. Ағымдағы таймер белгісінде берілген жиілікте шығыс қандай күйде (1 немесе 0) болуы керектігін есептеу жеткілікті. Бұл бүтін арифметика арқылы орындалады және өте жылдам жұмыс істейді, бұл 8-биттік приставкаларда әуендерді ойнату үшін шаршы толқынды пайдаланудың танымалдылығын түсіндіреді.

Мысалы: есептегішті жариялау:

Статикалық uint16_t s_counter = 0;

әрбір таймер үзілісінде біз 0x8000 көбейтеміз және есептегіштің ең маңызды биті портқа шығарылады:

// Таймер1 шығысын салыстыру Үзіліс қызметінің ретті үзілісі void timer1_compa_isr(void) ( PORTA.0 = (s_counter >> 15) & 1; s_counter += 0x8000; )

0x8000 + 0x8000 = 0x10000 болғандықтан, s_counter айнымалысы толып кетеді, 17-ші бит жойылады және айнымалыға 0x0000 жазылады.
Осылайша, таймер жиілігі 8 КГц болғанда, шығыс 4 КГц шаршы толқын болады.
Есептегішті 0x4000 көбейтсеңіз, сіз 2 кГц квадрат толқын аласыз.

Жалпы, F жиілігін қосу арқылы алуға болады:
қосу = F / 8000 * 0x10000

Мысалы, 1234 Гц жиілігі бар шаршы толқынды алу үшін 0x277C қосу керек. Нақты жиілік берілгеннен аздап ерекшеленеді, өйткені біз терминді бүтін санға дейін дөңгелектейміз. Бұл синтезаторда қолайлы.

Нағыз аспаптар дыбыстарының синтезі

Фортепиано алдында нота дыбысын цифрлауға болады (дыбыс амплитудасының мәндерін жадта тұрақты аралықпен сақтау үшін ADC көмегімен):
содан кейін дыбысты ойнатыңыз (жазылған мәндерді тұрақты аралықпен шығару үшін DAC көмегімен).

Жалпы, барабандарды синтездеу үшін барабан дыбыстарын жазып алып, қажетті уақытта ойнату керек. 8 биттік консольдерде барабан дыбыстарының орнына «ақ шу» пайдаланылады. «Ақ шу» үшін амплитудалық мәндер генератордың көмегімен алынады кездейсоқ сандар. Жад құны минималды.
hxMidiPlayer барабан синтезі үшін «ақ шуды» пайдаланады.

Арналарды араластыру

Берілген таймер белгісіндегі дыбыс амплитудасы әрбір арна үшін бөлек есептеледі. Соңғы амплитудалық мәнді алу үшін барлық арналардың мәндерін қосу керек. Дұрыс, қосындыны реттеу керек, өйткені қабылданатын дыбыс логарифмдік тәуелділікке бағынады, бірақ мұндай қарапайым синтезаторда қарапайым қосумен айналысуға тура келеді. Сондықтан әрбір арнаның максималды амплитудасы 255/Н құрайды.

AVR жүйесінен дыбыс шығарылуда

Барлық қажетті есептеулерді орындағаннан кейін ойнатқыш аналогқа түрлендіру қажет сигнал деңгейін алады. Осы мақсаттар үшін сыртқы DAC немесе PWM пайдалануға болады.
Бұл жерде айта кететін жайт, екі жағдайда да қабылданған сигналды сүзгіден өткізген жөн – синтездің және дөңгелектенудің төмен жиілігіне байланысты пайда болатын жоғары жиілікті шуды жою.

Сыртқы параллель DAC шығысы

Дәл DAC чиптерін пайдалану мағынасы жоқ болғандықтан, мұндай жобалар әдетте R2R матрицасын жасайды:

Бұл схема арқылы біз портқа есептелген амплитуданы шығарамыз:

PORTB = үлгі;

Кемшіліктері:
1) R2R матрицасының шығысы тым әлсіз сигнал, аналогты күшейткішті пайдалану міндетті болып табылады;
2) кем дегенде 5 түйреуіш (және жақсырақ 8) пайдалану қажет;
Бұл әдіс бос PWM арналары болмаған кезде ғана негізделген.

(тіректерді сақтау үшін SPI интерфейсі бар сыртқы ADC пайдалануға болады).

PWM

Егер тегін PWM арнасы болса, онда бұл әдісті қолданудың ең оңай жолы.

PWM инициализациясы (ATMega8):

// Таймер/есептегіш 2 инициализациясы // Сағат көзі: Жүйе сағаты // Сағат мәні: 20000,000 кГц // Режим: Жылдам PWM top=0xFF // OC2 шығысы: Инвертсіз PWM ASSR=0x00; TCCR2=0x69; TCNT2=0x00; OCR2=0x00; Ал үлгі шығысы: void Player_Output(uint8_t үлгісі) ( OC2 = үлгі. )

PWM пайдаланудың жалпы тәжірибесі RC сүзгісі арқылы шығыс сигналын тегістеуді қамтиды:

Өкінішке орай, сүзгіден кейін сигнал тым әлсірейді, сондықтан динамикті қосу үшін аналогтық күшейткіш жасау керек.

Схеманы жеңілдету үшін динамиктің өзіне дейін «цифрлық» болып қалу жақсы. Арзан динамик әлі де 30 кГц-тен жоғары жиіліктерді шығара алмайтындықтан, оларды сүзудің қажеті жоқ. Диффузордың өзі жоғары PWM жиіліктерін «сүзеді».

Егер сізге көбірек ток алу қажет болса, транзисторлық күшейткішті пайдалануға болады. R1 динамикті қажетті токпен қамтамасыз ету үшін таңдалады.

Ойыншықтардан кішкентай динамиктерді осылай қосуға болады:

Үлкен динамиктер үшін дискіні 2 транзистор арқылы жинап, шуды жою үшін LC сүзгісін орнатқан дұрыс:

C1 конденсаторы PWM жұмыс істемей тұрғанда динамик арқылы токты шектеу үшін қызмет етеді. Сондай-ақ, сериялы конденсаторды қосуға байланысты нөлге қатысты симметриялы сигнал динамикке жетеді. Осылайша, динамик конусы дыбыс сапасына оң әсер ететін орталық «босаңсыған» күйге қатысты қозғалады.
Бұл жағдайда транзисторлар ауысу режимінде жұмыс істейді, сондықтан базалық ығысуды өтеудің қажеті жоқ.

PWM, екі істікшелі қосылым

Алғашқы екі тізбектің кемшілігі динамик бір бағытта токпен қамтамасыз етіледі. Токтың бағытын өзгертсек, рұқсат етілген қуаттан аспай, көлемді 2 есе арттыруға болады. Ол үшін динамик микроконтроллердің екі түйреуішіне қосылған – инверттелмеген және инверттелген, мысалы, OC1A және /OC1A. Төңкерілмеген шығыс болмаса, екінші арнаны инверттелген режимде (OC1B) пайдалануға болады:

// Таймер/санауыш 1 инициализациясы // Сағат көзі: Жүйе сағаты // Сағат мәні: 24500 000 кГц // Режим: Fast PWM top=0x00FF // OC1A шығысы: Inv емес. // OC1B шығысы: Төңкерілген // Шуды болдырмайтын: Өшірулі // Құлаған жиекте кіріс түсіру // Таймер1 толып кету үзілуі: Өшірулі // Кіріс түсіру үзілуі: Өшірулі // Сәйкестік үзілуін салыстыру: Өшірулі // B сәйкестік үзілуін салыстыру: Өшірулі TCCR1A =0xB1; TCCR1B=0x09; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; void Player_Output(uint8_t үлгісі) ( OCR1A = үлгі; OCR1B = үлгі; )

PWM, екі түйреуіш, D класты күшейткіш

Ұсынылған схемалардың кемшілігі - үнсіздік кезіндегі ток тұтынуы.
Біз үшін «үнсіздік» 128 сигнал деңгейіне сәйкес келеді, яғни 50% толтырылған PWM - ток әрқашан динамик арқылы өтеді!

Бағдарламалық жасақтаманы сәл өзгерту арқылы сіз айтарлықтай қуатты бағдарламалық жасақтаманы және D класындағы аппараттық күшейткішті ала аласыз:

Void Player_Output(uint8_t үлгісі) ( егер (үлгі >= 128) ( TCCR2=0x21; //қалыпты, салыстырмалы сәйкестікте анық TCCR2=0x21 | 0x80; //CLEAR OC2 PORTC.0 = 0; TCCR2=0x69; //жоқ -инверттеу PWM OCR2 = (үлгі-128) * 2; ) else // егер (үлгі)< 128) { TCCR2=0x31; //normal, set on compare match TCCR2=0x31 | 0x80; //SET OC2 PORTC.0 = 1; TCCR2=0x79; //inverting PWM OCR2 = (128-sample) *2; } }

Бұл жағдайда транзисторлардың бір жұбы PWM шығысына, екіншісі - тұрақты сандық шығысқа қосылады.

Кодтан көріп отырғанымыздай, 128-ден жоғары сигналды бір бағытқа бағытталған ток деп, ал 128-ден төмен сигналды басқа бағытқа бағытталған ток деп қарастырамыз. 128-де екі динамик түйреуіштері бірдей қуат көзіне қосылған және ток жоқ. 128-деңгейден ауытқыған кезде PWM толтырылуы артады және динамик арқылы сәйкес полярлық ток өтеді.

Іске асырудағы маңызды сәт екінші (тұрақты цифрлық) пин (PORTC.0) ауысу сәтінде PWM шығысын қажетті күйге мәжбүрлеп ауыстыру болып табылады. OCR2 регистріне жазу PWM ақауларын жою үшін буферленген. Біз кезеңнің аяқталуын күтпестен, PWM шығысын дереу ауыстыруымыз керек.

Соңғы схема IMHO қарапайымдылығы, энергияны үнемдеу және қуат шығысы тұрғысынан ең жақсы нұсқа болып табылады.

SquareWave толқын пішінімен дыбыс шығару

Меандрді синтездеу кезінде жеңілдетілген алгоритмдер қолданылады.

Әрбір арна (соның ішінде барабандар) 0 немесе 1 шығарады. Осылайша, 3 арналы айналмалы табақ 0..3 ауқымындағы мәндерді шығарады. Сондықтан, PWM пайдалану кезінде шығыс процедурасы келесідей болады:

Жарамсыз Ойнатқыш_Шығыс(uint8_t үлгісі) ( OCR2 = үлгі * (255 / HXMIDIPLAYER_CHANNELS_COUNT); )

Егер сіз PWM қолданбасаңыз, 3 арналы әуенді шығару үшін екі қарапайым сандық шығыс және 2 биттік R2R матрицасы жеткілікті.

MIDI пішімі

Алынған әуен кодын қарасаңыз, массив шағын ауқымдағы қайталанатын сандарды пайдаланатынын оңай көре аласыз. Бұл түсінікті: әуен 1-2 октава шегінде шектеулі ноталар санын пайдаланады, әуен қарқыны бекітілген – кешігулер тең, арналар саны 0..15 диапазонында.
Мұның бәрі қысу алгоритмінің қандай да бір түрін қолдану арқылы алынған массивті айтарлықтай азайтуға болатындығын білдіреді.
ZIP сияқты алгоритмдер жақсы қысуды қамтамасыз етеді, бірақ жұмыс істеу үшін көп жад қажет (ZIP сөздігі - 64 Кб). Біз іс жүзінде ешқандай жадты қажет етпейтін өте қарапайым қысу әдісін пайдалана аламыз, оның мәні келесідей.

Бір байтта барлық сандар 0...255 диапазонында біркелкі таралады және әрбір сан 8 битпен көрсетіледі. Біздің жағдайда кейбір сандар басқаларға қарағанда әлдеқайда жиі кездеседі. Жиі кездесетін сандарды азырақ битпен, ал сирек кездесетін сандарды көбірек кодпен кодтасаңыз, жадты арттыруға болады.

Біз бекітілген кодтау әдісін таңдаймыз: 000,001 және 010 биттерінің комбинациясы (ұзындығы - 3 бит) ең жиі кездесетін 3 санды білдіреді. 0110, 0111 бит комбинациялары (ұзындығы – 4 бит) – келесі 2 жиі кездесетін сандар және т.б.:

//000..010 - 0..2 //011 x 3..4 //100 xx 5..8 //101 xxx 9..16 //110 xxx 17..24 //111 бірден

111-ден басталатын комбинация (ұзындығы – 11 бит) барлық басқа сандарды кодтайды.
Битті кодтау әдісі әртүрлі болуы мүмкін. Мен бірнеше әдістерді қолданып көрдім және осындай деректер бойынша ең жақсы нәтиже беретін осы әдісті таңдадым.

Қысу процедурасы келесідей көрінеді:
1. Х = үшін ағындағы X санының жалпы санын есептеңіз.
2. Ағында пайда болу жиілігін азайту бойынша сұрыптау.
3. Алғашқы 25 санды алыңыз. Олар азырақ биттермен кодталады.
4. Кіріс ағынын кодтаңыз.

Шығару ең жиі кездесетін 25 сан мен бит ағынының массиві болып табылады.
Бұл қысу жад пен өнімділік шығындарының аз болуымен 50% қысуға қол жеткізуге мүмкіндік береді. Өкінішке орай, бұл ойнатқыш кодын арттырады, сондықтан қысқа әуендер үшін қысу ұсынылмайды.

Жазба жиіліктерін сақтау

Кестедегі барлық ноталардың жиіліктерін жадтан сақтау өте қымбат. Іс жүзінде нотаның жиілігін оның миди саны бойынша анықтау формуласы бар:

F = 2^((N - 69)/12) * 440, Гц

Бірақ бөлшек қуатты есептеу өте қиын. Оның орнына ойнатқыш жоғарғы октавада 12 нота жиілігін сақтайды. Төменгі октавалардағы ноталардың жиілігі жиілікті тағы 2^Y есе азайту арқылы анықталады, мұнда Y - октавалардың төмен саны.

Компрессияның одан әрі дамуы

Әуенде жиі қайталанатын үзінділер («хор», «өлеңдер») болады. Қайталанатын фрагменттерді тауып, әуенді үзінділер түрінде ұсыну арқылы сіз уақытты жұмсамай, әуенді тағы 50%-ға азайта аласыз. Жедел Жадтау Құрылғысыжәне өнімділік. Мен жобаны қиындатпау үшін мұндай алгоритмді жүзеге асырмадым.

Бағдарламалық қамтамасыз ету сипаттамасы

Конвертер бағдарламасының негізгі терезесі:

Load Midi түймесі midi файлын жүктеуге мүмкіндік береді. Бағдарлама дереу таңдалған параметрлермен файлды ойната бастайды, аппараттық құралда болатын дыбысты имитациялайды.

Ақпараттық терезе (4) көрсетеді:
– Length – таңдалған әуен фрагментінің мс-дегі ұзындығы;
– Max Active синтезатор арналары – бір уақытта белсенді синтезатор арналарының максималды саны;
– Максималды белсенді барабан арналары – «барабандарды» шығаратын бір уақытта белсенді синтезатор арналарының ең көп саны;
– Максималды белсенді стерео ноталар – бір нотаны шығаратын арналардың ең көп саны (төменде қараңыз);
– Болжалды өлшем, байт – байттағы әуен өлшемі. «Таңдамалы үлгі» режимінде өлшем A+B түрінде көрсетіледі, мұнда A – әуен өлшемі, B – үлгі өлшемі. Ойыншы кодының өлшемі мұнда көрсетілмеген.

Орындалу барысы терезесі ағымдағы ойнату орнын көрсетеді.
Көрсетілген нүктеден ойнатуды бастау үшін орындалу барысы жолағын басуға болады.
Сол және оң жақтағы енгізу өрістері әуен фрагментінің басы мен соңын мс-де көрсетуге мүмкіндік береді.

Қызыл түспен «Әуенді ойнату үшін арналар жеткіліксіз» белгісі әуенді ағымдағы параметрлермен ойнату үшін синтезатор арналары жеткіліксіз екенін көрсетеді. Ойнатқыш бос арнаны таппаса, ол ең ескі жазбаны өшіреді. Көптеген жағдайларда бұл жақсы жұмыс істейді. Әуен құлаққа дұрыс емес естілген кезде ғана арналар санын көбейту мағынасы бар.

Параметрлерді ойнатқыш параметрлері мен midi файлды өңдеу параметрлеріне бөлуге болады. Ойнатқыш конфигурациясы мен әуен коды бірдей ойнатқыш параметрлерімен жасалған болса, ойнатқыш алынған әуен кодын ойната алады. Бұған қоса, ойнатқыш арналар саны азырақ (бірақ көп емес) ойнатқыш үшін коды жасалған әуенді ойнай алады.

Ойнатқыштың жабдық параметрлері мыналарды қамтиды:

– Sampling Rate – синтез жиілігі. Біріктірудің максималды жиілігі эксперименталды түрде анықталады. Atmega 16 МГц негізінде 6 арнасы бар ойнатқыш үшін 12000 Гц жиіліктен бастай аласыз және оны аппараттық ойнатқышта әуеннің бұрмалануы байқалғанша қалағаныңызша арттыра аласыз. Максималды жиілік арналар санына, толқын пішініне және әуеннің күрделілігіне байланысты.

– толқын пішіні – толқын формасы:
– шаршы толқын – меандр;
– синус – синус;
– Синус + Конверт – әлсіреуі бар синус;
– Waveform * + Envelope – әлсіреуі бар және онсыз синусоидалы емес толқындардың әртүрлі нұсқалары;
– Custom Sample – құрал үлгісін пайдаланыңыз.

«Үлгіні жүктеу» түймесі WAV файлынан үлгіні жүктеуге мүмкіндік береді. WAV файлы PCM 8 биттік моно, 4173 Гц, C-5 болуы керек. Нұсқау: Жиілікті арттырып, жазбаны төмендетуге болады, бірақ ойнатқыш параметрлерінде Pitch параметрін өзгертуге болады. Пішім тексерулері жоқ - пішім басқа болса, дыбыс дұрыс ойнатылмайды.
Pitch – дыбыс биіктігін өзгертуге мүмкіндік береді. Мысалы, 1 октава жоғары ойнау үшін Pitch +12 параметрін орнату керек.

Қысуды пайдаланыңыз – әуенді қысуды пайдаланыңыз.
Барабан синтезаторын қосу – барабан синтезаторын қосыңыз.

Ойнатқыш арналары: синтезатор арналарының саны (бір уақытта дыбыс шығаратын ноталардың ең көп саны).

Midi файлды өңдеу параметрлері мыналарды қамтиды:

Әдетте, мұндай дәл баптау қажет емес. Бұл параметрлерді әдепкі ретінде қалдыруға болады.

Ойыншының API

Ойнатқышты іске асыру Common\hxMidiPlayer.c және Common\hxMidiPlayer.h файлдарында орналасқан. Бұл файлдар жобаға қосылуы керек. Сондай-ақ, конфигурацияны орналастыру қажет hxMidiPlayer_config.h файлын жасау керек.
Ойнатқыш C тілінде құрастыру кірістірусіз жазылған, бұл оны басқа микроконтроллерлерге өткізуді жеңілдетеді.

Extern void Player_StartMelody(const flash TMelody* _pMelody, uint16_t _delay);

Әуенді ойнауды бастаңыз. _delay ойнату алдындағы бастапқы кідірісті орнатады, 255 бірлік = 1 секунд.

Void Player_Stop();

Әуенді ойнауды тоқтатыңыз.

Сыртқы bool Player_IsPlaying();

Әуен ойнап бітсе, жалған мәнін қайтарады.

Extern void Player_WaitFinish();

Әуен ойнап болғанша күтіңіз.

Extern void Player_TimerFunc();

Бұл функция конфигурацияда көрсетілген таңдау жылдамдығымен таймер үзілісінде шақырылуы керек. Әуен ойнап болған кезде, сізге қоңырау шалудың қажеті жоқ.

Extern void Player_Output(uint8_t үлгісі);

Пайдаланушы жүзеге асыруы керек. Келесі үлгіні шығару қажет болғанда ойнатқыш шақырады.

Extern void Player_Started();

Пайдаланушы жүзеге асыруы керек. Ойыншы әуенді ойнай бастағанда шақырылады. Таймер үзілістерін конфигурациялау үшін пайдалануға болады.

Extern void Player_Finished();

Пайдаланушы жүзеге асыруы керек. Ойыншы әуенді ойнап болған кезде шақырылады. Оны таймер үзілістерін өшіру немесе басқа әуенді ойнатуды бастау үшін пайдалануға болады.

//#NOTES_TO_EEPROM анықтау //#SINETABLE_TO_EEPROM анықтау //#ENVELOPE_TO_EEPROM анықтау

Егер ескертпелер кестесі, синустар кестесі және әлсіреу кестесі eeprom ішінде орналасуы қажет болса, hxMidiPlayer_config.h файлында бұл жолдарға түсініктемелер алынбауы керек.

Мысал жобалар

ATMega644Example – PB3 бойынша ATMega644, 25МГц, PWM шығысына арналған жоба.

Жад талаптары

Кесте. Ойнатқыштың өлшемі және жарқылдағы әуендер.

*бар бос емес жобаға ойнатқышты қосқанда, код өлшемі кішірек болады

**әуенді қалыпты ойнату үшін арналар жеткіліксіз

1-әуен: bach_minuet_in_g.mid, 35 сек
2-әуен: yiruma-river_flows_in_you.mid, 165 сек
3 әуен: Франц Шуберт – Serenade.mid, 217 сек

Кестеден көріп отырғаныңыздай, ең аз конфигурацияда сіз тіпті ATTiny2313 ішіне де жеткілікті ұзын әуенді сығып аласыз. Қысу әуенді екі еседен астам азайтуы мүмкін, бірақ ойнатқыш кодының өлшемі ~600 байтқа артады.

Синус және ыдырау жазба кестелерін шамамен 16, 50 және 100 байт жарқылды үнемдей отырып, EEPROM ішінде орналастыруға болады.

wav файлынан үлгіні пайдаланған кезде ойнатқыш кодының өлшеміне байттағы үлгі өлшемін қосу керек.

Қолдану мысалы

Ойнатқышты пайдаланудың мысалы ретінде музыкалық қорапты жасау процесін қарастырайық.

Біз дайын MDF қорабын аламыз:

Микроконтроллер ретінде біз SO-8 пакетіндегі ATTiny85-ті ең арзаны ретінде жеткілікті үлкен жады көлемімен аламыз. 4 Sine+Envelope арналарымен 18КГц синтез жиілігін алу үшін оны 27МГц-ке дейін үдетеміз.

Күшейткіш батареяларды үнемдеу үшін 4 транзисторы бар D класты болады.

Транзисторлар коммутациялық режимде жұмыс істейді және кез келген типті болуы мүмкін. Жоғары жиілікті шусыз дыбыс алу үшін L1 индукторы мен C6 конденсаторы талғамға сәйкес таңдалады. R1 және R2 дыбыс деңгейін төмендету және динамиктің серпілісін азайту үшін 2K дейін көтеруге болады.

Диск жетегіндегі шектеу қосқышы қорап үшін арнайы жасалған сияқты өте жақсы сәйкес келеді (ол ашу үшін жұмыс істейді - қақпақты ашқан кезде тақтаға қуат беріледі):

Микробағдарлама көздері ATTiny85MusicBox каталогында орналасқан.

8 Кб сәйкес келеді:
1) ойнатқыш: 18000Гц, 4 арна, Синус+Конверт, Pitch+12, қысу, әуендерді бір-бірлеп ойнатады (соңғысы EEPROM-да сақталады)
2) Йирума - өзен сізде ағып жатыр
3) Франц Шуберт – Серенада
4) П.И. Чайковский «Қазан»

Бейнедегі нәтиже:

Әрі қарай дамыту

Негізінде, ойнатқышты толыққанды Midi немесе MOD ойнатқышына жеткізе отырып, одан әрі дамытуға болады. Менің ойымша, жоғары сапалы әуенді алу үшін SD картасын қосу және одан кез келген WAV файлдарын ойнату оңайырақ болар еді. ең жақсы сапаәдетте бағдарламалық қамтамасыз ету синтезі арқылы алуға болады. Ал мұндай ойнатқыш бағдарламалық және аппараттық құралдарда әлдеқайда қарапайым. HxMidiPlayer ұясы бірнеше аяқтар қалғанда және жарқылда аз орын қалғанда дайын жобаларға жақсы дыбыс қосады. Ол бұл тапсырманы бұрыннан бар түрінде «өте жақсы» жеңеді.

Менің ойымша, бұл AVR-де барлық музыкалық қораптарды/қоңырауларды жасау мәселесін жабуы мүмкін :)

Сабақты жалғастыру ұзаққа созылды, бұл түсінікті, мен жад карталарымен және файлмен жұмыс істеуді меңгеруім керек болды. FAT жүйесі. Бірақ бәрібір, бұл болды, сабақ дайын - шын мәнінде, жаңа жылдық керемет.

Мақаланы ақпаратпен шамадан тыс жүктемеу үшін мен wav файл пішімінің құрылымын сипаттамаймын, іздеу жүйелерінде ақпарат жеткілікті. Егер файлды Hex редакторының қандай да бір түрімен ашсаңыз, онда алғашқы 44 байт файл түрі, іріктеу жылдамдығы, арналар саны және т.б. туралы барлық ақпаратты қамтиды. Егер сізге файлды талдау қажет болса, мынаны оқыңыз. тақырыбы және сіз бақытты боласыз.

Пайдалы жүктеме деректері негізінен дыбысты құрайтын кернеу деңгейлерін қамтитын 44 байттан басталады. Біз сабақтың соңғы бөлігінде кернеу деңгейлері туралы айттық. Осылайша, бәрі қарапайым, бұл қадамдарды файлды таңдау жиілігінде динамикке шығару керек.

Динамикті физикалық түрде қалай шайқауға болады? Бұл кернеу деңгейлерін PWM немесе R2R арқылы шығару керек. Қалай болғанда да, оны пайдалану өте қарапайым, нөмірді оқыңыз, оны OCR немесе PORTx ішіне қойыңыз. Содан кейін, белгілі бір уақыттан кейін мен келесі мәнді ауыстырдым және файлдың соңына дейін солай жалғастырдым.

Мысалы, белгілі бір wav файлы, деректер 44=0х2С байттан келеді, онда 0х80 саны жазылады, дыбысты қайта шығарамыз, мысалы, бірінші таймердің PWM арқылы, OCR1A=0x80 деп жазыңыз; Үлгі таңдау жиілігі 8 кГц делік, сондықтан үзіліс бірдей жиілікке орнатылуы керек. Үзілісте 1/8000 = 125 мкс кейін келесі 0x85 мәнін ауыстырыңыз.

Үзіліс жиілігін 8 кГц-ке қалай орнатуға болады? Егер таймер 250 кГц жиілікте жұмыс істейтін болса, онда үзілістерді салыстыру регистрін (250/8)-1=31-1 немесе 0x1E ауыстыру керек екенін еске түсірейік. PWM-де бәрі де қарапайым; ол жұмыс істейтін жиілік неғұрлым жоғары болса, соғұрлым жақсы.

Микробағдарлама жұмыс істеуі үшін флэш-диск 23.2-сабақтағы PetitFat lib арқылы FAT32 форматында пішімделгенімен келісеміз. Файл wav пішімінде, 8кГц немесе 22,050кГц, моно. Файл атауы 1.wav. Микробағдарламаны талдап көрейік.

#қосу #include "diskio.h" #include "pff.h" белгісі жоқ таңба буфері[512 ] ; /* флэш-дискіден ақпарат көшірілетін буфер */өзгермелі қолтаңбасыз инт саны; //көшірілген деректер есептегішіүзу [TIM2_COMP] void timer2_comp_isr(жарамсыз) //мәндер ауыстырылатын үзіліс( OCR1A = буфер[ санау] ; // дыбысты динамикке шығаруегер (++ саны >= 512 ) //есептегішті ұлғайтусанау = 0; //егер 512 қалпына келтірілсе) void main(void) ( unsigned int br; /* файлды оқу/жазу есептегіші */ unsigned char buf = 0; //буфердің қай бөлігі оқылатынын анықтайтын айнымалы FATFS fs; /* Логикалық дискілерге арналған жұмыс кеңістігі (файлдық жүйе нысаны) */ PORTB= 0x00 ; DDRB= 0x02 ; // jump shim ocr1a // Таймер/санауыш 1 инициализациясы// Сағат көзі: Жүйе сағаты // Сағат мәні: 8000 000 кГц // Режим: Fast PWM top=0x00FF // OC1A шығысы: Inv емес. TCCR1A= 0x81 ; TCCR1B= 0x09 ; TCNT1= 0x00 ; OCR1A= 0x00 ; // Таймер/санауыш 2 инициализациясы// Сағат көзі: Жүйе сағаты // Сағат мәні: 250 000 кГц // Режим: CTC top=OCR2 TCCR2= 0x0B ; TCNT2= 0x00 ; //OCR2=0x1E; //8кГц үшін салыстыру регистрін орнату OCR2= 0xA ; //22кГц үшін #asm("sei") // Таймер(лар)/санауыш(тар) үзу(лар)ды баптандыруегер (disk_initialize() == 0 ) //флэш-дискіні инициализациялау( pf_mount(&fs) ; //тау файлдық жүйе pf_open("1.wav" ); //жіпті ашу pf_lseek(44) ; //меңзерді 44-ке жылжытыңыз pf_read(буфер, 512,& br); //алғаш рет 512 байтты бірден жұтамыз TIMSK= 0x80 ; //музыканы қосу (1) (егер (! buf && count> 255 ) //егер 255 байттан көп шығарылса,( pf_read(& буфер[ 0 ], 256,& br); //содан кейін біз флэш-дискідегі ақпаратты буфердің бірінші жартысына оқимыз buf= 1 ; егер (бр< 256 ) //егер буферде 256 мән болмаса, бұл файлдың соңын білдіредіүзіліс; ) егер (буф && санау< 256 ) { pf_read(& buffer[ 256 ] , 256 ,& br) ; // флэш-дискіден буфердің екінші бөлігін оқыңыз buf = 0; егер (бр< 256 ) break ; } } TIMSK = 0x00 ; //глушим все pf_mount(0x00 ) ; //параны бөлшектеңіз) ал (1 ) ( ) )

#қосу #include "diskio.h" #include "pff.h" таңбасыз таңба буфері; /* флэш-дискіден ақпарат көшірілетін буфер */ ұшпа unsigned int count; //көшірілген деректердің санауышы үзіліс уақыты жоқ timer2_comp_isr(void) //мәндер ауыстырылатын үзіліс ( OCR1A = буфер; //егер (++санау >= 512) болса, динамикке дыбыс шығару //санауыш санын көбейту = 0; //егер 512 қалпына келтіру ) void main(void) ( unsigned int br; /* файлды оқу/жазу есептегіші */ unsigned char buf = 0; //буфердің қай бөлігі оқылатынын анықтайтын айнымалы FATFS fs; /* Жұмыс логикалық дискілерге арналған аймақ (файлдық жүйе нысаны) */ PORTB=0x00; DDRB=0x02; //шим ocr1a секіру // Таймер/Counter 1 инициализациясы // Сағат көзі: Жүйе сағаты // Сағат мәні: 8000 000 кГц // Режим: Fast PWM top=0x00FF // OC1A шығысы: Inv емес TCCR1A=0x81; TCCR1B=0x09; TCNT1=0x00; OCR1A=0x00; // Таймер/есептегіш 2 инициализациясы // Сағат көзі: Жүйе сағаты // Сағат мәні : 250,000 кГц // Режим: CTC top= OCR2 TCCR2=0x0B; TCNT2=0x00; //OCR2=0x1E; //салыстырмалы регистрді 8кГц OCR2=0xA үшін орнату; //22кГц үшін #asm("sei") // Таймер(лар)/санауыш(тар) үзу(лар) инициализациясы if(disk_initialize()==0) //флэш-дискіні инициализациялау ( pf_mount(&fs); //файлдық жүйені орнату pf_open("1.wav"); //pf_lseek(44) тармағын ашыңыз; //көрсеткішті 44 pf_read(буфер, 512,&br) мәніне жылжытыңыз; //алғаш рет 512 байтты бірден жұтамыз TIMSK=0x80; //музыканы қосу кезінде(1) ( if(!buf && count>255) //егер 255 байттан астам ойнатылған болса, ( pf_read(&buffer, 256,&br);//содан кейін флэштен ақпаратты оқыңыз. буфер буфінің бірінші жартысына апарыңыз=1; егер (br< 256) //если буфер не содержит 256 значений значит конец файла break; } if(buf && count<256) { pf_read(&buffer, 256,&br); // читаем во вторую часть буфера с флешки buf = 0; if (br < 256) break; } } TIMSK = 0x00; //глушим все pf_mount(0x00); //демонтируем фат } while (1) { } }

Тексеру үшін динамикті OCR1A істікшесіне 100 мкФ конденсатор арқылы, «+» микроконтроллердің істікшесіне, «-» динамикке қосамыз. «-» динамик жерге, «+» конденсаторға.

Шығыста қатты сигнал күтпеңіз, қатты дыбыс шығару үшін күшейткіш қажет. Бұл бейнеде анық көрінеді. Сынақ үшін мен әтешті 8 кГц және жолды 22 кГц жүктедім.

Қалаушылар 44 кГц файлдарды ойнату үшін таймер2 жиілігін қауіпсіз түрде арттыра алады; эксперименттер өте жақсы дыбыс сапасына қол жеткізуге болатынын көрсетеді. Бейнебаянда дыбыс әлсіз, сапасы нашар, бірақ шын мәнінде бұл камерамен түсіргенімнің кесірінен.

Мен сондай-ақ Apparatchik ұсынған материалдарды - CAVR микробағдарламасы жазылған GCC бастапқы кодын жариялап отырмын.

Және 44 кГц ойнатуы бар бейне.

Осы мүмкіндікті пайдаланып, барлығыңызды Жаңа жылмен құттықтаймын, барлық микробағдарламалар мен құрылғылар сіз үшін жұмыс істеуін тілеймін :)

Atmega8-дегі wav ойнатқышы жобасы

Мен AVR микроконтроллеріндегі кез келген дерлік жобаға әуендерді немесе дыбыс ретін ойнау функциясын қосуға мүмкіндік беретін бағдарламалық модуль жаздым.

Модуль мүмкіндіктері:

Дайын жобамен оңай біріктіру

Тек 8-биттік таймер t2 пайдаланылады, бірақ оны сұрау немесе уақыт аралығын қалыптастыру үшін пайдалануға болады.

Модуль кез келген тактілік генератор жиілігіне реттеледі

Ноталар биіктігі символдық тұрақтылар (C0, A2, т.б.) ретінде немесе Герцпен көрсетіледі.

Ұзақтықтар стандартты түрде (тоқсандар, сегіздіктер және т.б.) немесе миллисекундтармен көрсетіледі

Әуенді ойнату қарқынын және оның қайталану санын орнатуға болады

Ойнату кезінде әуенді кідіртуге болады


Дыбыс модулін қосу

1. Барлық модуль файлдарын (tone.h, sound.h, sound.c) жоба қалтасына көшіріңіз.

2. sound.c файлын жобаға қосыңыз.

IAR `a үшін – жұмыс кеңістігі терезесін тінтуірдің оң жақ түймешігімен басып, Қосу > Файлдарды қосу… тармағын таңдаңыз.

WINAVR үшін бұл шамамен бірдей, тек sound.c файлын жасау файлына қосу керек:

SRC = $(TARGET).c дыбыс.c

3. sound.h тақырып файлын сәйкес модульге қосыңыз. Мысалы, main.c

#қосу "sound.h"

4. Модуль параметрлерін sound.h файлында орнатыңыз

//егер сіз түсініктеме берсеңіз, жазбалардың ұзақтығы болады

//әуенде көрсетілген BPM-ден есептеледі

//қалған болса, төменде көрсетілген мәннен

//#SUND_BPM 24 анықтау

//сағат жиілігі μ

#SOUND_F_CPU 16U анықтау

//дыбыс жасалатын микроконтроллердің шығысы

#PORT_SOUND PORTB анықтау

#PINX_SOUND 0 анықтау

//көрсетілген әуендер саны.

#Дыбыс_мөлшерін_анықтаңыз 4

5. Әуендеріңізді sound.c файлына қосып, әуендер жиымына әуендердің атын жазыңыз.

Қоңырау үндерін қосу

Әуен 16 разрядты сандар массиві және келесі құрылымға ие

BPM (минутына ширек нота)ноталардың ұзақтығын есептеу үшін қолданылатын тұрақты шама және әуеннің ойналу жылдамдығын анықтайды.

BPM 1-ден 24-ке дейін болуы мүмкін, бұл тиісінше минутына 10 және 240 ширек нотаға сәйкес келеді.

Егер ноталардың/дыбыстардың ұзақтығы миллисекундтармен көрсетілген болса, онда массивте жазылған BPM 1-ге тең болуы керек.

Егер SOUND_BPM тұрақтысы sound.h тақырып файлында түсіндірілсе, онда ескертпелер ұзақтығы массивте көрсетілген BPM сәйкес бағдарламаны орындау кезінде есептеледі. Егер SOUND_BPM түсіндірілмесе, ноталардың ұзақтығы осы тұрақтының мәніне негізделген компиляция сатысында есептеледі және барлық әуендер бірдей қарқынмен ойналады. Бұл функционалдылықты шектейді, бірақ кодты бірнеше байтты сақтайды.

Қайталанулар саны. 1 ... 254 және LOOP (255) мәндерін қабылдай алады. LOOP - SOUND_STOP немесе SOUND_PAUSE пәрмені берілгенше әуеннің шексіз қайталанатынын білдіреді.

Ескерту ұзақтығы– берілген дыбыс үні жасалатын немесе үзіліс сақталатын уақыт. ms(x) макросы арқылы немесе стандартты нота мәндері ретінде ms-де көрсетілуі мүмкін - сегізінші ноталар, он алтыншы ноталар және т.б. Төменде қолдау көрсетілетін ұзақтықтардың тізімі берілген. Кейбір экзотикалық ұзақтықтар қажет болса, оларды әрқашан tone.h файлына қосуға болады

n1 - тұтас нота

n2 - жарты нота

n4 - тоқсан

n8 - сегізінші

n3 - сегізінші үштік

n16 - он алтыншы

n6 - секстол

n32 - отыз екінші

Ескерту қадамы tone.h файлында сипатталған символдық тұрақтылар арқылы көрсетіледі, мысалы, C2, A1, т.б. Сондай-ақ, ноталар биіктігін f(x) макросы арқылы Герцте көрсетуге болады.

Бағдарламада ең төменгі және максималды дыбыс жиілігіне шектеулер бар!

Әуеннің аяқталу маркері.Массивтің соңғы элементінің мәні нөлге тең болуы керек.

Дыбыс модулін пайдалану

main басында SOUND_Init() функциясын шақыру керек. Бұл функция микроконтроллердің шығыс істікшесін орнатады, T2 таймерін конфигурациялайды және модуль айнымалы мәндерін инициализациялайды.

Содан кейін үзілістерді қосу жалауын орнату керек - __enable_interrupt(), себебі модуль T2 таймерінің толып кетуін және сәйкестік үзулерін пайдаланады.

Осыдан кейін сіз әуендерді ойнауды бастай аласыз.

Мысалы, келесідей:

SOUND_SetSong(2);

SOUND_Com(SOUND_PLAY); //әуен ойнату

//2-ші әуенге көрсеткішті орнатыңыз

//және ойнатуды бастаңыз

SOUND_PlaySong(2);

Әуенді ойнатуды кез келген уақытта SOUND_STOP пәрменін беру арқылы тоқтатуға болады.
Сондай-ақ, SOUND_PAUSE пәрмені арқылы әуенді кідіртуге болады. SOUND_PLAY пәрменінің келесі шығарылымы әуенді ойнатуды тоқтатылған жерден жалғастырады.

Негізінде бұл функция аса қажет емес (мен оны жай ғана ойлап таптым) және модульмен жұмыс істегенде SOUND_PlaySong(unsigned char numSong) функциясы жеткілікті;

Файлдар

Дыбыс модулін пайдалану мысалдарын төмендегі сілтемелерден жүктеп алуға болады. Мен диаграмма салмадым, өйткені ол жерде бәрі қарапайым. PB0 істікшесіне қосылған, әуендерді бастау түймесі PD3 істікшесіне қосылған. Жобаларда анықталған 4 әуен бар. Түймені басқан сайын жаңа әуен басталады. atmega8535 микроконтроллері қолданылады. Бастапқыда мен төрт түймесі бар жобамен айналысқым келді - ОЙНАТУ, ТОҚТАТУ, ТОҚТАТУ және КЕЛЕСІ, бірақ кейін бұл қажет емес деп ойладым.

PS: Модуль ауқымды тестілеуден өтпеген және «сол қалпында» берілген. Ұтымды ұсыныстар болса, пысықтап алайық.

Бұл мақалада біз тондарды қалай ойнау керектігін қарастырамыз және монофониялық әуенді ойнауды үйренеміз.

Жұмысқа дайындалу

Бағдарлама екі массивті жариялайды. Жазбалары бар массив ескертпелержазбалардың қарапайым тізімін қамтиды. Бұл жазбалар массивтегі дыбыс ұзақтығына сәйкес келеді соғады. Музыкадағы ұзақтығы нотаның бөлгішімен бүкіл нотаға қатысты анықталады. Тұтас ескертпе ретінде алынған мән 255 . Осы санды бөлу арқылы жартылар, ширектер, сегіздіктер шығады.
Назар аударыңыз, бірінші нотаның ұзақтығы 255-ті екінің дәрежесіне бөлу арқылы алынбайды. Мұнда сіз музыка теориясына ауысуыңыз керек. Түпнұсқа әуеннің ноталарын көруге болады. Бұл ноталар үштікке біріктірілген. Осылай біріктірілгенде үш сегізінші нота ширек нотамен бірдей естіледі. Сондықтан олардың салыстырмалы ұзақтығы 21.
Сондай-ақ пайдаланушы директивамен қатардағы ескертпелер санын нақты көрсетуі керек:

# SEQU_SIZE 19 анықтау

Негізгі бағдарламада, ең алдымен, жиілік массивтері қайта есептеледі және ұзақтығы сигналдар кезеңдері мен ноталардың ұзақтығы.
Сигнал кезеңдерімен (массив сигнал_кезеңі) бәрі оңай. Период ұзақтығын микросекундтарда алу үшін 1 000 000-ды сигнал жиілігіне бөлу жеткілікті.
Ноталардың абсолютті ұзақтығын есептеу үшін музыкалық шығарманың қарқынын көрсету керек. Бұл директива бойынша жасалады

# ТЕМПО 108 анықтау

Музыкадағы қарқын – минутына ширек ноталар саны. Кезекте

# WHOLE_NOTE_DUR 240000 / TEMPO анықтаңыз

Толық нотаның ұзақтығы миллисекундпен есептеледі. Енді формуланы пайдаланып массивтен салыстырмалы мәндерді қайта есептеу жеткілікті соғадыабсолютті массивке ескертпе_ұзақтығы.
Негізгі циклде айнымалы өткен уақытойнатылған сигналдың әрбір кезеңінен кейін нота ұзақтығынан асқанша осы кезеңнің ұзақтығына артады. Бұл жазбаға назар аударған жөн:

әзірше(өткен_уақыт< 1000 * ((uint32_t) note_duration[ i] ) )

Айнымалы өткен уақыт 32-бит және массив элементтері жазбалар_ұзақтығы 16-бит. Егер 16-биттік сан 1000-ға көбейтілсе, онда толып кетуге кепілдік беріледі және айнымалы өткен уақытқоқыспен салыстырылатын болады. Модификатор (uint32_t)массив элементін түрлендіреді жазбалар_ұзақтығы[i] 32 биттік нөмірде толып кету болмайды.
Аудио циклында басқа мүмкіндікті көруге болады. Функцияны пайдалану мүмкін болмайды _delay_us(), өйткені оның аргументі айнымалы бола алмайды.
Мұндай кідірістерді жасау үшін функцияны пайдаланыңыз VarDelay_us(). Онда 1 мкс кідіріспен цикл белгілі бір рет айналдырылады.

void VarDelay_us(uint32_t takt) ( while (takt- - ) ( _delay_us(1 ) ; ) )

Әуенді ойнағанда тағы екі кідіріс қолданылады. Егер ноталар үзіліссіз ойналса, олар бір нотаға біріктіріледі. Ол үшін олардың арасына директивада көрсетілген 1 мс кідіріс енгізіледі:

# NOTES_PAUSE 1 анықтау

Әуенді ойнаудың әрбір толық циклінен кейін бағдарлама 1 секундқа үзіліс жасап, қайта ойнай бастайды.
Нәтижесінде біз қарқынды өзгертуге, ұзақтықты реттеуге немесе әуенді толығымен қайта жазуға оңай болатын код алдық. Ол үшін директивалар мен айнымалы декларациялары бар бағдарламаның тек бөлігін ғана түрлендіру жеткілікті болады.

Жеке тапсырмалар

  1. Ұсынылған әуенде қарқынды өзгертіп көріңіз және қайталау арасында 5 секунд үзіліс жасаңыз.
  2. Массив элементтері соғадытек 0-ден 255-ке дейінгі мәндерді қабылдаңыз. Жиым элементтерінің бит енін өзгертіңіз және оның бағдарлама алатын жад көлеміне қалай әсер ететінін көру үшін компилятор шығысын қараңыз.
  3. Енді әуенді өзіңіз өзгертіп көріңіз. Мысалы, міне, сол фильмдегі «Императорлық марш»: int notes = ( A4, R, A4, R, A4, R, F4, R, C5, R, A4, R, F4, R, C5, R, A4, R, E5, R, E5, R, E5, R, F5, R, C5, R, G5, R, F5, R, C5, R, A4, R); int соққылары = ( 50 , 20 , 50 , 20 , 50 , 20 , 40 , 5 , 20 , 5 , 60 , 10 , 40 , 5 , 20 , 5 , 60 , 80 , 2 02 , 5 , 50 , 50 20, 40, 5, 20

    Егер сіздің көлігіңізде дыбыстық сирена орнатылмаған болса және сіз қайсысын сатып алуды және орнатуды әлі шеше алмасаңыз, онда бұл мақала тек сізге арналған. Егер сіз бәрін өзіңіз құрастыра алсаңыз, неге қымбат дабылдарды сатып алу керек?

    Соның екеуін ұсынамын қарапайым тізбектер AVR ATmega8 және Attiny2313 микроконтроллерлерінде, дәлірек айтқанда, осы екі микроконтроллерлерде жұмыс істеу үшін бірдей схема жай ғана жүзеге асырылады. Айтпақшы, мұрағатта сіз Atmega8 микроконтроллеріне арналған микробағдарламаның екі нұсқасын таба аласыз, олардың біріншісі дыбысқа ұқсас дыбысты шығарады. автокөлік дабылы, ал екінші дыбыс ғимараттың қауіпсіздік дабылына ұқсайды (жылдам және өткір сигнал).

    Төмендегі барлық микробағдарламаны мұрағатқа жүктеп алуға болады (олардың барлығына қол қойылған), мұрағатта сіз Proteus схемаларының симуляциясын таба аласыз, яғни барлық әуендерді тыңдағаннан кейін тізімнен өзіңізге ұнайтын нәрсені таңдауға болады. .

    Төменде Atmega8 үшін сигналдық диаграмма берілген

    Atmega8 тізбегінде қолданылатын радио компоненттерінің тізімі

    U1- AVR микроконтроллері 8 биттік ATmega8-16PU, көлемі 1,
    R1- 47 Ом номиналды мәні бар резистор, №. 1,
    R2, R3 - 270 Ом номиналды мәні бар резистор, жоқ. 2,
    D2,D3-жарық диодты, жоқ. 2,
    LS1-динамик, жоқ. 1,
    S1-сенсор.

    Ал Attiny2313 сигналдық тізбегінде тек МК өзгертілген.
    U1- микроконтроллер AVR 8-бит ATtiny2313-20PU, №. 1.

    Баспа төлем Atmega8 үшін келесідей көрінеді:

    Көріп отырғаныңыздай, схема өте қарапайым, тек бір микроконтроллер, 3 резистор, 2 жарықдиодты және тағы бір динамик бар. Түйменің орнына қамыс қосқышын немесе басқа контактіні пайдалануға болады.

    Жұмыс принципі келесідей. Қуатты қосқан кезде жарық диоды (D3 тізбегінде) бірден жанады немесе жыпылықтай бастайды (микробағдарламаға байланысты), ал сенсорды ұстамасақ, дабыл үнсіз болады. Енді сенсор іске қосылса, сирена да жұмыс істейді, жарық диоды жыпылықтайды, бірақ D2.

    Егер сіз дабыл жұмыс істеп тұрған кезде автомобильдің фараларының жыпылықтауын қаласаңыз, ол үшін 24 PC1 микроконтроллерінің істікшесін транзистор арқылы релеге, ал реленің өзін фарларға қосу керек. Сиренаны өшіру үшін құрылғыны өшіріп, қайта қосу керек немесе жай ғана түймені басу керек. Микроконтроллерді басқару үшін сізге ішкі 8 МГц осциллятор қажет,

    Егер сіз дабыл дыбысын қандай да бір жолмен күшейткіңіз келсе, транзисторлары бар күшейткішті жинап, оны тізбекке қосуға болады. Мен дәл осылай жасадым, бірақ мен оны бұл диаграммада көрсетпедім.

    Attiny 2313 тізбегіндегі схемаға көшейік, мен жоғарыда айтқанымдай, оның барлық бөлшектері бірдей және жұмыс принципі бірдей, тек МК өзгерді және нәтижесінде қосылған түйреуіштер.Бұл микроконтроллер жұмыс істейді. ішкі 4 МГц осциллятор, бірақ оны 1 МГц жиілікте жыпылықтауға болады.

    Төменде Attiny2313 жүйесінде қосылым диаграммасы берілген

    Бұл МК үшін мен микробағдарламаның тек бір нұсқасын жаздым, схеманың бәрін жинадым, оны тексердім, бәрі жақсы жұмыс істейді.
    Және сақтандырғыштарды төменде көрсетілгендей орнату керек:





Жоғарғы