Atmega8 csengőhangok. Egyszerű hangszirénák az MK AVR-en. A hangmodul használata

A cikk leírja a zenei szintézis alapelveit az AVR-en. A mellékelt szoftver lehetővé teszi bármilyen midi fájl konvertálását forrás C-ben AVR mikrokontrollerekhez, hogy zenei töredékek lejátszását adják hozzá a kész fejlesztésekhez. Egy példa a szoftver zenedobozban való használatára.

Először is egy rövid videó az egész működéséről:

Amit a szoftver megenged

A PC-szoftver lehetővé teszi a CodeVision AVR C-forrás beszerzését, amely lejátssza a kiválasztott midi fájlt:

1. Csatlakoztassa a common\hxMidiPlayer.h, common\hxMidiPlayer.c fájlt a projekthez. Másolja ki az ATMega8Example\melody.h, ATMega8Example\melody.c, ATMega8Example\hxMidiPlayer_config.h sablonokat, és csatlakozzon.
2. Indítsa el a MidiToC.exe fájlt
3. Töltse be a Midi fájlt.
4. Állítsa be a lejátszót: mintavételi frekvencia, csatornák száma, hullámforma stb. A szoftver ugyanúgy játssza le a dallamot, mint az AVR.
5. Kattintson a „Lejátszókonfiguráció létrehozása” gombra, és illessze be a forrást a hxMidiPlayer_config.h fájlba.
6. Kattintson a „Dallamkód létrehozása” gombra, és illessze be a forrást a melody.c fájlba
7. Projektünkben a Player_Output() metódust valósítjuk meg a hang PWM-en vagy külső DAC-n keresztül történő kiadásához.
8. Állítsa az időzítőt a mintavételezési frekvenciára, és hívja meg a Player_TimerFunc()-t a megszakításból.
9. Hívja a Player_StartMelody(&s_melody, 0) parancsot.

A dallam az időzítő megszakításától szólal meg. Ez azt jelenti, hogy lejátszás közben a mikrokontroller is hasznos munkát végezhet.

Hogyan működik

A cikk további részében megpróbálom röviden elmagyarázni, hogyan valósul meg mindez. Sajnos nem lesz túl rövid – rengeteg az anyag. Ha nem érdekli, egyenesen a „Szoftver leírása” és a „Lejátszó API” szakaszokhoz léphet.

Mi a zene

A zene változó frekvenciájú és időtartamú hangok sorozata. Egy hang alapharmonikusának frekvenciájának meg kell egyeznie egy bizonyos hang frekvenciájával. Ha a hangok rezgési frekvenciája eltér a hangok frekvenciáitól, akkor számunkra úgy tűnik, hogy a zenész „elhangolódott”.

Asztal. Jegyezze fel a frekvenciákat, Hz.

Minden hang oktávra van osztva, mindegyikben 7 hang + 5 félhang (fekete billentyűk a zongorán). A szomszédos oktávokban a hangok frekvenciája pontosan 2-szer tér el.

A legegyszerűbb zenelejátszó tartalmaz egy táblázatot egy dallam hangsorával (hang + időtartam), valamint egy táblázatot a hangok frekvenciáival. A hang szintetizálásához az egyik időzítő csatornát használják, amely egy meandert alkot:

Sajnos egy ilyen primitív lejátszónak fix hullámformája van (négyzethullám), ami nem nagyon hasonlít a valódi hangszerekre, és egyszerre csak egy hangot tud játszani.

Egy igazi dallam legalább két szólamot tartalmaz (szóló + basszus), és ha zongorán játsszák, az előző hang továbbra is szól, amikor a következő elkezdődik. Ez könnyen megérthető, ha emlékezünk a zongora szerkezetére - minden hang egy külön húrnak felel meg. Egyszerre több húrt is megszólaltathatunk, ha a kezünket a billentyűkön húzzuk.

Egyes mikrokontrollerek több időzítő csatornával rendelkeznek, amelyekkel egyszerre több hangot is lejátszhatunk. De általában ezek a csatornák értékes erőforrást jelentenek, és nem tanácsos mindegyiket felhasználni. Kivéve persze, ha csak zenedobozt készítünk.
Összességében a polifónia és a hangszerek különféle hangjainak eléréséhez hangszintézist kell használni.

Hangszintézis az AVR-en

A hxMidiPlayer hangszintézist használ, és különböző hullámformákkal képes polifóniát játszani. A lejátszó kiszámolja a kimenő jel amplitúdóját az időzítő megszakításkezelőben 8-22 KHz frekvenciával (mekkora processzorteljesítmény elég; függ a hullámformától és a csatornák számától is).

A hangszintézis elve a szinuszos szintézis példáján keresztül magyarázható.

Vegyünk egy 64-es méretű táblázatot, amelynek minden cellájába a szinusz amplitúdójának értékeit a * 2 * PI / 64 pontokba írjuk (egy periódus):

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

A 128 (0x80) nullának, a 255 (0xff) a legnagyobb pozitív pontnak, a 0 a legnagyobb negatív pontnak felel meg.

Most tegyük fel, hogy a táblázatból kiadjuk az értékeket egy külső DAC-ra egy 1000 Hz-es frekvencián meghívott időzítő megszakításban:

Statikus uint8_t s_index = 0; // Időzítő1 kimenet összehasonlítása Megszakítási rutin szolgáltatásmegszakítás void timer1_compa_isr(void) ( SetDac(s_sineTable[ s_index]); if (s_index == 63) ( s_index = 0; ) else ( s_index++; ) )

Mit kapunk ennek eredményeként? 1000/64 Hz frekvenciájú szinuszos rezgéseket fogunk kapni.

Most ne 1-gyel, hanem kettővel növeljük az indexet a megszakításban.
Nyilvánvaló, hogy a kimeneti oszcillációs frekvencia már 1000/64 * 2 Hz lesz.

Általában az F frekvencia eléréséhez növelni kell a táblázatban szereplő indexet:
add = F / 1000 * 64

Ez a szám lehet tört, de a nagy sebesség eléréséhez fixpontos aritmetikát használnak.

A táblázatban szereplő bejegyzések száma és az időzítő frekvenciája befolyásolja a szintetizált hang minőségét. Esetünkben periódusonként 64 bejegyzés elegendő a táblázatban, az időzítő frekvenciája pedig 12 kHz. A minimálisan elfogadható időzítő frekvencia 8 kHz, az ideális 44 kHz.

Nyilvánvalóan 12 kHz-es időzítő frekvenciával maximum 6 kHz-es négyszöghullámokat generálhatunk, hiszen periódusonként legalább két kapcsolást kell végrehajtanunk. A magasabb frekvenciák azonban továbbra is felismerhetők lesznek, ha a kimeneti állapotot minden egyes időzítéskor helyesen számítják ki.

A táblázatba beírhatja a nem szinuszos rezgések időszakának értékeit, és eltérő hangot kaphat.

Csillapítás

Ha egy hangszer húrokra épül (például zongora), akkor egy billentyű lenyomása után a hang simán elhalkul. A természetesebb szintetizátorhangzás érdekében a hang kezdete után simán csökkenteni kell a rezgések amplitúdóját (a rezgéseket csillapító formába „burkolni” – „burokba”).

A lejátszó tartalmaz egy lecsengési táblázatot, amelyet a szinusz (vagy más hullámforma) amplitúdójának csökkentésére használ a hang kezdetétől számítva.
Az ilyen héjba „bugyolált” „sine” egy mechanikus zenedoboz hangjához hasonlít.

Meander szintézis

A meander hullám különleges alakja lehetővé teszi a szintézis jelentős egyszerűsítését. A táblázatokat ebben az esetben nem használjuk. Elég kiszámolni, hogy adott frekvencián milyen állapotú (1 vagy 0) legyen a kimenet az aktuális időzítő ketyegésénél. Ez egész számok aritmetikával történik, és nagyon gyorsan működik, ami megmagyarázza a négyzethullám használatának népszerűségét a 8 bites set-top boxokban való dallamok lejátszására.

Példa: számláló deklarálása:

Statikus uint16_t s_counter = 0;

amit minden időzítő megszakításnál 0x8000-el növelünk, és a számláló legjelentősebb bitje kerül kimenni a portra:

// Időzítő1 kimenet összehasonlítása Megszakítási rutin szolgáltatásmegszakítás void timer1_compa_isr(void) ( PORTA.0 = (s_counter >> 15) & 1; s_counter += 0x8000; )

Mivel 0x8000 + 0x8000 = 0x10000, az s_counter változó túlcsordul, a 17. bit eldobásra kerül, és 0x0000 kerül a változóba.
Így 8KHz-es időzítőfrekvenciával a kimenet 4KHz-es négyszöghullám lesz.
Ha megnöveli a számlálót 0x4000-rel, akkor 2 kHz-es négyszöghullámot kap.

Általában az F frekvenciát a következő hozzáadásával kaphatja meg:
add = F / 8000 * 0x10000

Például egy 1234 Hz ​​frekvenciájú négyszöghullám eléréséhez hozzá kell adni a 0x277C értéket. A tényleges gyakoriság némileg eltér a megadottól, mert a kifejezést egész számra kerekítjük. Ez szintetizátorban elfogadható.

Valódi hangszerek hangjainak szintézise

A hangjegy hangját a zongora előtt digitalizálhatja (egy ADC segítségével a hangamplitúdó értékeket rendszeres időközönként a memóriában tárolja):
majd lejátssza a hangot (a DAC segítségével rendszeres időközönként kiadja a rögzített értékeket).

Általában a dobok szintetizálásához fel kell venni a dob hangjait, és a megfelelő pillanatban le kell játszani. A 8 bites konzolokon a „white noise” használatos a dobhangok helyett. A „fehér zaj” amplitúdóértékeit generátor segítségével kapjuk meg véletlen számok. A memória költségek minimálisak.
A hxMidiPlayer „fehér zajt” használ a dobszintézishez.

Csatorna keverés

A hang amplitúdója egy adott időzítőnél minden csatornára külön kerül kiszámításra. A végső amplitúdóérték megszerzéséhez hozzá kell adni az összes csatorna értékét. Helyesen be kell állítani az összeget, mivel az észlelt hangosság logaritmikus függőségnek engedelmeskedik, de egy ilyen egyszerű szintetizátorban egyszerű összeadással kell beérnie. Ezért az egyes csatornák maximális amplitúdója 255/N.

Hangkimenet az AVR-ből

Az összes szükséges számítás elvégzése után a lejátszó megkapja azt a jelszintet, amelyet analógra kell konvertálni. Erre a célra külső DAC vagy PWM használható.
Itt kell megjegyezni, hogy mindkét esetben célszerű a vett jelet szűrni - a magas frekvenciájú zajok eltávolítására, amelyek a szintézis és a kerekítés alacsony frekvenciája miatt keletkeznek.

Kimenet külső párhuzamos DAC-ra

Mivel nincs értelme precíz DAC-chipeket használni, az ilyen projektek általában beérik az R2R mátrixszal:

Ezzel a sémával egyszerűen kiadjuk a számított amplitúdót a portra:

PORTB = minta;

Hibák:
1) az R2R mátrix kimenete is gyenge jel, analóg erősítő használata kötelező;
2) legalább 5 (lehetőleg 8) tűt kell használni;
Ez a módszer csak akkor indokolt, ha nincsenek szabad PWM csatornák.

(a lábak mentéséhez használhat külső ADC-t SPI interfésszel).

PWM

Ha van szabad PWM csatorna, akkor a legegyszerűbb módja ennek a módszernek a használata.

PWM inicializálás (ATMega8):

// Időzítő/Számláló 2 inicializálása // Óraforrás: Rendszer óra // Órajel értéke: 20000.000 kHz // Mód: Fast PWM top=0xFF // OC2 kimenet: Nem Invertált PWM ASSR=0x00; TCCR2=0x69; TCNT2=0x00; OCR2=0x00; És a minta kimenete: void Player_Output(uint8_t sample) ( OC2 = minta. )

A PWM használatának általános gyakorlata a kimeneti jel simítása RC szűrővel:

Sajnos a szűrés után a jel túlságosan gyengül, ezért analóg erősítőt kell készíteni a hangszóró csatlakoztatásához.

Az áramkör egyszerűsítése érdekében jobb, ha „digitális” marad egészen a hangszóróig. Mivel egy olcsó hangszóró még mindig nem képes reprodukálni a 30 kHz feletti frekvenciákat, nincs szükség szűrésre. Maga a diffúzor „kiszűri” a magas PWM-frekvenciákat.

Ha több áramot kell kapnia, használhat tranzisztoros erősítőt. R1 van kiválasztva, hogy biztosítsa a szükséges áramot a hangszóróhoz.

Így csatlakoztathat kis hangszórókat játékokból:

Nagyobb hangszórók esetén jobb, ha a meghajtót 2 tranzisztorral szereljük össze, és egy LC-szűrőt telepítünk a zaj eltávolítására:

A C1 kondenzátor a hangszórón keresztüli áram korlátozására szolgál, amikor a PWM nem működik. Ezenkívül a soros kondenzátor beépítése miatt nulla körül szimmetrikus jel éri el a hangszórót. Így a hangszórókúp elmozdul a központi „lazított” helyzethez képest, ami pozitív hatással van a hangminőségre.
Ebben az esetben a tranzisztorok kapcsolási módban működnek, így nem kell kompenzálni az alapeltolást.

PWM, két tűs csatlakozás

Az első két áramkör hátránya, hogy a hangszórót egyirányú árammal látják el. Ha megváltoztatjuk az áram irányát, a hangerő 2-szeresére növelhető a megengedett teljesítmény túllépése nélkül. Ehhez a hangszórót a mikrokontroller két érintkezőjéhez kell csatlakoztatni - nem invertált és fordított, például OC1A és /OC1A. Ha nincs nem invertált kimenet, használhatja a második csatornát fordított módban (OC1B):

// Időzítő/Számláló 1 inicializálása // Óraforrás: Rendszeróra // Órajel értéke: 24500 000 kHz // Mód: Fast PWM top=0x00FF // OC1A kimenet: Non-Inv. // OC1B kimenet: fordított // Zajszűrő: Ki // Bemeneti rögzítés leeső élen // Időzítő1 túlcsordulás megszakítása: Ki // Bemeneti rögzítés megszakítása: Ki // A mérkőzés megszakításának összehasonlítása: Ki // B összehasonlítása Match megszakítás: Ki 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 minta) ( OCR1A = minta; OCR1B = minta; )

PWM, két tűs, D osztályú erősítő

A javasolt áramkörök hátránya a csend alatti áramfelvétel.
A „csend” számunkra 128-as jelszintnek felel meg, azaz PWM 50% -os töltéssel - az áram mindig a hangszórón keresztül folyik!

A szoftver enyhe megváltoztatásával egy meglehetősen erős szoftveres és hardveres D osztályú erősítőt kaphat:

Void Player_Output(uint8_t minta) ( if (minta >= 128) ( TCCR2=0x21; //normál, törlése az összehasonlításkor TCCR2=0x21 | 0x80; //CLEAR OC2 PORTC.0 = 0; TCCR2=0x69; //non -inverting PWM OCR2 = (sample-128) * 2; ) else // if (minta< 128) { TCCR2=0x31; //normal, set on compare match TCCR2=0x31 | 0x80; //SET OC2 PORTC.0 = 1; TCCR2=0x79; //inverting PWM OCR2 = (128-sample) *2; } }

Ebben az esetben egy pár tranzisztor csatlakozik a PWM kimenethez, a második egy normál digitális kimenethez.

A kódból látható, hogy a 128 feletti jelet egyik irányba, a 128 alatti jelet pedig a másik irányba irányított áramnak tekintjük. 128-nál mindkét hangszóró érintkezője ugyanahhoz a tápegység érintkezőjéhez van csatlakoztatva, és nincs áram. A 128-as szinttől való eltérés esetén a PWM-töltés növekszik, és a megfelelő polaritású áram folyik át a hangszórón.

A megvalósítás fontos pontja a PWM kimenet kényszerített átkapcsolása a kívánt állapotba a második (normál digitális) láb (PORTC.0) átkapcsolásának pillanatában. Az OCR2 regiszterbe való írás pufferelve van a PWM-hibák kiküszöbölése érdekében. A PWM kimenetet azonnal át kell kapcsolnunk, anélkül, hogy megvárnánk az időszak végét.

Ez utóbbi áramkör az IMHO a legjobb megoldás az egyszerűség, az energiamegtakarítás és a teljesítmény szempontjából.

Hangkimenet SquareWave hullámformával

A meander szintetizálása során egyszerűsített algoritmusokat használnak.

Minden csatorna (beleértve a dobokat is) 0-t vagy 1-et ad ki. Így egy 3 csatornás lemezjátszó 0...3 tartományba eső értékeket ad ki. Ezért PWM használatakor a kimeneti eljárás így néz ki:

Void Player_Output(uint8_t minta) ( OCR2 = minta * (255 / HXMIDIPLAYER_CHANNELS_COUNT); )

Ha nem használ PWM-et, akkor egy 3 csatornás dallam kimenetéhez elegendő két hagyományos digitális kimenet és egy 2 bites R2R mátrix.

MIDI formátum

Ha megnézi a kapott dallamkódot, könnyen láthatja, hogy a tömb kis tartományból ismétlődő számokat használ. Ez érthető: a dallam 1-2 oktávon belül korlátozott számú hangot használ, a dallamtempó fix - egyenlő késések, a csatornák száma 0...15 tartományba esik.
Mindez azt jelenti, hogy a kapott tömb jelentősen csökkenthető valamilyen tömörítési algoritmus alkalmazásával.
Az olyan algoritmusok, mint a ZIP, jó tömörítést biztosítanak, de sok memóriát is igényelnek a működésükhöz (ZIP szótár - 64 Kb). Használhatunk egy nagyon egyszerű, gyakorlatilag memóriát nem igénylő tömörítési módszert, melynek lényege a következő.

Egy bájtban minden szám egyenletesen oszlik el a 0...255 tartományban, és minden számot 8 bit képvisel. Esetünkben egyes számok sokkal gyakoribbak, mint mások. Ha a gyakran előforduló számokat kevesebb bittel kódolja, a ritkábban előfordulóakat pedig több bittel, memórianövekedést kaphat.

Rögzített kódolási módot választunk: a 000 001 és 010 bitek kombinációi (hossz - 3 bit) jelentik a 3 leggyakrabban előforduló számot. Bitkombinációk 0110, 0111 (hossz – 4 bit) – a következő 2 leggyakoribb szám stb.:

//000..010 - 0..2 //011 x 3..4 //100 xx 5..8 //101 xxx 9..16 //110 xxx 17..24 //111 azonnali

A 111-gyel kezdődő kombináció (hosszúság – 11 bit) az összes többi számot kódolja.
A bitkódolási módszer eltérő lehet. Több módszert is kipróbáltam, és ezt választottam, mivel ez a legjobb eredményt nyújtja ilyen adatokon.

A tömörítési eljárás így néz ki:
1. Számítsa ki az X szám teljes számát az adatfolyamban X = esetén.
2. Rendezés az adatfolyamban való megjelenés gyakoriságának csökkenésével.
3. Vegyük az első 25 számot. Kevesebb bitben lesznek kódolva.
4. Kódolja a bemeneti adatfolyamot.

A kimenet a 25 leggyakrabban előforduló számból és egy bitfolyamból álló tömb.
Ezzel a tömörítéssel 50%-os tömörítést érhet el minimális memória- és teljesítményköltséggel. Sajnos ez megnöveli a lejátszó kódját, így a tömörítés nem javasolt rövid dallamoknál.

Hangjegyfrekvenciák tárolása

Meglehetősen költséges az összes hang frekvenciáját egy táblázatban tárolni a memóriából. Valójában van egy képlet a hang gyakoriságának meghatározására a midi szám alapján:

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

De a tört hatvány kiszámítása meglehetősen nehéz. Ehelyett a lejátszó 12 hangfrekvenciát tárol a felső oktávban. Az alsó oktávokban lévő hangok frekvenciáját úgy határozzuk meg, hogy a frekvenciát még 2^Y-szeresre csökkentjük, ahol Y a lefelé tartó oktávok száma.

A kompresszió továbbfejlesztése

A dallam gyakran tartalmaz ismétlődő töredékeket („kórusokat”, „verseket”). Ismétlődő töredékek keresésével és a dallam töredékek formájában történő bemutatásával további 50%-kal csökkentheti a dallamot, szinte idő nélkül RAMés a termelékenység. Nem valósítottam meg ilyen algoritmust, hogy ne bonyolítsam a projektet.

Szoftver leírás

A konverter program fő ablaka:

A Load Midi gomb lehetővé teszi midi fájl betöltését. A program azonnal elkezdi lejátszani a fájlt az aktuálisan kiválasztott paraméterekkel, szimulálva a hardverben lévő hangot.

Az információs ablak (4) a következőket jeleníti meg:
– Length – a kiválasztott dallamrészlet hossza ms-ban;
– Max Active szintetizátor csatornák – az egyidejűleg aktív szintetizátor csatornák maximális száma;
– Max aktív dobcsatornák – a „dobokat” reprodukáló, egyidejűleg aktív szintetizátorcsatornák maximális száma;
– Max aktív sztereó hangok – az ugyanazt a hangot reprodukáló csatornák maximális száma (lásd alább);
– Becsült méret, bájt – dallamméret bájtban. Az „Egyéni minta” módban a méret A+B formában jelenik meg, ahol A a dallam mérete, B a minta mérete. A játékos kód mérete itt nincs megadva.

A folyamatjelző ablak az aktuális lejátszási pozíciót mutatja.
A folyamatjelző sávra kattintva elindíthatja a lejátszást a megadott ponttól.
A bal és jobb oldali beviteli mezők lehetővé teszik a dallamrészlet kezdetének és végének megadását ms-ban.

A „Nincs elég csatorna a dallam lejátszásához” felirat pirosan azt jelzi, hogy nincs elég szintetizátorcsatorna a dallam lejátszásához az aktuális beállításokkal. Ha a lejátszó nem talál szabad csatornát, kikapcsolja a legrégebbi hangot. Sok esetben ez jól fog működni. Csak akkor van értelme a csatornák számát növelni, ha a dallam nem megfelelő a fülben.

A beállítások feloszthatók lejátszó beállításokra és midi fájlfeldolgozási beállításokra. A lejátszó akkor tudja lejátszani a kapott dallamkódot, ha a lejátszó konfigurációja és a dallamkód ugyanazokkal a lejátszóbeállításokkal lett létrehozva. Ezenkívül a lejátszó képes lesz lejátszani egy olyan dallamot, amelynek kódja egy kisebb (de nem nagyobb) csatornaszámú lejátszóhoz készült.

A lejátszó hardverbeállításai a következők:

– Sampling Rate – szintézis frekvencia. A maximális fúziós frekvenciát kísérleti úton határozzuk meg. Az Atmega 16MHz alapján 12000 Hz-ről indulhat egy 6 csatornás lejátszónál, és tetszés szerint növelheti, amíg a dallamtorzulás észrevehetővé válik a hardveres lejátszóban. A maximális frekvencia a csatornák számától, a hullámformától és magának a dallamnak a bonyolultságától függ.

– Hullámforma – Hullámforma:
– Négyszöghullám – meander;
– Szinusz – szinusz;
– Szinusz + boríték – szinusz csillapítással;
– Hullámforma * + Envelope – különféle lehetőségek nem szinuszos hullámokhoz csillapítással és anélkül;
– Egyéni minta – használja a műszer mintáját.

A „Minta betöltése” gomb lehetővé teszi a minta betöltését egy WAV fájlból. A WAV fájlnak PCM 8 bites monó, 4173 Hz, C-5 formátumban kell lennie. Tipp: Növelheti a frekvenciát és csökkentheti a hangot, de módosíthatja a hangmagasságot a lejátszó beállításaiban. Nincsenek formátumellenőrzések – ha a formátum eltérő, a hang nem fog megfelelően játszani.
Hangmagasság – lehetővé teszi a hang magasságának módosítását. Ha például 1 oktávval magasabban szeretne játszani, be kell állítania a Hangmagasság +12 értéket.

Használjon tömörítést – használjon dallamtömörítést.
Dobszintetizátor engedélyezése – a dobszintetizátor engedélyezése.

Játékos csatornák: A szintetizátor csatornáinak száma (az egyidejűleg megszólaló hangok maximális száma).

A Midi fájl feldolgozási beállítások a következők:

Általában nincs szükség ilyen finomhangolásra. Ezeket a beállításokat alapértelmezettként lehet hagyni.

Player API

A lejátszó megvalósítása a Common\hxMidiPlayer.c és a Common\hxMidiPlayer.h fájlokban található. Ezeket a fájlokat bele kell foglalni a projektbe. Létre kell hoznia egy hxMidiPlayer_config.h fájlt is, amelyben el kell helyeznie a konfigurációt.
A lejátszó C nyelven íródott, szerelőbetétek nélkül, ami megkönnyíti a portolást más mikrokontrollerekre.

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

Kezdje el lejátszani a dallamot. A _delay beállítja a kezdeti késleltetést a lejátszás előtt, 255 egység = 1 másodperc.

Void Player_Stop();

Hagyja abba a dallam lejátszását.

Extern bool Player_IsPlaying();

False értéket ad vissza, ha a dallam lejátszása befejeződött.

Extern void Player_WaitFinish();

Várja meg, amíg a dallam befejeződik.

Extern void Player_TimerFunc();

Ezt a funkciót időzítő megszakításban kell meghívni a konfigurációban megadott mintavételezési gyakorisággal. Amikor a dallam lejátszása befejeződött, nem kell hívást kezdeményeznie.

Extern void Player_Output(uint8_t minta);

A felhasználónak kell megvalósítania. A lejátszó hívja, amikor a következő mintát kell kiadni.

Extern void Player_Started();

A felhasználónak kell megvalósítania. Akkor hívják, amikor a játékos elkezd játszani egy dallamot. Használható időzítő megszakítások konfigurálására.

Extern void Player_Finished();

A felhasználónak kell megvalósítania. Akkor hívják, amikor a lejátszó befejezte a dallam lejátszását. Használható az időzített megszakítások letiltására, vagy egy másik dallam lejátszásának elindítására.

//#define NOTES_TO_EEPROM //#define SINETABLE_TO_EEPROM //#define ENVELOPE_TO_EEPROM

Ezeket a sorokat megjegyzés nélkül kell hagyni a hxMidiPlayer_config.h fájlban, ha a jegyzettáblázatot, a szinusztáblát és a csillapítási táblázatot az eepromban kell elhelyezni.

Példa projektek

ATMega644Example – projekt ATMega644, 25 MHz, PWM kimenethez a PB3-on.

Memóriakövetelmények

Asztal. A lejátszó mérete és a dallamok vakuban.

*Ha lejátszót ad hozzá egy meglévő, nem üres projekthez, a kód mérete kisebb lesz

**nincs elég csatorna a normál dallamlejátszáshoz

1. dallam: bach_minuet_in_g.mid, 35 mp
2. dallam: yiruma-river_flows_in_you.mid, 165 mp
3. dallam: Franz Schubert – Szerenád.közép, 217 mp

Ahogy a táblázatból is látszik, a minimális konfigurációban még az ATTiny2313-ba is bele lehet préselni egy elég hosszú dallamot. A tömörítés több mint kétszeresére csökkentheti a dallamot, de a lejátszó kód mérete ~600 bájttal nő.

A szinuszos és a lecsengési jegyzettáblázatok elhelyezhetők az EEPROM-ban, így körülbelül 16, 50 és 100 bájt flash memória takarítható meg.

Ha wav fájlból származó mintát használ, hozzá kell adnia a minta méretét bájtokban a lejátszó kódjának méretéhez.

Használati példa

Példaként a lejátszó használatára nézzük meg a zenedoboz létrehozásának folyamatát.

Kész MDF dobozt veszünk:

Mikrokontrollerként az ATTiny85-öt SO-8-as kiszerelésben vesszük a legolcsóbbnak kellően nagy memóriával. Túlhúzzuk 27 MHz-re, hogy 18 kHz-es szintézisfrekvenciát kapjunk 4 szinusz+burkológörbe csatornával.

Az erősítő D-osztályú lesz, 4 tranzisztorral, hogy kímélje az akkumulátorokat.

A tranzisztorok kapcsolási módban működnek, és bármilyen típusúak lehetnek. Az L1 induktivitás és a C6 kondenzátor ízlés szerint van kiválasztva, hogy a hangot magas frekvenciájú zaj nélkül állítsák elő. Az R1 és az R2 2K-ig növelhető a hangerő csökkentése és a hangszóró visszapattanásának csökkentése érdekében.

A lemezmeghajtó végálláskapcsolója tökéletesen illeszkedik, mintha kifejezetten a dobozhoz lett volna létrehozva (nyitva működik - amikor kinyitja a fedelet, a tábla áramellátást kap):

A firmware-források az ATTiny85MusicBox könyvtárban találhatók.

8Kb illik:
1) lejátszó: 18000Hz, 4 csatorna, Sine+Envelope, Pitch+12, tömörítés, egyenként játssza le a dallamokat (az utolsó EEPROM-ban van tárolva)
2) Yiruma – Folyó folyik benned
3) Franz Schubert – Szerenád
4) P.I. Csajkovszkij "október"

Eredmény a videón:

További fejlődés

A lejátszót elvileg tovább lehet fejleszteni, egy teljes értékű Midi vagy MOD lejátszóvá alakítva. Én személy szerint úgy gondolom, hogy a jó minőségű dallam eléréséhez egyszerűbb lenne csatlakoztatni egy SD-kártyát és lejátszani róla bármilyen WAV-fájlt legjobb minőség mint általában szoftverszintézissel elérhető. És egy ilyen lejátszó szoftveresen és hardveresen sokkal egyszerűbb. A hxMidiPlayer rése jó hangzást ad a kész projektekhez, ha van néhány láb és egy kis hely a vakuban. Ezzel a feladattal már meglévő formájában „kitűnően” megbirkózik.

Szerintem ezzel lezárható a mindenféle zenedoboz/harang létrehozásának kérdése az AVR-n :)

A lecke folytatása sokáig tartott, ami érthető, el kellett sajátítanom a memóriakártyákkal és fájlokkal való munkát FAT rendszer. De mégis megtörtént, a lecke készen van – valójában újévi csoda.

Annak érdekében, hogy ne terheljük túl a cikket információkkal, nem írom le a wav fájlformátum szerkezetét, több mint elegendő információ található a keresőmotorokban. Elég annyit mondanunk, hogy ha valamilyen Hex szerkesztővel nyitunk meg egy fájlt, akkor az első 44 bájt tartalmazza az összes információt a fájl típusáról, mintavételi gyakoriságáról, csatornák számáról stb. Ha elemezni kell a fájlt, olvassa el ezt fejléc, és boldog leszel.

A hasznos adat 44 bájtnál kezdődik, lényegében a hangot alkotó feszültségszinteket tartalmazza. Az óra utolsó részében már beszéltünk a feszültségszintekről. Így minden egyszerű, ezeket a lépéseket a fájl mintavételi frekvenciáján kell kiadnia a hangszórónak.

Hogyan lehet fizikailag rázni a hangszórót? Ezeket a feszültségszinteket PWM vagy R2R használatával kell kiadnia. Mindenesetre nagyon egyszerű a használata, olvasd le a számot, rakd be akár OCR-be, akár PORTx-be. Ezután egy bizonyos idő elteltével behelyettesítettem a következő értékkel, és így tovább a fájl végéig.

Példa egy bizonyos wav fájl, az adatok 44=0x2C bájtokból származnak, oda van írva a 0x80 szám, reprodukáljuk a hangot pl. az első időzítő PWM-ével, írjuk OCR1A=0x80; Tegyük fel, hogy a mintavételezési frekvencia 8 kHz, tehát a megszakítást ugyanarra a frekvenciára kell beállítani. A megszakításban 1/8000 = 125 µs után cserélje be a következő értéket 0x85-re.

Hogyan állítsuk be a megszakítást 8 kHz-re? Emlékezzünk arra, hogy ha az időzítő 250 kHz frekvencián működik, akkor a megszakítás összehasonlító regisztert be kell cserélni (250/8)-1=31-1 vagy 0x1E. A PWM-mel is minden egyszerű: minél magasabb frekvencián működik, annál jobb.

A firmware működéséhez egyetértünk abban, hogy a flash meghajtó FAT32 formátumban van formázva, a 23.2 lecke PetitFat lib használatával. A fájl wav formátumú, 8kHz vagy 22.050kHz, monó. Fájlnév 1.wav. Elemezzük a firmware-t.

#beleértve #include "diskio.h" #include "pff.h" unsigned char puffer[ 512 ] ; /* puffer, amelybe az információkat a flash meghajtóról másolja */ volatile unsigned int count; //adatszámláló másolt megszakítás [TIM2_COMP] void timer2_comp_isr(void) //megszakítás, amelyben az értékeket helyettesítik( OCR1A = puffer[ count] ; // hangot ad ki a hangszóróba ha (++ szám >= 512 ) //növeljük a számlálót szám = 0 ; //ha az 512 visszaáll) void main(void) ( unsigned int br; /* fájl olvasási/írási számlálója */ előjel nélküli char buf = 0 ; //változó, amely meghatározza, hogy a puffer melyik része kerül beolvasásra FATFS fs; /* Munkaterület (fájlrendszer-objektum) logikai meghajtókhoz */ PORTB= 0x00 ; DDRB= 0x02 ; //ugrás alátét ocr1a // Időzítő/Számláló 1 inicializálása// Óraforrás: System Clock // Órajel értéke: 8000 000 kHz // Mód: Fast PWM top=0x00FF // OC1A kimenet: Non-Inv. TCCR1A= 0x81 ; TCCR1B= 0x09 ; TCNT1= 0x00 ; OCR1A= 0x00 ; // Timer/Counter 2 inicializálása// Óraforrás: System Clock // Órajel értéke: 250 000 kHz // Mód: CTC top=OCR2 TCCR2= 0x0B ; TCNT2= 0x00 ; //OCR2=0x1E; //összehasonlító regiszter beállítása 8kHz-re OCR2=0xA; //22kHz-hez #asm("sei") // Időzítő(k)/Számláló(k) Megszakítás(ok) inicializálása if (disk_initialize() == 0 ) //inicializálja a flash meghajtót( pf_mount(&fs) ; //hegy fájlrendszer pf_open("1.wav" ) ; //szál megnyitása pf_lseek(44) ; //vigye a mutatót 44-re pf_read(puffer, 512 ,& br) ; //először 512 bájtot nyelünk le egyszerre TIMSK= 0x80 ; //bekapcsolja a zenét miközben (1) ( if (! buf && count> 255 ) //ha több mint 255 bájt reprodukálódik,( pf_read(& puffer[ 0 ], 256 ,& br) ; //majd beolvassuk a pendrive-ról az információt a puffer első felébe buf=1; ha (br< 256 ) //ha a puffer nem tartalmaz 256 értéket, az a fájl végét jelenti szünet ; ) if (buf && count< 256 ) { pf_read(& buffer[ 256 ] , 256 ,& br) ; // olvassa be a puffer második részét a flash meghajtóról buf = 0; ha (br< 256 ) break ; } } TIMSK = 0x00 ; //глушим все pf_mount(0x00 ) ; //bontsd le a fátylat) míg (1 ) ( ) )

#beleértve #include "diskio.h" #include "pff.h" unsigned char puffer; /* puffer, amelybe az információkat a flash meghajtóról másolják */ volatile unsigned int count; //másolt adatok számlálója megszakítás void timer2_comp_isr(void) //megszakítás, amelyben az értékeket helyettesítenek ( OCR1A = puffer; //hangot ad ki a hangszóróba, ha (++count >= 512) //a számláló számának növelése = 0; //if 512 reset ) void main(void) ( unsigned int br; /* fájl olvasási/írási számláló */ unsigned char buf = 0; //változó, amely meghatározza, hogy a puffer melyik része olvassa FATFS fs; /* Működik terület (fájlrendszer-objektum) logikai meghajtókhoz */ PORTB=0x00; DDRB=0x02; //ugrás az alátétre ocr1a // Timer/Counter 1 inicializálás // Óraforrás: System Clock // Órajel értéke: 8000 000 kHz // Mód: Fast PWM top=0x00FF // OC1A kimenet: Non-Inv. TCCR1A=0x81; TCCR1B=0x09; TCNT1=0x00; OCR1A=0x00; // Timer/Counter 2 inicializálás // Óraforrás: Rendszeróra // Óraérték : 250 000 kHz // Mód: CTC top= OCR2 TCCR2=0x0B; TCNT2=0x00; //OCR2=0x1E; //az összehasonlító regiszter beállítása 8kHz-re OCR2=0xA; //22kHz-hez #asm("sei") // Időzítő(k)/Számláló(k) Megszakítás(ok) inicializálása if(disk_initialize()==0) //a flash meghajtó inicializálása ( pf_mount(&fs); //csatlakoztassa a fájlrendszert pf_open("1.wav"); //megnyitjuk az ágat pf_lseek(44); //a mutató mozgatása 44 pf_read(buffer, 512,&br); //először 512 bájtot nyelünk le egyszerre TIMSK=0x80; //bekapcsolja a zenét while(1) ( if(!buf && count>255) //ha több mint 255 bájtot játszott le, ( pf_read(&buffer, 256,&br);//majd olvassa be az információt a flashről behajtás a puffer első felébe buf=1 ; if (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) { } }

Az ellenőrzéshez egy hangszórót csatlakoztatunk az OCR1A érintkezőhöz egy 100 uF-os kondenzátoron keresztül, a „+” jelet a mikrokontroller tűjéhez, „-” a hangszóróhoz. „-” hangszóró a földhöz, „+” a kondenzátorhoz.

Ne várjon hangos jelet a kimeneten, erősítőre van szüksége a hangos hangzáshoz. Ez jól látható a videón. A teszthez a kakast 8 kHz-el, a pályát 22 kHz-cel terheltem.

Aki szeretné, az nyugodtan növelheti a timer2 frekvenciáját a 44 kHz-es fájlok lejátszásához, a kísérletek azt mutatják, hogy elég jó hangminőség érhető el. A videóban gyenge a hang és rossz a minőség, de valójában ez annak köszönhető, hogy kamerával vettem fel.

Szintén közzéteszem az Apparatchik által kedvesen biztosított anyagokat - a GCC forráskódját, amelyből a CAVR firmware-e íródott.

És videó 44 kHz-es lejátszással.

Megragadom az alkalmat, hogy gratuláljak mindenkinek az újévhez, kívánom, hogy minden firmware és eszköz működjön neked :)

wav player projekt az Atmega8-on

Írtam egy szoftvermodult, amely lehetővé teszi dallamok vagy hangszekvenciák lejátszásának funkcióját az AVR mikrokontroller szinte bármely projektjéhez.

A modul jellemzői:

Egyszerű integráció egy kész projekttel

Csak a 8 bites t2 időzítőt használjuk, de továbbra is használható lekérdezésre vagy időintervallumok kialakítására

A modul szinte bármilyen órajelgenerátor frekvenciára állítható

A hangok hangmagassága szimbolikus állandóként (C0, A2 stb.) vagy Hertzben van megadva

Az időtartamok szabványos formában (negyedek, nyolcadok stb.) vagy ezredmásodpercben vannak megadva

Lehetőség van a dallam lejátszási tempójának és ismétléseinek számának beállítására

Lejátszás közben a dallam szüneteltethető


Hangmodul csatlakoztatása

1. Másolja az összes modulfájlt (tone.h, sound.h, sound.c) a projekt mappájába.

2. Csatlakoztassa a sound.c fájlt a projekthez.

IAR `a esetén – kattintson a jobb gombbal a munkaterület ablakában, és válassza a Hozzáadás > Fájlok hozzáadása…

A WINAVR esetében nagyjából ugyanez, csak a sound.c-t kell hozzáadni a makefile-hoz:

SRC = $(TARGET).c hang.c

3. Szerelje be a hang.h fejlécfájlt a megfelelő modulba. Például a main.c

#include "hang.h"

4. Adja meg a modul beállításait a sound.h fájlban

//ha kommenteled, akkor a jegyzetek időtartama lesz

//a dallamban megadott BPM-ből számolva

//ha maradt, akkor az alább megadott értéktől

//#define SOUND_BPM 24

//órafrekvencia μ

#define SOUND_F_CPU 16U

//a mikrokontroller kimenete, amelyen a hang létrejön

#define PORT_SOUND PORTB

#define PINX_SOUND 0

//meghatározott dallamok száma.

#define SOUND_AMOUNT_MELODY 4

5. Adja hozzá dallamait a sound.c-hez, és írja be a dallamok nevét a dallamtömbbe.

Csengőhangok hozzáadása

A dallam 16 bites számokból álló tömb, és a következő szerkezettel rendelkezik

BPM (negyed hangok percenként) egy konstans, amelyet a hangok időtartamának kiszámításához használnak, és meghatározza a dallam lejátszási sebességét.

A BPM 1-től 24-ig terjedhet, ami percenként 10, illetve 240 negyed hangnak felel meg.

Ha a hangok/hangok időtartama ezredmásodpercben van megadva, akkor a tömbbe írt BPM-nek 1-nek kell lennie.

Ha a SOUND_BPM konstans ki van írva a hang.h fejlécfájlban, akkor a hangjegyek időtartama a program végrehajtása során a tömbben megadott BPM szerint kerül kiszámításra. Ha a SOUND_BPM nincs kommentálva, akkor a hangok időtartama a fordítási szakaszban ennek az állandónak az értéke alapján kerül kiszámításra, és minden dallam ugyanabban a tempóban szólal meg. Ez korlátozza a funkcionalitást, de megtakarít néhány bájt kódot.

Ismétlések száma. 1 ... 254 és LOOP (255) értékeket vehet fel. LOOP - azt jelenti, hogy a dallam a végtelenségig ismétlődik, amíg a SOUND_STOP vagy SOUND_PAUSE parancsot ki nem adják.

Megjegyzés időtartama– az az idő, ameddig egy adott hang hangot generál vagy szünetet tart fenn. Megadható ms-ban, az ms(x) makró használatával, vagy szabványos hangjegyértékekként - nyolcad hangok, tizenhatod hangok stb. Az alábbiakban felsoroljuk a támogatott időtartamokat. Ha szükség van néhány egzotikus időtartamra, bármikor hozzáadhatja azokat a tone.h fájlhoz

n1 - egész hangjegy

n2 - fél hang

n4 - negyed

n8 - nyolcadik

n3 - nyolcadik hármas

n16 - tizenhatodik

n6 - sextole

n32 - harminckettedik

Megjegyzés hangmagasság a tone.h fájlban leírt szimbolikus állandókkal van megadva, például C2, A1 stb. A hangok hangmagassága is megadható Hertzben az f(x) makró használatával.

A programnak korlátozásai vannak a minimális és maximális hangfrekvenciára vonatkozóan!

Dallamvég jelző. A tömb utolsó elemének értékének nullának kell lennie.

A hangmodul használata

A main elején meg kell hívni a SOUND_Init() függvényt. Ez a funkció beállítja a mikrokontroller kimeneti lábát, konfigurálja a T2 időzítőt és inicializálja a modul változóit.

Ezután be kell állítani a megszakítás engedélyezése jelzőt - __enable_interrupt(), mert a modul T2 időzítő túlcsordulást és koincidencia megszakításokat használ.

Ezt követően elkezdheti a dallamok lejátszását.

Például így:

HANG_SetSong(2);

HANG_Com(HANG_LEJÁTSZÁS); //dallam lejátszása

//a mutatót a 2. dallamra állítja

//és indítsa el a lejátszást

HANG_PlaySong(2);

A dallam lejátszása bármikor leállítható a SOUND_STOP parancs kiadásával.
A dallamot a SOUND_PAUSE paranccsal is szüneteltetheti. A SOUND_PLAY parancs ezt követő kiadása a dallam lejátszását attól a ponttól folytatja, ahol abbahagyta.

Erre a funkcióra elvileg nincs különösebben szükség (most találtam ki) és a modullal való munka során elég a SOUND_PlaySong(unsigned char numSong) funkció;

Fájlok

Az alábbi linkekről letölthet példákat a hangmodul használatára. Nem rajzoltam diagramot, mert ott minden egyszerű. csatlakozik a PB0 érintkezőhöz, a dallamok indítógombja a PD3 érintkezőhöz csatlakozik. A projektekben 4 dallam van meghatározva. A gomb megnyomása minden alkalommal új dallamot indít el. Az atmega8535 mikrokontroller használatos. Kezdetben egy négy gombos projekttel akartam bajlódni - PLAY, STOP, PAUSE és NEXT, de aztán úgy gondoltam, hogy ez felesleges.

PS: A modul nem esett át kiterjedt tesztelésen, és „ahogy van” áll rendelkezésre. Ha vannak racionális javaslatok, véglegesítsük.

Ebben a cikkben megvizsgáljuk, hogyan kell lejátszani a hangokat, és megtanuljuk, hogyan kell lejátszani egy monofonikus dallamot.

Felkészülés a munkára

A program két tömböt deklarál. Tömb jegyzetekkel jegyzetek egyszerű jegyzetlistát tartalmaz. Ezeket a hangokat a tömbben lévő hang időtartamával egyeztetjük veri. A zenében az időtartamot a hang osztója határozza meg az egész hanghoz viszonyítva. Az érték egészében véve a következő 255 . A feleket, negyedeket, nyolcadokat ennek a számnak az elosztásával kapjuk.
Felhívjuk figyelmét, hogy az első hang időtartamát nem úgy kapjuk meg, hogy 255-öt elosztjuk kettő hatványával. Itt át kell váltanod a zeneelméletre. Az eredeti dallam hangjegyei megtekinthetők. Ezeket a hangjegyeket hármasjegyekké egyesítik. Ily módon kombinálva három nyolcad hang ugyanaz, mint egy negyedhang. Ezért relatív időtartamuk 21.
A felhasználónak kifejezetten meg kell adnia a jegyzetek számát a szekvenciában az irányelvvel:

# határozza meg a SEQU_SIZE 19-et

A főprogramban mindenekelőtt a frekvenciatömbök újraszámítása történik, az időtartam pedig a jelek periódusaira és a hangok időtartamára.
Jelperiódusokkal (tömb signal_period) minden egyszerű. A periódus időtartamának mikromásodpercben való kiszámításához egyszerűen el kell osztani 1 000 000-et a jel frekvenciájával.
A hangjegyek hangzásának abszolút időtartamának kiszámításához fel kell tüntetni a zenei mű tempóját. Ez direktívával történik

# határozza meg a TEMPO 108-at

A zenei tempó a percenkénti negyed hangok száma. Sorban

# define WHOLE_NOTE_DUR 240000 / TEMPO

Egy egész hang időtartamát ezredmásodpercben számítják ki. Most elegendő újraszámolni a relatív értékeket a tömbből a képlet segítségével veri abszolút tömbhöz note_duration.
A főhurokban a változó eltelt idő A lejátszott jel minden periódusa után növekszik ennek a periódusnak az időtartamával, amíg meg nem haladja a hang időtartamát. Érdemes odafigyelni erre a bejegyzésre:

while(eltelt_idő< 1000 * ((uint32_t) note_duration[ i] ) )

Változó eltelt idő 32 bites, és a tömbelemek notes_duration 16 bites. Ha egy 16 bites számot megszorozunk 1000-el, akkor garantált a túlcsordulás és a változó eltelt idő szeméthez fogják hasonlítani. Módosító (uint32_t) tömbelemet alakít át notes_duration[i] 32 bites számban nincs túlcsordulás.
A hanghurokban egy másik funkció is látható. A funkció nem használható _delay_us(), mivel argumentuma nem lehet változó.
Ilyen késések létrehozásához használja a funkciót VarDelay_us(). Ebben egy 1 μs késleltetésű hurkot meghatározott számú alkalommal görgetünk.

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

Dallam lejátszásakor két további késleltetést használunk. Ha a hangjegyeket szünet nélkül játssza le, akkor azok egybeolvadnak. Ehhez a direktíva által meghatározott 1 ms-os késleltetést kell beilleszteni közéjük:

# definiálja a NOTES_PAUSE 1

A dallam lejátszásának minden teljes ciklusa után a program 1 másodpercre megáll, és újrakezdi a lejátszást.
Ennek eredményeként olyan kódot kaptunk, amiben egyszerűen lehet tempót változtatni, beállítani az időtartamot, vagy teljesen átírni a dallamot. Ehhez elég lesz csak a program részét átalakítani direktívákkal és változódeklarációkkal.

Egyéni feladatok

  1. A javasolt dallamban próbálja megváltoztatni a tempót, és 5 másodperces szünetet tartani az ismétlések között.
  2. Tömb elemek veri Csak 0 és 255 közötti értékeket fogadjon el. Változtassa meg a tömbelemek bitszélességét, és nézze meg a fordító kimenetében, hogy ez hogyan befolyásolja a program által elfoglalt memória mennyiségét.
  3. Most próbálja meg saját maga megváltoztatni a dallamot. Például itt van az „Imperial March” ugyanabból a filmből: 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 ütem = ( 50 , 20 , 50 , 20 , 50 , 20 , 40 , 5 , 20 , 5 , 60 , 10 , 40 , 5 , 20 , 5 , 60 , 80 , 0 , 5 20, 40, 5, 20

    Ha autójában nincs sziréna felszerelve, és még mindig nem tudja eldönteni, hogy melyiket vásárolja meg és telepítse, akkor ez a cikk csak Önnek szól. Miért vásároljon drága riasztót, ha mindezt saját maga is össze tudja szerelni meglehetősen egyszerű módon?

    Ebből kettőt mutatok be egyszerű áramkörök Az AVR ATmega8 és Attiny2313 mikrokontrollereken, vagy inkább ugyanazt az áramkört valósítják meg, hogy ezen a két mikrokontrolleren működjön. Az archívumban egyébként az Atmega8 mikrokontroller firmware-jének két verziója található, amelyek közül az első a hangzáshoz hasonló hangot ad. autóriasztó, és a második hang hasonló az épület biztonsági riasztójához (gyors és éles jelzés).

    A lenti összes firmware-t letöltheti az archívumból (mind alá van írva), az archívumban a Proteus áramkörök szimulációját is megtalálja, ami azt jelenti, hogy az összes dallam meghallgatása után kiválaszthatja a listából azt, ami a legjobban tetszik. .

    Az alábbiakban az Atmega8 jelzési diagramja látható

    Az Atmega8 áramkörben használt rádióalkatrészek listája

    U1- AVR mikrokontroller 8 bites ATmega8-16PU, darab. 1,
    R1- 47 Ohm névleges értékű ellenállás, sz. 1,
    R2, R3 - 270 Ohm névleges értékű ellenállás, sz. 2,
    D2,D3-LED, sz. 2,
    LS1 hangszóró, sz. 1,
    S1-érzékelő.

    Az Attiny2313 jelzőáramkörében pedig csak az MK módosult.
    U1- Mikrokontroller AVR 8 bites ATtiny2313-20PU, sz. 1.

    Nyomtatott áramkör Az Atmega8 esetében így néz ki:

    Mint látható, az áramkör nagyon egyszerű, csak egy mikrokontroller, 3 ellenállás, 2 LED és még egy hangszóró található. Gomb helyett használhat reed kapcsolót vagy más érintkezőt.

    A működési elv a következő. Amint bekapcsoljuk a tápfeszültséget, a LED (a D3 áramkörben) azonnal kigyullad vagy villogni kezd (a firmware-től függően), és ha nem érintjük meg az érzékelőt, a riasztás elnémul. Most, ha kiold az érzékelő, akkor a sziréna is működik, a LED is villog, de D2.

    Ha azt szeretné, hogy az autó fényszórói villogjanak, amikor a riasztó működik, akkor ehhez csatlakoztatnia kell a 24 PC1 mikrokontroller lábát egy tranzisztoron keresztül a reléhez, és magát a relét a fényszórókhoz. A sziréna kikapcsolásához ki kell kapcsolni, majd újra be kell kapcsolni a készüléket, vagy egyszerűen meg kell nyomni a gombot. A mikrokontroller működtetéséhez belső 8 MHz-es oszcillátorra van szükség,

    Ha valamilyen módon fokozni szeretné a riasztás hangját, összeállíthat egy erősítőt tranzisztorokkal, és csatlakoztathatja az áramkörhöz. Pontosan ezt tettem, de nem ábrázoltam ezen az ábrán.

    Térjünk át az Attiny 2313 áramkörére, ahogy korábban mondtam, ugyanazok a részletek és ugyanaz a működési elve, csak az MK-t változtatták meg, és ennek eredményeként a csatlakoztatott érintkezőket. belső 4 MHz-es oszcillátor, bár 1 MHz-en is lehet villogni.

    Az alábbiakban az Attiny2313-on már látható bekötési rajz

    Ehhez az MK-hoz csak egy firmware-verziót írtam, mindent összeállítottam az áramköri lapon, ellenőriztem, minden jól működik.
    És a biztosítékokat az alábbiak szerint kell beállítani:





Top