مجید بهره مند 43111 اشتراک گذاری ارسال شده در 5 آبان، ۱۳۹۳ [TABLE] [TR] [TD] برای تولید نت موسیقی با هر میکروکنترلری باید بر نکته اساسی زیر واقف بود: نسبت فرکانس هر دو نت متوالی در دستگاه موسیقی بین المللی(فاصله نیم پرده) برابر است با عدد 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% [/TD] [TD=width: 7%] [/TD] [/TR] [/TABLE] 3 لینک به دیدگاه
ارسال های توصیه شده