Atmega8 soittoäänet. Yksinkertaiset sireenit MK AVR:ssä. Äänimoduulin käyttö

Artikkelissa kuvataan musiikin synteesin periaatteet AVR:llä. Mukana olevan ohjelmiston avulla voit muuntaa minkä tahansa midi-tiedoston lähde C-muodossa AVR-mikro-ohjaimille musiikillisten fragmenttien toiston lisäämiseksi valmiisiin kehitystöihin. Tarkastellaan esimerkkiä ohjelmiston käytöstä musiikkilaatikossa.

Ensin lyhyt video siitä, kuinka kaikki toimii:

Mitä ohjelmisto sallii

PC-ohjelmiston avulla voit saada C-lähteen CodeVision AVR:lle, joka toistaa valitun midi-tiedoston:

1. Yhdistä common\hxMidiPlayer.h, common\hxMidiPlayer.c projektiisi. Kopioi mallit ATMega8Example\melody.h, ATMega8Example\melody.c, ATMega8Example\hxMidiPlayer_config.h ja muodosta yhteys.
2. Käynnistä MidiToC.exe
3. Lataa Midi-tiedosto.
4. Aseta soitin: näytteenottotaajuus, kanavien määrä, aaltomuoto jne. Ohjelmisto toistaa melodian samalla tavalla kuin AVR.
5. Napsauta "Create player config" ja liitä lähde tiedostoon hxMidiPlayer_config.h.
6. Napsauta "Luo melodiakoodi" ja liitä lähde tiedostoon melody.c
7. Projektissamme toteutamme Player_Output() -menetelmän äänen tuottamiseksi PWM:n tai ulkoisen DAC:n kautta.
8. Aseta ajastin näytteenottotaajuudelle ja kutsu keskeytyksestä Player_TimerFunc().
9. Soita Player_StartMelody(&s_melody, 0).

Melodia toistetaan ajastimen keskeytyksestä. Tämä tarkoittaa, että toiston aikana mikro-ohjain voi myös tehdä hyödyllistä työtä.

Kuinka se toimii

Artikkelin loppuosassa yritän selittää lyhyesti, kuinka tämä kaikki toteutetaan. Valitettavasti se ei ole kovin lyhyt - materiaalia on paljon. Jos et ole kiinnostunut, voit siirtyä välittömästi "Ohjelmiston kuvaus"- ja "Soittimen API" -osiin.

Mitä on musiikki

Musiikki on sarja eri taajuuksia ja kestoisia ääniä. Äänen perusharmonisen taajuuden tulee vastata tietyn sävelen taajuutta. Jos äänten värähtelytaajuus eroaa nuottien taajuuksista, meistä näyttää siltä, ​​​​että muusikko on "viimeistynyt".

Pöytä. Huomioi taajuudet, Hz.

Kaikki nuotit on jaettu oktaaveihin, 7 nuottia jokaisessa + 5 puolisäveltä (pianon mustat koskettimet). Vierekkäisten oktaavien sävelten taajuudet eroavat tasan 2 kertaa.

Yksinkertaisin musiikkisoitin sisältää taulukon, jossa on melodian nuottisarja (sävel + kesto) ja taulukon nuottitaajuuksilla. Äänen syntetisoimiseen käytetään yhtä ajastinkanavista, joka muodostaa meanderin:

Valitettavasti tällaisella primitiivisellä soittimella on kiinteä aaltomuoto (neliöaalto), joka ei ole kovin samanlainen kuin oikeita soittimia, ja se voi soittaa vain yhden nuotin kerrallaan.

Todellinen melodia sisältää vähintään kaksi osaa (soolo + basso), ja pianolla soitettaessa edellinen sävel jatkaa edelleen, kun seuraava on alkanut. Tämä on helppo ymmärtää muistamalla pianon rakenne - jokainen nuotti vastaa erillistä kielen. Voimme saada useita kieliä soimaan samaan aikaan ajamalla käsiämme koskettimien päällä.

Joissakin mikro-ohjaimissa on useita ajastinkanavia, joita voidaan käyttää useiden nuottien soittamiseen samanaikaisesti. Mutta yleensä nämä kanavat ovat arvokas resurssi, eikä niitä kaikkia kannata käyttää. Ellemme tietysti tee vain musiikkilaatikkoa.
Kaiken kaikkiaan moniäänisen ja erilaisten musiikki-instrumenttien äänten saamiseksi sinun on käytettävä äänisynteesiä.

Äänen synteesi AVR:llä

hxMidiPlayer käyttää äänisynteesiä ja voi toistaa polyfoniaa eri aaltomuodoilla. Soitin laskee lähtösignaalin amplitudin ajastimen keskeytyskäsittelijässä taajuudella 8-22 KHz (kuinka paljon prosessorin tehoa riittää; riippuu myös aaltomuodosta ja kanavien määrästä).

Äänisynteesin periaatetta voidaan selittää sinimuotoisen synteesin esimerkillä.

Otetaan taulukko, jonka koko on 64, jonka jokaiseen soluun on kirjoitettu siniamplitudin arvot pisteindeksiin * 2 * PI / 64 (yksi jakso):

Static const flash uint8_t s_sineTable[ 64 ] = ( 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x9,0,0x93,0x93,0 x9 5, 0x95, 0x95, 0x94 , 0x93, 0x93, 0x91, 0x90, 0x8F, 0x8D, 0x8C, 0x8A, 0x88, 0x86, 0x84, 0x82, 0x80, 0x7E, 0x7C, 0x70,0x7,0,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,0x76;

128 (0x80) vastaa nollaa, 255 (0xff) suurinta positiivista pistettä, 0 suurinta negatiivista pistettä.

Oletetaan nyt, että tuotamme arvot taulukosta ulkoiseen DAC:iin ajastinkeskeytyksessä, jota kutsutaan taajuudella 1000 Hz:

Staattinen uint8_t s_index = 0; // Ajastin1-ulostulon vertailu Keskeytyksen palvelurutiinin keskeytys void timer1_compa_isr(void) ( SetDac(s_sineTable[ s_index]); if (s_index == 63) ( s_index = 0; ) else ( s_index++; ) )

Mitä saamme tuloksena? Saamme sinivärähtelyt taajuudella 1000/64 Hz.

Nostetaan nyt keskeytyksen indeksiä ei yhdellä, vaan kahdella.
Ilmeisesti lähtövärähtelytaajuus on jo 1000/64 * 2 Hz.

Yleisesti ottaen taajuuden F saamiseksi sinun on lisättävä taulukon indeksiä seuraavasti:
lisää = F / 1000 * 64

Tämä luku voi olla murto-osa, mutta suuren nopeuden saavuttamiseksi käytetään kiinteän pisteen aritmetiikkaa.

Taulukon merkintöjen määrä ja ajastimen taajuus vaikuttavat syntetisoidun äänen laatuun. Meidän tapauksessamme riittää 64 merkintää taulukkoon per jakso ja ajastimen taajuus on 12kHz. Pienin hyväksyttävä ajastintaajuus on 8 kHz, ihanteellinen 44 kHz.

Ilmeisesti 12 kHz ajastintaajuudella voimme tuottaa enintään 6 kHz neliöaaltoja, koska meidän on tehtävä vähintään kaksi kytkintä per jakso. Korkeammat taajuudet ovat kuitenkin edelleen tunnistettavissa, jos lähtötila lasketaan oikein jokaisella ajastimen tikkulla.

Voit syöttää ei-sinimuotoisten värähtelyjen ajanjakson arvot taulukkoon ja saada erilaisen äänen.

Vaimennus

Jos soitin perustuu jousiin (esimerkiksi piano), ääni vaimenee tasaisesti näppäimen painalluksen jälkeen. Luonnollisemman syntetisaattoriäänen saamiseksi sinun on vähennettävä tasaisesti värähtelyjen amplitudia nuotin alun jälkeen (”kääre” värinät vaimennusmuotoon – ”verhokuori”).

Soittimessa on vaimenemistaulukko, jota se käyttää sinin (tai muun aaltomuodon) amplitudin vähentämiseen nuotin alkamishetkestä lähtien.
"Sine" "kääritty" tällaiseen kuoreen muistuttaa mekaanisen musiikkilaatikon ääntä.

Meander-synteesi

Kiertoaallon erityinen muoto mahdollistaa synteesin merkittävästi yksinkertaistamisen. Taulukoita ei käytetä tässä tapauksessa. Riittää, kun lasketaan mikä tila (1 tai 0) lähdön tulee olla tietyllä taajuudella nykyisellä ajastimen tikkulla. Tämä tehdään kokonaislukuaritmetiikkaa käyttäen ja toimii hyvin nopeasti, mikä selittää neliöaallon käytön suosion soittaa kappaleita 8-bittisissä digisovittimissa.

Esimerkki: laskurin ilmoittaminen:

Staattinen uint16_t s_counter = 0;

jota lisäämme 0x8000 jokaisessa ajastinkeskeytyksessä, ja laskurin merkittävin bitti lähetetään porttiin:

// Ajastin1-ulostulon vertailu Keskeytyspalvelurutiinin keskeytys void timer1_compa_isr(void) ( PORTA.0 = (s_counter >> 15) & 1; s_counter += 0x8000; )

Koska 0x8000 + 0x8000 = 0x10000, s_counter-muuttuja vuotaa yli, 17. bitti hylätään ja muuttujaan kirjoitetaan 0x0000.
Siten ajastimen taajuudella 8 kHz lähtö on 4 kHz:n neliöaalto.
Jos lisäät laskuria 0x4000, saat 2 kHz:n neliöaallon.

Yleensä saat taajuuden F lisäämällä:
lisää = F / 8000 * 0x10000

Esimerkiksi saadaksesi neliöaallon, jonka taajuus on 1234 Hz, sinun on lisättävä 0x277C. Todellinen taajuus poikkeaa hieman annetusta, koska pyöristetään termi kokonaislukuun. Tämä on hyväksyttävää syntetisaattorissa.

Oikeiden soittimien äänien synteesi

Voit digitoida nuotin äänen ennen pianoa (käyttäen ADC:tä tallentaaksesi äänen amplitudiarvot muistiin säännöllisin väliajoin):
ja toista sitten ääni (käyttämällä DAC:ta tallennettujen arvojen tulostamiseen säännöllisin väliajoin).

Yleensä rumpujen syntetisoimiseksi sinun on tallennettava rumpuääniä ja toistettava ne oikealla hetkellä. 8-bittisissä konsoleissa käytetään "valkoista kohinaa" rumpuäänien sijaan. "Valkoisen kohinan" amplitudiarvot saadaan generaattorilla satunnaisia ​​numeroita. Muistin kustannukset ovat minimaaliset.
hxMidiPlayer käyttää "white noisea" rumpusynteesiin.

Kanavien miksaus

Äänen amplitudi tietyllä ajastimen tikkulla lasketaan kullekin kanavalle erikseen. Saadaksesi lopullisen amplitudiarvon, sinun on lisättävä kaikkien kanavien arvot. Oikein summaa on säädettävä, koska havaittu äänenvoimakkuus noudattaa logaritmista riippuvuutta, mutta niin yksinkertaisessa syntetisaattorissa joudut tyytymään yksinkertaiseen summaukseen. Siksi kunkin kanavan maksimiamplitudi on 255/N.

Äänentoisto AVR:stä

Kaikkien tarvittavien laskelmien suorittamisen jälkeen soitin vastaanottaa signaalitason, joka on muutettava analogiseksi. Näihin tarkoituksiin voit käyttää ulkoista DAC:ta tai PWM:ää.
Tässä on huomattava, että molemmissa tapauksissa on suositeltavaa suodattaa vastaanotettu signaali - poistaa korkeataajuinen kohina, joka syntyy synteesin ja pyöristyksen alhaisesta taajuudesta.

Lähtö ulkoiseen rinnakkais-DAC:hen

Koska ei ole järkevää käyttää tarkkoja DAC-siruja, tällaiset projektit yleensä tyytyvät R2R-matriisiin:

Tällä mallilla annamme yksinkertaisesti lasketun amplitudin porttiin:

PORTB = näyte;

Virheet:
1) R2R-matriisin lähtö on myös heikko signaali, analogisen vahvistimen käyttö on pakollista;
2) on tarpeen käyttää vähintään 5 nastaa (ja mielellään 8);
Tämä menetelmä on perusteltu vain, kun vapaita PWM-kanavia ei ole.

(Nastajen säästämiseksi voit käyttää ulkoista ADC:tä, jossa on SPI-liitäntä).

PWM

Jos PWM-kanava on vapaa, helpoin tapa on käyttää tätä menetelmää.

PWM-alustus (ATMega8):

// Ajastin/Laskuri 2 alustus // Kellon lähde: Järjestelmän kello // Kellon arvo: 20000.000 kHz // Tila: Nopea PWM top=0xFF // OC2-lähtö: Ei-käänteinen PWM ASSR=0x00; TCCR2=0x69; TCNT2=0x00; OCR2 = 0x00; Ja näytelähtö: void Player_Output(uint8_t sample) ( OC2 = näyte. )

PWM:n yleinen käytäntö sisältää lähtösignaalin tasoittamisen RC-suodattimen avulla:

Valitettavasti suodatuksen jälkeen signaali heikkenee liikaa, joten sinun on tehtävä analoginen vahvistin kaiuttimen kytkemiseksi.

Piirin yksinkertaistamiseksi on parempi pysyä "digitaalisena" itse kaiuttimeen asti. Koska halpa kaiutin ei silti pysty toistamaan yli 30 kHz:n taajuuksia, niitä ei tarvitse suodattaa. Itse diffuusori "suodattaa" korkeat PWM-taajuudet.

Jos tarvitset lisää virtaa, voit käyttää transistorivahvistinta. R1 on valittu antamaan kaiuttimelle tarvittava virta.

Näin voit liittää pienet kaiuttimet leluista:

Suuremmille kaiuttimille on parempi koota asema käyttämällä 2 transistoria ja asentaa LC-suodatin melun poistamiseksi:

Kondensaattori C1 rajoittaa kaiuttimen kautta kulkevaa virtaa, kun PWM ei toimi. Sarjakondensaattorin ansiosta kaiuttimeen pääsee myös signaali, joka on symmetrinen nollan suhteen. Siten kaiuttimen kartio liikkuu keskimmäiseen "rentoon" asentoon, millä on positiivinen vaikutus äänenlaatuun.
Tässä tapauksessa transistorit toimivat kytkentätilassa, joten kantasiirtymää ei tarvitse kompensoida.

PWM, kaksinapainen liitäntä

Kahden ensimmäisen piirin haittana on, että kaiuttimeen syötetään virtaa yhteen suuntaan. Jos muutamme virran suuntaa, äänenvoimakkuutta voidaan lisätä 2 kertaa ylittämättä sallittua tehoa. Tätä varten kaiutin liitetään mikro-ohjaimen kahteen nastaan ​​- ei-invertoituun ja käänteiseen, esimerkiksi OC1A ja /OC1A. Jos ei-invertoitua lähtöä ei ole, voit käyttää toista kanavaa käänteisessä tilassa (OC1B):

// Ajastin/Laskuri 1 alustus // Kellon lähde: Järjestelmän kello // Kellon arvo: 24500 000 kHz // Tila: Fast PWM top=0x00FF // OC1A-lähtö: Non-Inv. // OC1B-lähtö: Käänteinen // Kohinanvaimennus: Pois // Tulon sieppaus laskevalla reunalla // Ajastin1 ylivuotokeskeytys: Pois // Tulon sieppauskeskeytys: Pois // Vertaa A-sovituskeskeytys: Pois // Vertaa B-sovituskeskeytys: Pois TCCR1A =0xB1; TCCR1B = 0x09; TCNT1H = 0 x 00; TCNT1L=0x00; ICR1H = 0 x 00; ICR1L = 0x00; OCR1AH ​​= 0x00; OCR1AL=0x00; OCR1BH = 0x00; OCR1BL=0x00; void Player_Output(uint8_t sample) ( OCR1A = näyte; OCR1B = näyte; )

PWM, kaksi nastaa, D-luokan vahvistin

Ehdotettujen piirien haittana on virrankulutus hiljaisuuden aikana.
"Hiljaisuus" vastaa meille signaalitasoa 128, eli PWM 50% täytöllä - virta kulkee aina kaiuttimen läpi!

Ohjelmistoa hieman muuttamalla saat melko tehokkaan ohjelmisto- ja laitteistoluokan D vahvistimen:

Ei -inverting PWM OCR2 = (näyte-128) * 2; ) else // if (näyte< 128) { TCCR2=0x31; //normal, set on compare match TCCR2=0x31 | 0x80; //SET OC2 PORTC.0 = 1; TCCR2=0x79; //inverting PWM OCR2 = (128-sample) *2; } }

Tässä tapauksessa yksi transistoreiden pari on kytketty PWM-lähtöön, toinen - tavalliseen digitaaliseen lähtöön.

Kuten koodista näkyy, pidämme 128:n yläpuolella olevaa signaalia yhteen suuntaan suuntautuvana virtana ja 128:n alapuolella olevaa signaalia toiseen suuntaan suuntautuvana virtana. Kohdassa 128 molemmat kaiuttimen nastat on kytketty samaan virtalähteen nastaan, eikä virtaa ole. Tasolta 128 poikettaessa PWM-täyttö kasvaa ja kaiuttimen läpi kulkee vastaavan napaisuuden omaava virta.

Tärkeä kohta toteutuksessa on PWM-lähdön pakotettu kytkeminen haluttuun tilaan toisen (tavallisen digitaalisen) nastan (PORTC.0) kytkentähetkellä. OCR2-rekisteriin kirjoittaminen puskuroidaan PWM-häiriöiden poistamiseksi. Meidän on vaihdettava PWM-lähtö välittömästi, odottamatta jakson loppua.

Jälkimmäinen piiri on IMHO paras vaihtoehto yksinkertaisuuden, energiansäästön ja tehon suhteen.

Äänen lähtö SquareWave-aaltomuodolla

Meideriä syntetisoitaessa käytetään yksinkertaistettuja algoritmeja.

Jokainen kanava (mukaan lukien rummut) tuottaa joko 0 tai 1. Näin ollen 3-kanavainen levysoitin antaa arvoja välillä 0...3. Siksi PWM:ää käytettäessä tulostusmenettely näyttää tältä:

Void Player_Output(uint8_t sample) ( OCR2 = näyte * (255 / HXMIDIPLAYER_CHANNELS_COUNT); )

Jos et käytä PWM:ää, niin 3-kanavaisen melodian tuottamiseen riittää kaksi tavallista digitaalilähtöä ja 2-bittinen R2R-matriisi.

MIDI-muoto

Jos katsot tuloksena olevaa melodiakoodia, voit helposti nähdä, että taulukko käyttää toistuvia numeroita pieneltä alueelta. Tämä on ymmärrettävää: melodiassa on rajoitettu määrä säveliä 1-2 oktaavin sisällä, melodian tempo on kiinteä - tasaiset viiveet, kanavien lukumäärä on 0...15.
Kaikki tämä tarkoittaa, että tuloksena olevaa taulukkoa voidaan pienentää merkittävästi käyttämällä jonkinlaista pakkausalgoritmia.
Algoritmit, kuten ZIP, tarjoavat hyvän pakkauksen, mutta vaativat myös paljon muistia toimiakseen (ZIP-sanakirja - 64 Kb). Voimme käyttää hyvin yksinkertaista pakkausmenetelmää, joka käytännössä ei vaadi muistia, jonka ydin on seuraava.

Yhdessä tavussa kaikki luvut jakautuvat tasaisesti välillä 0...255, ja jokaista numeroa edustaa 8 bittiä. Meidän tapauksessamme jotkut numerot ovat paljon yleisempiä kuin toiset. Jos koodaat usein esiintyviä lukuja vähemmällä bitillä ja harvemmin esiintyviä enemmän, voit saada muistivahvistuksen.

Valitsemme kiinteän koodausmenetelmän: bittien 000 001 ja 010 yhdistelmät (pituus - 3 bittiä) edustavat kolmea yleisimmin esiintyvää numeroa. Bittiyhdistelmät 0110, 0111 (pituus – 4 bittiä) – seuraavat 2 yleisintä numeroa jne.:

//000..010 - 0..2 //011 x 3..4 //100 xx 5..8 //101 xxx 9..16 //110 xxx 17..24 //111 välitön

Numerolla 111 alkava yhdistelmä (pituus – 11 bittiä) koodaa kaikki muut numerot.
Bittikoodausmenetelmä voi olla erilainen. Kokeilin useita menetelmiä ja valitsin tämän, joka antaa parhaat tulokset tällaisilla tiedoilla.

Pakkausprosessi näyttää tältä:
1. Laske luvun X kokonaismäärä virrassa X = .
2. Lajittele vähentämällä esiintymistiheyttä streamissa.
3. Ota ensimmäiset 25 numeroa. Ne koodataan pienemmillä biteillä.
4. Koodaa tulovirta.

Tulos on joukko 25 yleisimmin esiintyvää numeroa ja bittivirta.
Tämän pakkauksen avulla voit saavuttaa 50 %:n pakkauksen minimaalisilla muisti- ja suorituskykykustannuksilla. Valitettavasti tämä lisää soittimen koodia, joten pakkausta ei suositella lyhyille melodioille.

Nuottitaajuuksien tallennus

On melko kallista tallentaa kaikkien nuottien taajuudet taulukkoon muistista. Itse asiassa on kaava nuotin taajuuden määrittämiseksi sen midi-numeron perusteella:

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

Mutta murtovoiman laskeminen on melko vaikeaa. Sen sijaan soitin tallentaa 12 nuottitaajuutta ylempään oktaaviin. Alempien oktaavien sävelten taajuudet määritetään vähentämällä taajuutta 2^Y kertaa enemmän, missä Y on alaspäin olevien oktaavien määrä.

Kompression jatkokehitys

Melodia sisältää usein toistuvia katkelmia ("kuorot", "säkeet"). Etsimällä toistuvia fragmentteja ja esittämällä melodian fragmenttien muodossa, voit vähentää melodiaa vielä 50 % kuluttamatta aikaa lähes RAM ja tuottavuus. En ottanut käyttöön tällaista algoritmia, jotta en vaikeuttaisi projektia.

Ohjelmiston kuvaus

Muuntoohjelman pääikkuna:

Load Midi -painikkeella voit ladata midi-tiedoston. Ohjelma alkaa välittömästi toistaa tiedostoa tällä hetkellä valituilla parametreilla simuloiden laitteistossa olevaa ääntä.

Tietoikkuna (4) näyttää:
– Length – valitun melodiafragmentin pituus ms;
– Max Active syntetisaattorikanavat – maksimimäärä samanaikaisesti aktiivisia syntetisaattorikanavia;
– Aktiivisten rumpukanavien enimmäismäärä – "rumpuja" toistavien samanaikaisesti aktiivisten syntetisaattorikanavien enimmäismäärä;
– Aktiivisten stereoäänien enimmäismäärä – saman sävelen toistavien kanavien enimmäismäärä (katso alla);
– Arvioitu koko, tavut – melodian koko tavuina. "Mukautettu näyte" -tilassa koko näkyy muodossa A+B, jossa A on melodian koko, B on näytteen koko. Pelaajakoodin kokoa ei ole määritelty tässä.

Edistymisikkuna näyttää nykyisen toistopaikan.
Voit aloittaa toiston määritetystä kohdasta napsauttamalla edistymispalkkia.
Vasemmalla ja oikealla olevien syöttöruutujen avulla voit määrittää melodian alun ja lopun ms.

Punainen "Ei tarpeeksi kanavia melodian toistamiseen" tarkoittaa, että syntetisaattorikanavia ei ole tarpeeksi melodian toistamiseen nykyisillä asetuksilla. Jos soitin ei löydä vapaata kanavaa, se sammuttaa vanhimman nuotin. Monissa tapauksissa tämä toimii hyvin. On järkevää lisätä kanavien määrää vain silloin, kun melodia kuulostaa väärältä korvalle.

Asetukset voidaan jakaa soittimen asetuksiin ja midi-tiedostonkäsittelyasetuksiin. Soitin voi toistaa tuloksena olevan melodiakoodin, jos soittimen kokoonpano ja melodiakoodi on luotu samoilla soittimen asetuksilla. Lisäksi soitin pystyy soittamaan melodian, jonka koodi on luotu soittimelle, jolla on pienempi (mutta ei suurempi) kanavien määrä.

Soittimen laitteistoasetukset sisältävät:

– Näytteenottotaajuus – synteesitaajuus. Suurin fuusiotaajuus määritetään kokeellisesti. Perustuu Atmega 16MHz:iin, voit aloittaa 12000 Hz:stä 6-kanavaisessa soittimessa ja nostaa sitä halutessasi, kunnes melodiasärö näkyy kuulolla laitteistosoittimessa. Maksimitaajuus riippuu kanavien lukumäärästä, aaltomuodosta ja itse melodian monimutkaisuudesta.

– Aaltomuoto – aaltomuoto:
– Neliöaalto – mutka;
– Sini – sini;
– Sini + kirjekuori – sini vaimennuksen kanssa;
– Aaltomuoto * + Envelope – erilaisia ​​vaihtoehtoja ei-siniaaltoaalloille vaimennuksen kanssa tai ilman;
– Mukautettu näyte – käytä instrumentin näytettä.

"Lataa näyte" -painikkeella voit ladata näytteen WAV-tiedostosta. WAV-tiedoston on oltava PCM 8-bittinen mono, 4173 Hz, C-5. Vihje: Voit lisätä taajuutta ja alentaa nuottia, mutta muuttaa sävelkorkeutta soittimen asetuksista. Muototarkastuksia ei ole - jos muoto on erilainen, ääni ei toistu oikein.
Pitch – voit muuttaa äänen korkeutta. Jos haluat esimerkiksi soittaa 1 oktaavin korkeammalla, sinun on asetettava Pitch +12.

Käytä pakkausta – käytä melodian pakkausta.
Ota rumpusyntetisaattori käyttöön – ota rumpusyntetisaattori käyttöön.

Player Channels: Syntetisaattorikanavien määrä (samanaikaisesti soivien nuottien enimmäismäärä).

Midi-tiedoston käsittelyasetukset sisältävät:

Tyypillisesti tällaista hienosäätöä ei tarvita. Nämä asetukset voidaan jättää oletusasetuksiksi.

Player API

Soittimen toteutus sijaitsee tiedostoissa Common\hxMidiPlayer.c ja Common\hxMidiPlayer.h. Nämä tiedostot on sisällytettävä projektiin. Sinun on myös luotava tiedosto hxMidiPlayer_config.h, johon sinun on asetettava asetukset.
Soitin on kirjoitettu C-kielellä ilman asennusosia, mikä helpottaa sen siirtämistä muihin mikrokontrollereihin.

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

Aloita melodian soitto. _delay asettaa alkuviiveen ennen toistoa, 255 yksikköä = 1 sekunti.

Void Player_Stop();

Lopeta melodian soittaminen.

Extern bool Player_IsPlaying();

Palauttaa epätosi, jos melodia on soitettu.

Ulkoinen void Player_WaitFinish();

Odota, kunnes melodia on soitettu.

Ulkoinen void Player_TimerFunc();

Tämä toiminto on kutsuttava ajastinkeskeytyksessä konfiguraatiossa määritetyllä näytteenottotaajuudella. Kun melodia on soitettu, sinun ei tarvitse soittaa puheluita.

Ulkoinen void Player_Output(uint8_t sample);

Käyttäjän on toteutettava se. Soitin soittaa, kun seuraava näyte on tulostettava.

Ulkoinen void Player_Started();

Käyttäjän on toteutettava se. Kutsutaan, kun soitin alkaa soittaa melodiaa. Voidaan käyttää ajastimen keskeytysten määrittämiseen.

Ulkoinen void Player_Finished();

Käyttäjän on toteutettava se. Kutsutaan, kun soitin on lopettanut melodian soittamisen. Voidaan käyttää ajastimen keskeytysten poistamiseen tai toisen kappaleen soittamiseen.

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

Nämä rivit on poistettava kommenteista hxMidiPlayer_config.h-tiedostossa, jos nuottitaulukon, sinitaulukon ja vaimennustaulukon on sijaittava eepromissa.

Esimerkkiprojektit

ATMega644Example – projekti ATMega644:lle, 25MHz, PWM-lähtö PB3:lle.

Muistivaatimukset

Pöytä. Soittimen koko ja melodiat salamassa.

*kun lisäät pelaajan olemassa olevaan ei-tyhjään projektiin, koodin koko on pienempi

**kanavat eivät riitä normaaliin melodian toistoon

Melodia 1: bach_minuet_in_g.mid, 35 s
Melodia 2: yiruma-river_flows_in_you.mid, 165 s
Melodia 3: Franz Schubert – Serenade.mid, 217 s

Kuten taulukosta näkyy, minimikokoonpanossa voit puristaa melko pitkän melodian jopa ATTiny2313:een. Pakkaaminen voi pienentää melodiaa yli kaksinkertaiseksi, mutta soittimen koodin koko kasvaa ~600 tavua.

Sini- ja vaimenemisnuottitaulukot voidaan sijoittaa EEPROMiin, mikä säästää vastaavasti noin 16, 50 ja 100 tavua flash-muistia.

Kun käytät näytettä wav-tiedostosta, sinun on lisättävä näytekoko tavuina soittimen koodin kokoon.

Käyttöesimerkki

Esimerkkinä soittimen käytöstä tarkastellaan musiikkilaatikon luomisprosessia.

Otamme valmiin MDF-laatikon:

Mikrokontrolleriksi otamme halvimpana ATTiny85:n SO-8-paketissa riittävän suurella muistimäärällä. Ylikellotamme sen 27 MHz:iin saadaksemme 18 kHz:n synteesitaajuuden 4 Sine+Envelope-kanavalla.

Vahvistimesta tulee D-luokan 4 transistoria akkujen säästämiseksi.

Transistorit toimivat kytkentätilassa ja voivat olla mitä tahansa tyyppiä. Induktori L1 ja kondensaattori C6 valitaan maun mukaan äänen saamiseksi ilman suurtaajuista kohinaa. R1:tä ja R2:ta voidaan nostaa 2K:iin äänenvoimakkuuden pienentämiseksi ja kaiuttimien pomppimisen vähentämiseksi.

Levyaseman rajakytkin sopii täydellisesti, ikään kuin se olisi luotu erityisesti laatikkoa varten (se toimii avautuessaan - kun avaat kannen, virta syötetään kortille):

Laiteohjelmiston lähteet sijaitsevat ATTiny85MusicBox-hakemistossa.

8Kb sopii:
1) soitin: 18000Hz, 4 kanavaa, Sine+Envelope, Pitch+12, pakkaus, soittaa melodioita yksitellen (viimeinen on tallennettu EEPROM:iin)
2) Yiruma – Joki virtaa sinussa
3) Franz Schubert – Serenade
4) P.I. Tšaikovski "Lokakuu"

Tulos videolla:

Edelleen kehittäminen

Periaatteessa soitinta voidaan kehittää edelleen tuomalla se täysimittaiseksi Midi- tai MOD-soittimeksi. Itse olen sitä mieltä, että korkealaatuisen melodian saamiseksi olisi helpompi liittää SD-kortti ja toistaa WAV-tiedostoja siitä paljon enemmän. paras laatu kuin yleensä on mahdollista saada ohjelmistosynteesillä. Ja tällainen soitin on ohjelmistoltaan ja laitteistoltaan paljon yksinkertaisempi. HxMidiPlayerin markkinarako lisää hyvää soundia valmiisiin projekteihin, kun salamassa on pari jalkaa jäljellä ja vähän tilaa. Se selviää tästä tehtävästä "erinomaisesti" jo olemassa olevassa muodossaan.

Luulen, että tämä voi sulkea kysymyksen kaikenlaisten musiikkilaatikoiden / kellojen luomisesta AVR: lle :)

Oppitunnin jatkaminen kesti pitkään, mikä on ymmärrettävää; minun oli hallittava työskentely muistikorttien ja tiedostojen kanssa FAT-järjestelmä. Mutta silti se tapahtui, oppitunti on valmis - itse asiassa uudenvuoden ihme.

Jotta artikkelia ei ylikuormittaisi tiedoilla, en kuvaile wav-tiedostomuodon rakennetta, hakukoneissa on enemmän kuin tarpeeksi tietoa. Riittää, kun totean, että jos avaat tiedoston jollain Hex-editorilla, niin ensimmäiset 44 tavua sisältävät kaikki tiedot tiedostotyypistä, näytteenottotaajuudesta, kanavien lukumäärästä jne. Jos haluat analysoida tiedostoa, lue tämä otsikko ja olet onnellinen.

Hyötykuormadata alkaa 44 tavusta, sisältäen olennaisesti äänen muodostavat jännitetasot. Puhuimme jo jännitetasoista oppitunnin viimeisessä osassa. Näin ollen kaikki on yksinkertaista, sinun on tulostettava nämä vaiheet kaiuttimelle tiedoston näytteenottotaajuudella.

Kuinka saada kaiutin tärisemään fyysisesti? Sinun on tulostettava nämä jännitetasot käyttämällä PWM:ää tai R2R:ää. Joka tapauksessa sen käyttö on erittäin helppoa, lue numero, laita se joko OCR:ään tai PORTx:ään. Sitten tietyn ajan kuluttua korvasin seuraavan arvon ja niin edelleen tiedoston loppuun asti.

Esimerkki, tietty wav-tiedosto, data tulee tavuista 44=0x2C, sinne on kirjoitettu numero 0x80, toistamme äänen esim. ensimmäisen ajastimen PWM:llä, kirjoita OCR1A=0x80; Oletetaan, että näytteenottotaajuus on 8 kHz, joten keskeytys tulee asettaa samalle taajuudelle. Korvaa keskeytyksessä seuraava arvo 0x85 1/8000 = 125 µs jälkeen.

Kuinka asettaa keskeytys 8kHz:iin? Muista, että jos ajastin toimii 250 kHz:n taajuudella, tulee keskeytysvertailurekisteri korvata (250/8)-1=31-1 tai 0x1E. PWM:llä kaikki on myös yksinkertaista; mitä korkeammalla taajuudella se toimii, sitä parempi.

Jotta laiteohjelmisto toimisi, sovimme, että flash-asema alustetaan FAT32-muodossa käyttämällä PetitFat libiä oppitunnista 23.2. Tiedosto on wav-muodossa, joko 8kHz tai 22.050kHz, mono. Tiedoston nimi 1.wav. Analysoidaan laiteohjelmisto.

#sisältää #include "diskio.h" #include "pff.h" allekirjoittamaton merkkipuskuri[ 512 ] ; /* puskuri, johon tiedot kopioidaan muistitikulta */ haihtuvien unsigned int count; //kopioitu datalaskuri keskeytys [TIM2_COMP] void timer2_comp_isr(void) //keskeytys, jossa arvot korvataan( OCR1A = puskuri[ määrä] ; // toistaa äänen kaiuttimeen jos (++ määrä >= 512 ) //lisää laskuria count = 0; //jos 512 nollataan) void main(void) ( unsigned int br; /* tiedoston luku-/kirjoituslaskuri */ etumerkitön char buf = 0; //muuttuja, joka määrittää, mikä puskurin osa luetaan FATFS fs; /* Työtila (tiedostojärjestelmäobjekti) loogisille asemille */ PORTB= 0x00 ; DDRB= 0x02; //hyppy välilevy ocr1a // Ajastin/Laskuri 1 alustus// Kellon lähde: Järjestelmän kello // Kellon arvo: 8000 000 kHz // Tila: Fast PWM top=0x00FF // OC1A-lähtö: Non-Inv. TCCR1A = 0x81; TCCR1B= 0x09; TCNT1 = 0x00 ; OCR1A = 0x00; // Ajastin/Laskuri 2 alustus// Kellon lähde: Järjestelmän kello // Kellon arvo: 250 000 kHz // Tila: CTC top=OCR2 TCCR2= 0x0B ; TCNT2= 0x00 ; //OCR2=0x1E; //vertailurekisterin asettaminen 8kHz:lle OCR2 = 0xA; //22kHz:lle #asm("sei") // Ajastin(t)/Laskuri(t) Keskeytysten alustus if (levyn_alustaa() == 0 ) //alustaa flash-asema( pf_mount(&fs) ; //kiinnitys tiedostojärjestelmä pf_open("1.wav" ) ; //avaa ketju pf_lseek(44) ; //siirrä osoitin kohtaan 44 pf_read(puskuri, 512 ,& br) ; //ensimmäistä kertaa nielemme 512 tavua kerralla TIMSK= 0x80 ; //laita musiikki päälle, kun (1) ( if (! buf && count> 255 ) //jos toistetaan yli 255 tavua,( pf_read(& puskuri[ 0 ], 256 ,& br) ; //luimme tiedot flash-asemalta puskurin ensimmäiseen puoliskoon buf = 1; jos (br< 256 ) //jos puskurissa ei ole 256 arvoa, se tarkoittaa tiedoston loppua tauko ; ) if (buf && count< 256 ) { pf_read(& buffer[ 256 ] , 256 ,& br) ; // lukea puskurin toiseen osaan flash-asemalta buf = 0; jos (br< 256 ) break ; } } TIMSK = 0x00 ; //глушим все pf_mount(0x00 ) ; //purkaa verho) kun taas (1 ) ( ) )

#sisältää #include "diskio.h" #include "pff.h" allekirjoittamaton merkkipuskuri; /* puskuri, johon tiedot kopioidaan flash-asemalta */ volatile unsigned int count; //kopioitujen tietojen laskuri keskeytys void timer2_comp_isr(void) //keskeytys, jossa arvot korvataan ( OCR1A = puskuri; //lähettää ääntä kaiuttimeen, jos (++count >= 512) //lisää laskurin määrää = 0; //jos 512 reset ) void main(void) ( unsigned int br; /* tiedoston luku-/kirjoituslaskuri */ unsigned char buf = 0; //muuttuja, joka määrittää, mikä puskurin osa luetaan FATFS fs; /* Toimii alue (tiedostojärjestelmäobjekti) loogisille asemille */ PORTB=0x00; DDRB=0x02; //hyppää välilevy ocr1a // Ajastin/Laskuri 1 alustus // Kellon lähde: Järjestelmän kello // Kellon arvo: 8000 000 kHz // Tila: Fast PWM top=0x00FF // OC1A-lähtö: Ei-inv. TCCR1A=0x81; TCCR1B=0x09; TCNT1=0x00; OCR1A=0x00; // Ajastin/Laskuri 2 alustus // Kellon lähde: Järjestelmän kello // Kellon arvo : 250 000 kHz // Tila: CTC top= OCR2 TCCR2=0x0B; TCNT2=0x00; //OCR2=0x1E; //vertailurekisterin asettaminen 8kHz:lle OCR2=0xA; //taajuudelle 22kHz #asm("sei") // Ajastin(t)/laskuri(t) Keskeytä(t) alustus if(disk_initialize()==0) //alustaa flash-asema ( pf_mount(&fs); //liitä tiedostojärjestelmä pf_open("1.wav"); //avaa haara pf_lseek(44); //siirrä osoitin kohtaan 44 pf_read(buffer, 512,&br); //ensimmäistä kertaa nielemme 512 tavua kerralla TIMSK=0x80; //laita musiikki päälle while(1) ( if(!buf && count>255) //jos yli 255 tavua on toistettu, ( pf_read(&buffer, 256,&br);//lue sitten tiedot flashistä aja puskurin ensimmäiseen puoliskoon 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) { } }

Tarkistaaksesi, yhdistämme kaiuttimen OCR1A-nastaan ​​100 uF:n kondensaattorin kautta, "+" mikro-ohjaimen nastaan ​​ja "-" kaiuttimeen. "-" kaiutin maahan, "+" kondensaattoriin.

Älä odota kovaa signaalia lähdössä; tarvitset vahvistimen, jotta se kuulostaa kovalta. Tämä näkyy selvästi videossa. Testiä varten laasin kukon taajuudella 8 kHz ja radan 22 kHz:llä.

Halukkaat voivat turvallisesti nostaa ajastimen 2 taajuutta 44 kHz:n tiedostojen toistamiseksi; kokeet osoittavat, että melko hyvä äänenlaatu voidaan saavuttaa. Videossa ääni on heikko ja laatu huono, mutta itse asiassa tämä johtuu siitä, että kuvasin sen kameralla.

Lähetän myös Apparatchikilta ystävällisesti toimittamia materiaaleja - GCC:n lähdekoodia, josta CAVR:n laiteohjelmisto on kirjoitettu.

Ja video 44 kHz toistolla.

Käytän tilaisuutta hyväkseni ja onnittelen kaikkia uudesta vuodesta, toivon, että kaikki laiteohjelmistot ja laitteet toimivat sinulle :)

wav-soitinprojekti Atmega8:lla

Kirjoitin ohjelmistomoduulin, jonka avulla voit lisätä melodioiden tai äänisekvenssien toistotoiminnon melkein mihin tahansa AVR-mikro-ohjaimen projektiin.

Moduulin ominaisuudet:

Helppo integrointi valmiiseen projektiin

Vain 8-bittinen ajastin t2 on käytössä, mutta sitä voidaan edelleen käyttää kyselyyn tai aikavälien muodostamiseen

Moduuli on säädettävissä lähes mille tahansa kellogeneraattorin taajuudelle

Nuottien sävelkorkeus määritellään symbolisina vakioina (C0, A2 jne.) tai hertseinä

Kesto on määritetty vakiomuodossa (neljännes, kahdeksasosa jne.) tai millisekunteina

On mahdollista asettaa melodian toiston tempo ja sen toistojen lukumäärä

Toiston aikana melodia voidaan keskeyttää


Äänimoduulin liittäminen

1. Kopioi kaikki moduulitiedostot (tone.h, sound.h, sound.c) projektikansioon.

2. Liitä sound.c-tiedosto projektiin.

IAR `a: napsauta hiiren kakkospainikkeella työtilaikkunaa ja valitse Lisää > Lisää tiedostoja…

WINAVR:lle se on suunnilleen sama, vain sound.c täytyy lisätä make-tiedostoon:

SRC = $(TARGET).c sound.c

3. Sisällytä otsikkotiedosto sound.h vastaavaan moduuliin. Esimerkiksi tiedostossa main.c

#include "ääni.h"

4. Aseta moduulin asetukset sound.h-tiedostossa

//jos kommentoit, muistiinpanojen kesto on

//laskettu melodiassa määritetystä BPM:stä

//jos vasemmalla, niin alla määritetystä arvosta

//#define SOUND_BPM 24

//kellotaajuus μ

#define SOUND_F_CPU 16U

//mikro-ohjaimen lähtö, jolla ääni luodaan

#define PORT_SOUND PORTB

#define PINX_SOUND 0

//määritettyjen melodioiden määrä.

#define SOUND_AMOUNT_MELODY 4

5. Lisää melodiat sound.c:hen ja kirjoita melodioiden nimet melodiataulukkoon.

Soittoäänien lisääminen

Melodia on 16-bittisten numeroiden joukko ja sillä on seuraava rakenne

BPM (neljännesnauttia minuutissa) on vakio, jota käytetään nuottien keston laskemiseen ja määrittää nopeuden, jolla melodia toistetaan.

BPM voi vaihdella välillä 1-24, mikä vastaa 10 ja 240 neljännessäveliä minuutissa.

Jos nuottien/äänien kesto on määritetty millisekunteina, taulukkoon kirjoitetun BPM:n tulee olla yhtä suuri kuin 1.

Jos SOUND_BPM-vakio kommentoidaan otsikkotiedostoon sound.h, niin nuottien kesto lasketaan ohjelman suorituksen aikana taulukossa määritellyn BPM:n mukaan. Jos SOUND_BPM ei kommentoida, nuottien kesto lasketaan käännösvaiheessa tämän vakion arvon perusteella ja kaikki melodiat soitetaan samassa tempossa. Tämä rajoittaa toimivuutta, mutta säästää muutaman tavun koodia.

Toistojen määrä. Voi ottaa arvot 1 ... 254 ja LOOP (255). LOOP - tarkoittaa, että melodia toistuu loputtomasti, kunnes SOUND_STOP tai SOUND_PAUSE komento annetaan.

Huomautuksen kesto– aika, jonka aikana tietty ääniääni luodaan tai tauko pidetään. Voidaan määrittää ms:na ms(x)-makroa käyttämällä tai vakionuottiarvoina - kahdeksannentoista nuotin, kuudestoista nuotin jne. Alla on luettelo tuetuista kestoista. Jos tarvitaan eksoottisia kestoja, voit aina lisätä ne tiedostoon tone.h

n1 - koko nuotti

n2 - puolisävel

n4 - neljännes

n8 - kahdeksas

n3 - kahdeksas tripletti

n16 - kuudestoista

n6 - sextole

n32 - kolmekymmentä sekuntia

Huomaa sävelkorkeus määritetään käyttämällä tone.h-tiedostossa kuvattuja symbolisia vakioita, esimerkiksi C2, A1 jne. Myös sävelkorkeus voidaan määrittää hertseinä käyttämällä f(x)-makroa.

Ohjelmalla on rajoituksia äänen minimi- ja enimmäistaajuudelle!

Melodian lopetusmerkki. Taulukon viimeisen elementin arvon on oltava nolla.

Äänimoduulin käyttö

Mainin alussa sinun on kutsuttava SOUND_Init()-funktio. Tämä toiminto asettaa mikro-ohjaimen lähtönastan, konfiguroi ajastimen T2 ja alustaa moduulimuuttujat.

Sitten sinun on asetettava keskeytyksen sallimislippu - __enable_interrupt(), koska moduuli käyttää T2-ajastimen ylivuotoa ja sattumakeskeytyksiä.

Tämän jälkeen voit alkaa soittaa melodioita.

Esimerkiksi näin:

ÄÄNI_SetSong(2);

ÄÄNI_Kom(ÄÄNI_TOISTO); //soita melodia

//asettaa osoittimen 2. melodiaan

//ja aloita toisto

ÄÄNI_PlaySong(2);

Melodian toisto voidaan lopettaa milloin tahansa antamalla SOUND_STOP-komento.
Voit myös keskeyttää melodian SOUND_PAUSE-komennolla. Myöhempi SOUND_PLAY-komennon antaminen jatkaa melodian toistoa kohdasta, jossa se pysäytettiin.

Periaatteessa tätä toiminnallisuutta ei juuri tarvita (keksin juuri) ja moduulin kanssa työskennellessä SOUND_PlaySong(unsigned char numSong) -toiminto riittää;

Tiedostot

Voit ladata esimerkkejä äänimoduulin käytöstä alla olevista linkeistä. En piirtänyt kaaviota, koska siellä kaikki on yksinkertaista. kytketty nastaan ​​PB0, melodioiden aloituspainike on kytketty nastaan ​​PD3. Projekteissa on määritelty 4 melodiaa. Painikkeen painaminen aloittaa uuden melodian joka kerta. Käytössä on atmega8535 mikro-ohjain. Aluksi halusin vaivautua projektiin, jossa oli neljä painiketta - PLAY, STOP, PAUSE ja NEXT, mutta sitten ajattelin, että se oli tarpeeton.

PS: Moduulia ei ole testattu laajasti ja se toimitetaan sellaisenaan. Jos on järkeviä ehdotuksia, viimeistellään ne.

Tässä artikkelissa tarkastellaan sävelten soittamista ja monofonisen melodian soittamista.

Valmistautuminen työhön

Ohjelma ilmoittaa kaksi taulukkoa. Joukko muistiinpanoilla muistiinpanoja sisältää yksinkertaisen luettelon muistiinpanoista. Nämä sävelet yhdistetään taulukon äänen kestoon lyö. Musiikin kesto määräytyy nuotin jakajalla suhteessa koko säveleen. Arvo kokonaisuutena otettuna on 255 . Puolikkaat, neljännekset ja kahdeksasosat saadaan jakamalla tämä luku.
Huomaa, että ensimmäisen nuotin kestoa ei saada jakamalla 255 kahdella. Täällä sinun on vaihdettava musiikin teoriaan. Alkuperäisen melodian sävelet ovat katsottavissa. Nämä nuotit on yhdistetty kolmoiksi. Tällä tavalla yhdistettynä kolme kahdeksassäveltä kuulostavat samalta kuin yksi kvartaali. Siksi niiden suhteellinen kesto on 21.
Käyttäjän on myös erikseen määritettävä nuottien määrä sekvenssissä direktiivin kanssa:

# määritä SEQU_SIZE 19

Pääohjelmassa lasketaan ensin taajuustaulukot uudelleen ja kesto signaalin jaksoiksi ja nuottien kestoiksi.
Signaalijaksoilla (matriisi signaali_jakso) kaikki on yksinkertaista. Saadaksesi jakson keston mikrosekunteina, jaa 1 000 000 signaalitaajuudella.
Nuottien äänen absoluuttisen keston laskemiseksi on välttämätöntä ilmoittaa musiikkiteoksen tempo. Tämä tehdään direktiivillä

# määrittele TEMPO 108

Musiikin tempo on neljännesnuottien määrä minuutissa. Linjassa

# määrittele WHOLE_NOTE_DUR 240000 / TEMPO

Koko nuotin kesto millisekunteina lasketaan. Nyt riittää, kun suhteelliset arvot lasketaan uudelleen taulukosta kaavan avulla lyö absoluuttiseen joukkoon note_duration.
Pääsilmukassa muuttuja kulunut aika kasvaa jokaisen toistetun signaalin jakson jälkeen tämän jakson keston verran, kunnes se ylittää nuotin keston. Kannattaa kiinnittää huomiota tähän merkintään:

while(kulunut_aika< 1000 * ((uint32_t) note_duration[ i] ) )

Muuttuva kulunut aika 32-bittinen ja taulukon elementit muistiinpanojen_kesto 16-bittinen. Jos 16-bittinen luku kerrotaan 1000:lla, ylivuoto taataan ja muuttuja kulunut aika verrataan roskiin. Muokkaus (uint32_t) muuntaa taulukon elementin muistiinpanot_kesto[i] 32-bittisessä numerossa ei ole ylivuotoa.
Voit nähdä toisen ominaisuuden äänisilmukassa. Toimintoa ei voi käyttää _delay_us(), koska sen argumentti ei voi olla muuttuja.
Käytä toimintoa luodaksesi tällaisia ​​viiveitä VarDelay_us(). Siinä silmukkaa, jonka viive on 1 μs, rullataan tietyn määrän kertoja.

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

Melodiaa toistettaessa käytetään vielä kahta viivettä. Jos nuotit toistetaan ilman taukoja, ne sulautuvat yhdeksi. Tätä varten niiden väliin lisätään 1 ms:n viive, jonka määrittelee direktiivi:

# määritä NOTES_PAUSE 1

Jokaisen melodian soittojakson jälkeen ohjelma pysähtyy 1 sekunnin ajaksi ja aloittaa toiston uudelleen.
Tuloksena saimme koodin, jossa on helppo muuttaa tempoa, säätää kestoa tai kirjoittaa melodia kokonaan uudelleen. Tätä varten riittää, että vain muunnetaan vain osa ohjelmasta direktiiveillä ja muuttujamäärityksillä.

Yksilölliset tehtävät

  1. Kokeile ehdotetun melodian tempoa ja pidä 5 sekunnin tauko toistojen välillä.
  2. Array elementit lyö hyväksy vain arvot välillä 0 - 255. Muuta taulukon elementtien bittileveyttä ja katso kääntäjän lähdöstä kuinka tämä vaikuttaa ohjelman varaamaan muistiin.
  3. Yritä nyt muuttaa melodiaa itse. Esimerkiksi tässä on "Imperial March" samasta elokuvasta: 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 lyöntiä = ( 50 , 20 , 50 , 20 , 50 , 20 , 40 , 5 , 20 , 5 , 60 , 10 , 40 , 5 , 20 , 5 , 60 , 80 , 0 , 5 , 50 , 50 20, 40, 5, 20

    Jos autoosi ei ole asennettu äänisireeniä, etkä silti voi päättää, kumman ostat ja asennat, tämä artikkeli on juuri sinua varten. Miksi ostaa kalliita hälytyksiä, jos voit koota ne kaikki itse melko yksinkertaisella tavalla?

    Esitän näistä kaksi yksinkertaiset piirit AVR ATmega8- ja Attiny2313-mikro-ohjaimissa, tai pikemminkin sama piiri on yksinkertaisesti toteutettu toimimaan näissä kahdessa mikro-ohjaimessa. Muuten, arkistosta löydät kaksi versiota laiteohjelmistosta Atmega8-mikro-ohjaimelle, joista ensimmäinen toistaa samanlaisen äänen kuin auton murtohälytin, ja toinen ääni on samanlainen kuin rakennuksen turvahälytys (nopea ja terävä signaali).

    Voit ladata kaikki alla olevat laiteohjelmistot arkistosta (kaikki on allekirjoitettu), arkistosta löydät myös Proteuksen piirien simulaation, mikä tarkoittaa, että kaikkien kappaleiden kuuntelun jälkeen voit valita luettelosta sen, mistä pidät eniten .

    Alla on Atmega8:n signalointikaavio

    Luettelo Atmega8-piirissä käytetyistä radiokomponenteista

    U1- AVR mikro-ohjain 8-bittinen ATmega8-16PU, kpl. 1,
    R1- Vastus, jonka nimellisarvo on 47 ohmia, no. 1,
    R2, R3 - Vastus, jonka nimellisarvo on 270 ohmia, no. 2,
    D2,D3-LED, no. 2,
    LS1-kaiutin, no. 1,
    S1-anturi.

    Ja Attiny2313:n signalointipiirissä vain MK on muutettu.
    U1- Mikro-ohjain AVR 8-bittinen ATtiny2313-20PU, no. 1.

    Painettu piirilevy Atmega8 näyttää tältä:

    Kuten näette, piiri on hyvin yksinkertainen, siinä on vain yksi mikro-ohjain, 3 vastusta, 2 LEDiä ja yksi kaiutin. Painikkeen sijasta voit käyttää reed-kytkintä tai muuta kosketinta.

    Toimintaperiaate on seuraava. Heti kun kytkemme virran päälle, LED (piirissä D3) syttyy välittömästi tai alkaa vilkkua (laiteohjelmistosta riippuen), ja jos emme kosketa anturia, hälytys on hiljainen. Nyt, jos anturi laukeaa, myös sireeni toimii, LED myös vilkkuu, mutta D2.

    Jos haluat, että auton ajovalot vilkkuvat hälyttimen toimiessa, sinun on kytkettävä mikro-ohjaimen 24 PC1 nasta releeseen transistorin kautta ja itse rele ajovaloihin. Sireenin sammuttamiseksi sinun on sammutettava laite ja kytkettävä se uudelleen päälle tai yksinkertaisesti paina painiketta. Mikro-ohjaimen käyttöä varten tarvitset sisäisen 8 MHz oskillaattorin,

    Jos haluat jotenkin parantaa hälytyksen ääntä, voit koota vahvistimen transistoreilla ja kytkeä sen piiriin. Juuri näin tein, mutta en esittänyt sitä tässä kaaviossa.

    Jatketaan Attiny 2313:n piiriin, kuten aiemmin sanoin, siinä on kaikki samat yksityiskohdat ja sama toimintaperiaate, vain MK on muutettu ja sen seurauksena liitetyt nastat. Tämä mikro-ohjain toimii sisäinen 4 MHz oskillaattori, vaikka se voidaan vilkkua 1 MHz:llä.

    Alla on jo Attiny2313:n kytkentäkaavio

    Tälle MK:lle kirjoitin vain yhden laiteohjelmistoversion, kokosin kaiken piirilevylle, tarkistin sen, kaikki toimii hyvin.
    Ja sulakkeet on asetettava alla olevan kuvan mukaisesti:





Yläosa