تبلیغات
پایگاه مجازی برق الکترونیک - تولید و پخش ملودی با AVR
1389/12/20  12:31    ویرایش: 1390/03/29 15:11
 
نوع مطلب: پروژه ،میکروکنترلر ،
 


برای تولید نت موسیقی با هر میکروکنترلری باید بر نکته اساسی زیر واقف بود:

نسبت فرکانس هر دو نت متوالی در دستگاه موسیقی بین المللی(فاصله نیم پرده) برابر است با عدد 1.059463

بنابراین اگر یک نت را به عنوان نقطه مبنا در نظر بگیریم، فرکانس نت بعدی 1.059463 برابر نت فعلی و فرکانس نت قبلی هم همین فرکانس تقسیم بر 1.059463 خواهد بود.با توجه به تدوین قراردادی مبنی بر قرار دادن یکی از نت های Do برابر با 440 هرتز، می توانیم همین عدد 440 هرتز را به عنوان مبنا در نظر بگیریم و فرکانس نت های بعدی و قبلی را با ضرب یا تقسیم متوالی بر عدد مذکور بدست آوریم.
در دستگاه موسیقی بین المللی که روی سازهایی مانند پیانو پیاده می شود، 12 نت با نام های مستقل وجود دارد که اگر هر نتی را در نظر بگیریم بعد از طی 12 نت به نت هم نام آن می رسیم و فرکانس نت هم نام بعدی دقیقا 2 برابر نت فعلی است (یک اکتاو). بنابراین برای برنامه نویسی هر میکرو کنترلری کافی است تنها 12 مقدار مستقل را برای کل نت ها بصورت یک Lookup Table در حافظه flash قرار دهیم و بقیه نت ها از روی همین 12 مقدار قابل ساخته شدن هستند. مقادیری که در این Table ذخیره می شوند، مقدار لازم برای قرار دادن در تایمری است که سبب تولید فرکانس مورد نظر در خروجی شود.

برای تولید هر نت دو مقدار فرکانس و طول مدت نواخته شدن نت باید در برنامه تعیین شود. به این منظور دو عملیات زمان گیری جداگانه باید برنامه ریزی شود. یکی تایمری که پورت خروجی را در یک فاصله زمانی مشخص toggle می کند و تایمر دومی که بعد از سپری شدن زمان مورد نظر برای نت، به عملیات تایمر اول خاتمه می دهد. مثلا اگر قرار باشد نت Do با فرکانس 440 هرتز به مدت یک ثانیه نواخته شود، با توجه به اینکه پریود این موج تقریبا 2.273 میلی ثانیه می شود و موج مورد نظر یک بخش low و یک بخش high دارد، بنابراین باید یک تایمر در وضعیتی قرار داده شود که با سپری شدن نصف این زمان 2.273 میلی ثانیه که 1.1365 میلی ثانیه می شود، خروجی مورد نظر را toggle کند. همزمان باید تایمر دیگری با مدت زمان 1 ثانیه بکار بیافتد و بعد از سپری شدن مدت زمان تایمر دوم، toggle شدن خروجی تولید کننده صدا متوقف شود. پس برای ایجاد یک موسیقی کامل کافی است نت های متوالی تولید کننده آن موسیقی به همراه طول مدت نواخته شدن هر نت را در یک یا دو lookup table قرار دهیم و با سپری شدن زمان هر نت، تایمرهای دوگانه مذکور را مجددا مقداردهی کنیم و منتظر بمانیم تا زمان نت جاری سپری شود.

برای نشان دادن روش پیاده سازی عملی این تئوری، ملودی موسیقی سرود " ای ایران " ساخته مرحوم روح الله خالقی، در برنامه ای پیاده سازی شده است. این برنامه با فرض فعال بودن اسیلاتور 1 مگاهرتز داخلی، در خروجی PB0 شکل موج لازم را تولید می کند و برای شنیدن آن کافی است یک بلندگو از طریق یک ترانزیستور به پورت متصل شود. به این منظور خروجی PB0 را بدون مقاومت به بیس یک ترانزیستور PNP وامیتر آن به بلندگو متصل می شود و سر دیگر بلندگو هم به ولتاژ مناسب(مثلا 5 ولت) وصل می شود.کلکتور ترانزیستور PNP هم باید به زمین متصل شود. (این مطلب قبلا در وبسایت ECA منتشر شده است).



$regfile = "M32def.dat"
$crystal = 1000000

Const Sil = 0
Const Sol1 = 1
Const Sol1_ = 2
Const La1 = 3
Const La1_ = 4
Const Si1 = 5
Const Do2 = 6
Const Do2_ = 7
Const Re2 = 8
Const Re2_ = 9
Const Mi2 = 10
Const Fa2 = 11
Const Fa2_ = 12
Const Sol2 = 13
Const Sol2_ = 14
Const La2 = 15
Const La2_ = 16
Const Si2 = 17
Const Do3 = 18
Const Do3_ = 19
Const Re3 = 20
Const Re3_ = 21
Const D1 = 1
Const D2 = 2
Const D3 = 3
Const D4 = 4
Const D6 = 6
Const D7 = 7
Const D8 = 8
Const D16 = 16
Const D32 = 32
Const End_of_table = 255

Dim Note_f As Bit
Dim Duration As Byte
Dim I As Word
Dim J As Byte
Dim Table_value As Byte
Dim Ocr1a_temp As Word
Speaker Alias Portb.0

Note_f = 0
I = 0

Config Pinb.0 = Output
Config Timer0 = Timer , Prescale = 1024 , Clear Timer = 1
Config Timer1 = Timer , Prescale = 1 , Clear Timer = 1
Ocr0 = &H40
On Oc0 Timer0_compare_isr
On Oc1a Timer1_comparea_isr
Enable Oc0
Enable Oc1a
Enable Interrupts

Loop1:

Table_value = Lookup(i , Note_table)
If Table_value = End_of_table Then
I = 0
Goto Loop1
End If
If Table_value = Sil Then Goto Silent_play
I = I + 1
Disable Interrupts
Note_f = 1
Duration = Lookup(i , Note_table)
I = I - 1
J = Lookup(i , Note_table)
J = J - 1
Timer1 = 0
Ocr1a_temp = Lookup(j , Ocr1a_value_table)
Ocr1a = Ocr1a_temp
Enable Interrupts
Do
Loop Until Duration = 0
I = I + 2
Goto Loop1

Silent_play:
Note_f = 0
I = I + 1
Duration = Lookup(i , Note_table)
Do
Loop Until Duration = 0
I = I + 1
Goto Loop1

Timer0_compare_isr:
If Duration > 0 Then Duration = Duration - 1
Return

Timer1_comparea_isr:
If Note_f = 1 Then Toggle Speaker
Return

Note_table:

Data Re2 , D4 , La2 , D1 , Sil , D1 , La2 , D1 , Sil , D1 , La2 , D4 , Re2 , D3
Data Sil , D1 , Re2 , D4 , La2 , D1 , Sil , D1 , La2 , D1 , Sil , D1 , La2 , D4
Data Re2 , D4 , La2 , D4 , La2_ , D2 , Do3 , D2 , La2 , D8 , Re3 , D2 , Do3 , D1
Data Sil , D1 , Do3 , D1 , Sil , D1 , La2_ , D1 , Sil , D1 , La2_ , D1 , Sil , D1
Data La2 , D1 , Sil , D1 , La2 , D1 , Sil , D1 , Sol2 , D2 , Fa2 , D4 , Sol2 , D2
Data Do3 , D2 , La2 , D8 , Re2 , D2 , Do2 , D2 , Re2 , D2 , Re2_ , D2 , Fa2 , D2
Data Re2_ , D2 , Fa2 , D2 , Sol2 , D2 , La2 , D2 , Do3 , D2 , La2_ , D2 , La2 , D2
Data Sol2 , D2 , Fa2 , D2 , Re2_ , D2 , Re2 , D2 , Do2 , D4 , Sol2 , D1 , Sil , D1
Data Sol2 , D1 , Sil , D1 , Sol2 , D4 , La2 , D4 , La2_ , D4 , La2 , D2 , Sol2 , D2
Data Fa2 , D4 , Sol2 , D4 , La2 , D4 , Sol2 , D2 , Fa2 , D2 , Re2_ , D4 , Fa2 , D4
Data Sol2 , D4 , Fa2 , D2 , Re2_ , D2 , Re2 , D8 , La2_ , D2 , La2 , D1 , Sil , D1
Data La2 , D1 , , Sil , D1 , Sol2 , D1 , Sil , D1 , Sol2 , D1 , Sil , D1 , Fa2 , D1
Data Sil , D1 , Fa2 , D1 , Sil , D1 , Re2_ , D2 , La2 , D2 , Sol2 , D1 , Sil , D1
Data Sol2 , D1 , Sil , D1 , Fa2 , D1 , Sil , D1 , Fa2 , D1 , Sil , D1 , Re2_ , D1
Data Sil , D1 , Re2_ , D1 , Sil , D1 , Re2 , D2 , Fa2 , D2 , Sil , D2 , Fa2 , D2
Data Sol2 , D2 , La2 , D8 , Re2 , D4 , La2 , D1 , Sil , D1 , La2 , D1 , Sil , D1
Data La2 , D4 , Re2 , D3 , Sil , D1 , Re2 , D4 , La2 , D1 , Sil , D1 , La2 , D1
Data Sil , D1 , La2 , D4 , Re2 , D4 , La2 , D4 , La2_ , D2 , Do3 , D2 , La2 , D8
Data Re3 , D2 , Do3 , D1 , Sil , D1 , Do3 , D1 , Sil , D1 , La2_ , D1 , Sil , D1
Data La2_ , D1 , Sil , D1 , La2 , D1 , Sil , D1 , La2 , D1 , Sil , D1 , Sol2 , D2
Data Fa2 , D4 , Sol2 , D2 , Do3 , D2 , La2 , D8 , Re2 , D2 , Do2 , D2 , Re2 , D2
Data Re2_ , D2 , Fa2 , D2 , Re2_ , D2 , Fa2 , D2 , Sol2 , D2 , La2 , D2 , Do3 , D2
Data La2_ , D2 , La2 , D2 , Sol2 , D2 , Fa2 , D2 , Re2_ , D2 , Re2 , D2 , Do2 , D4
Data Sol2 , D1 , Sil , D1 , Sol2 , D1 , Sil , D1 , Sol2 , D4 , La2 , D4 , La2_ , D4
Data La2 , D2 , Sol2 , D2 , Fa2 , D4 , Sol2 , D4 , La2 , D4 , Sol2 , D2 , Fa2 , D2
Data Re2_ , D4 , Fa2 , D4 , Sol2 , D4 , Fa2 , D2 , Re2_ , D2 , Re2 , D8 , La2_ , D2
Data La2 , D1 , Sil , D1 , La2 , D1 , Sil , D1 , Sol2 , D1 , Sil , D1 , Sol2 , D1
Data Sil , D1 , Fa2 , D1 , Sil , D1 , Fa2 , D1 , Sil , D1 , Re2_ , D2 , La2 , D2
Data Sol2 , D1 , Sil , D1 , Sol2 , D1 , Sil , D1 , Fa2 , D1 , Sil , D1 , Fa2 , D1
Data Sil , D1 , Re2_ , D1 , Sil , D1 , Re2_ , D1 , Sil , D1 , Re2 , D2 , Re2 , D4
Data Re2_ , D2 , Fa2 , D2 , Re2 , D6 , Sil , D2 , Re2 , D8 , La2 , D8 , Re2 , D8
Data La2 , D7 , Sil , D1 , La2 , D6 , La2_ , D2 , Do3 , D6 , La2_ , D2 , La2 , D8
Data Sil , D8 , Re3 , D8 , Do3 , D8 , La2_ , D8 , La2 , D8 , Sol2 , D6 , Fa2 , D2
Data Sol2 , D6 , Do3 , D2 , La2 , D8 , Sil , D8 , Re2 , D8 , La2_ , D8 , La2 , D8
Data Sol2 , D8 , Fa2 , D6 , Re2_ , D2 , Re2 , D6 , Re2_ , D2 , Do2 , D8 , Sil , D8
Data Fa2 , D8 , Re2_ , D8 , Re2 , D6 , Sol2 , D2 , Fa2 , D8 , Re2_ , D6 , Re2 , D2
Data Do2 , D6 , Re2_ , D2 , Re2 , D4 , La1 , D4 , La1_ , D4 , Do2 , D4 , Re2 , D4
Data Sol1 , D4 , Do2 , D4 , Sol1 , D4 , La1_ , D4 , Re2 , D4 , La1 , D4 , Re2 , D4
Data Sol1 , D4 , Re2 , D4 , La1 , D4 , Re2 , D4 , La1_ , D4 , Re2 , D4 , Do2 , D4
Data Re2 , D4 , Re3 , D32 , Do3 , D6 , Re3_ , D2 , Re3 , D6 , Do3 , D2 , La2_ , D6
Data Re3 , D2 , Do3 , D6 , La2_ , D2 , La2 , D6 , Do3 , D2 , La2_ , D6 , La2 , D2
Data Sol2 , D8 , Sil , D8 , Sol1 , D6 , La1 , D2 , La1_ , D6 , Do2 , D2 , Re2 , D6
Data Re2_ , D2 , Do2 , D6 , Re2 , D2 , Re2_ , D6 , Do2 , D2 , Re2 , D6 , Re2_ , D2
Data Re2 , D8 , Sil , D8 , Do3 , D8 , Si2 , D6 , Re3 , D2 , Do3 , D16 , La2_ , D6
Data La2 , D2 , Sol2 , D6 , La2_ , D2 , La2 , D16 , Do3 , D8 , Si2 , D6 , Re3 , D2
Data Do3 , D16 , La2_ , D6 , La2 , D2 , Sol2 , D6 , La2_ , D2 , La2 , D16 , Fa2 , D6
Data Re2_ , D2 , Fa2 , D6 , Sol2 , D2 , La2 , D16 , La2_ , D6 , La2 , D2 , Sol2 , D6
Data Fa2 , D2 , La2 , D6 , Sol2 , D2 , Fa2 , D6 , Re2_ , D2 , Sol2 , D6 , Fa2 , D2
Data Re2_ , D6 , Fa2 , D2 , Sol2 , D16 , La2 , D6 , Sol2 , D2 , Fa2 , D6 , Re2_ , D2
Data Sol2 , D6 , Fa2 , D2 , Re2_ , D6 , Re2 , D2 , Fa2 , D6 , Re2_ , D2 , Sol2 , D6
Data Re2_ , D2 , Re2 , D8 , Sil , D8
Data End_of_table

Ocr1a_value_table:

Data 1516% , 1431% , 1350% , 1275% , 1203% , 1135% , 1072% , 1011% , 955% , 901%
Data 850% , 803% , 757% , 715% , 675% , 637% , 601% , 567% , 535% , 505% , 477%

   


نظرات()  
mushdulugh
1390/10/19 23:15
yashasin
ARASH
1390/08/13 22:28
THX
اسماعیل دادخواه
1390/06/31 04:52
مطالب بسیار جالب بود
ممنونم
 
لبخندناراحتچشمک
نیشخندبغلسوال
قلبخجالتزبان
ماچتعجبعصبانی
عینکشیطانگریه
خندهقهقههخداحافظ
سبزقهرهورا
دستگلتفکر

پایگاه مجازی برق الکترونیک