計(jì)FPGA電子琴:從按鍵消抖到音符分頻)
簡介一套基于Quartus原理圖設(shè)計(jì)方法的電子琴FPGA工程文件包面向數(shù)字邏輯與FPGA入門及進(jìn)階學(xué)習(xí)者完整呈現(xiàn)從原理圖規(guī)劃、模塊例化到編譯仿真、下載調(diào)試的完整設(shè)計(jì)流程。設(shè)計(jì)圍繞音符頻率生成、定時(shí)計(jì)數(shù)、數(shù)模轉(zhuǎn)換、播放控制與樂曲存儲(chǔ)等核心環(huán)節(jié)展開通過查找表存放頻率值并利用計(jì)數(shù)器產(chǎn)生精確時(shí)長整體構(gòu)架清晰便于逐級拆解。壓縮包內(nèi)共413個(gè)文件主要包含原理圖文件、符號(hào)文件、仿真波形文件以及工程設(shè)置、編譯報(bào)告、樂曲初始化數(shù)據(jù)和少量文本描述代碼壓縮后僅5.42兆字節(jié)方便快速下載和導(dǎo)入Quartus環(huán)境學(xué)習(xí)。資源已有1045人學(xué)習(xí)使用適合課程設(shè)計(jì)、競賽準(zhǔn)備或業(yè)余電子琴制作項(xiàng)目參考。通過研讀可學(xué)習(xí)如何將音樂理論中的音名編碼轉(zhuǎn)換為硬件可處理的頻率參數(shù)理解計(jì)數(shù)器分頻與節(jié)拍控制機(jī)制并借助現(xiàn)成工程模板修改樂譜和音色避開常見編譯時(shí)序陷阱顯著提高設(shè)計(jì)效率與成功率。1. 原理圖電子琴不是玩具它把時(shí)序電路變成了聽得見的反饋用 Quartus 原理圖畫一臺(tái)電子琴聽起來像教科書里的教學(xué)實(shí)驗(yàn)但實(shí)際做出來的東西可以直接在 FPGA 開發(fā)板上彈奏甚至能跑出一段完整旋律。這個(gè)項(xiàng)目最特別的地方在于從按鍵消抖到音符分頻所有關(guān)鍵邏輯都以原理圖符號(hào)的形式呈現(xiàn)沒有一行 HDL 代碼它把一個(gè)時(shí)序電路的真實(shí)運(yùn)行狀態(tài)直接轉(zhuǎn)化為聲音反饋——跑對了耳朵能聽見跑錯(cuò)了同樣聽得出來。適合正在學(xué) FPGA 基礎(chǔ)、想驗(yàn)證計(jì)數(shù)器與觸發(fā)器行為的初學(xué)者也適合需要一份能快速改造成課程設(shè)計(jì)原型的開發(fā)者。下文從一個(gè)可運(yùn)行的工程角度把模塊劃分、分頻系數(shù)、連線方式和改造路徑逐一講透盡量讓你看完就能照著搭。2. 工程拆解Quartus 原理圖輸入與電子琴發(fā)聲鏈路2.1 原理圖工程的文件構(gòu)成與設(shè)計(jì)流程用原理圖方式做項(xiàng)目最容易翻車的地方是把所有邏輯都堆在一張 BDF 圖里最后復(fù)雜到連自己都看不清連線。我拿到一套電子琴工程時(shí)第一反應(yīng)是先看文件組織。一個(gè)規(guī)范的 Quartus 原理圖工程通常由三類文件組成.bdf 塊設(shè)計(jì)文件作為頂層圖紙.bsf 符號(hào)文件作為可復(fù)用的模塊封裝.v 或 .vhd 文件承載底層邏輯。一個(gè) 8 音符電子琴工程的典型目錄結(jié)構(gòu)長這樣project/ ├── top.bdf -- 頂層原理圖模塊之間的連線都在這里完成 ├── keyboard_ctrl.bsf -- 按鍵掃描與消抖模塊的符號(hào)文件 ├── tone_divider.bsf -- 音符分頻模塊的符號(hào)文件 ├── freq_table.mif -- 音符分頻系數(shù)存儲(chǔ)表供 ROM 讀取 ├── pin_assignments.qsf -- 引腳分配文件避免每次重新分配引腳 └── sim/ └── ekey_tb.v -- 可選仿真激勵(lì)驗(yàn)證分頻輸出波形不要小看這個(gè)結(jié)構(gòu)。頂層 BDF 只做連線不寫邏輯分頻器、掃描器都封裝成獨(dú)立符號(hào)。這樣做的直接收益是改一個(gè)模塊的參數(shù)不需要?jiǎng)禹攲訄D紙Quartus 在重新生成網(wǎng)表時(shí)會(huì)自動(dòng)同步排查問題時(shí)也能按圖索驥單獨(dú)仿真某一個(gè)模塊。實(shí)際操作順序我一般這樣排先新建工程指定頂層實(shí)體名然后新建 Block Diagram/Schematic File在 Symbol 庫中搜索需要的計(jì)數(shù)器、觸發(fā)器或自己生成的模塊符號(hào)放置到圖紙中接下來用連線工具把符號(hào)引腳連起來再用引腳屬性指定輸入輸出最后編譯一次打開 Pin Planner 分配引腳下載到板子。每完成一步就編譯一次不要等到全部畫完再一次性編譯否則幾十個(gè)錯(cuò)誤堆在一起神仙也難定位。2.2 音符頻率與分頻系數(shù)先算清楚再連線電子琴發(fā)聲的本質(zhì)是產(chǎn)生不同頻率的方波。以常見的 50MHz 開發(fā)板主時(shí)鐘為例要得到 262Hz 的中央 C需要把時(shí)鐘頻率分頻到 262Hz。不同音符對應(yīng)的方波頻率不同原理圖設(shè)計(jì)里最常見的方式是做一個(gè)計(jì)數(shù)器計(jì)數(shù)到預(yù)定值后翻轉(zhuǎn)一次輸出電平這樣輸出方波的周期就是時(shí)鐘周期的兩倍。因此分頻系數(shù) K 與目標(biāo)頻率 f 的關(guān)系是K 50_000_000 / (2 × f)計(jì)數(shù)到 K-1 時(shí)觸發(fā)翻轉(zhuǎn)。以 C 大調(diào)一個(gè)八度為例分頻系數(shù)可以這樣算音符頻率約值 (Hz)分頻系數(shù) K推薦計(jì)數(shù)位寬C4261.639555617D4293.668513817E4329.637584617F4349.237158817G4392.006377617A4440.005681817B4493.885061917C5523.254777816 亦可建議統(tǒng)一 17 位注意分頻系數(shù) K 是一個(gè)整數(shù)而 50MHz 除以兩倍頻率往往帶小數(shù)。我建議所有音符統(tǒng)一向下取整不要有的四舍五入、有的直接截?cái)喾駝t高音區(qū)會(huì)明顯偏低。另外計(jì)數(shù)器的計(jì)數(shù)范圍從 0 開始所以實(shí)際邏輯里是計(jì)數(shù)到 K-1 時(shí)清零或翻轉(zhuǎn)如果你誤寫成計(jì)數(shù)到 K 再清零實(shí)際分頻周期就變成了 K1每個(gè)音符都偏低一點(diǎn)。這類問題在仿真波形里很難一眼看出但一上板人耳馬上就發(fā)現(xiàn)。2.3 發(fā)聲鏈路與模塊邊界整臺(tái)電子琴的信號(hào)路徑可以切成四段每一段對應(yīng)原理圖上的一個(gè)區(qū)域按鍵輸入8 個(gè)按鍵引腳對應(yīng) C 大調(diào)八度音消抖與編碼按鍵信號(hào)先做防抖處理再編碼成 3 位音符索引分頻查表根據(jù)音符索引從分頻系數(shù)表中拿到對應(yīng) K 值驅(qū)動(dòng)音調(diào)分頻器音頻輸出分頻器輸出方波經(jīng)引腳送到無源蜂鳴器。這里有一個(gè)非常容易被忽略的硬件細(xì)節(jié)蜂鳴器分有源和無源兩類。有源蜂鳴器通電自帶固定頻率給它一個(gè)高電平就會(huì)響無源蜂鳴器需要外部提供振蕩方波才能發(fā)聲。這個(gè)電子琴項(xiàng)目的輸出必須接無源蜂鳴器或小喇叭否則你辛辛苦苦生成一個(gè) 262Hz 的翻轉(zhuǎn)電平它響的卻是自己內(nèi)部固定的那個(gè)音完全不聽你的分頻器。連線之前先查板子原理圖確認(rèn)揚(yáng)聲器類型能省掉后面一整晚的調(diào)試時(shí)間。這段鏈路也決定了調(diào)試策略如果按鍵模塊輸出的索引正確、分頻模塊輸出的方波頻率正確聲音就必然正確。所以排查時(shí)可以分段驗(yàn)證——先看按鍵編碼再看分頻輸出波形最后才懷疑硬件連線。3. 核心模塊拆解一個(gè)音符從按鍵到揚(yáng)聲器的完整路徑3.1 按鍵掃描與消抖模塊的原理圖實(shí)現(xiàn)按鍵模塊要解決兩件事消抖和編碼。機(jī)械按鍵按下時(shí)會(huì)有約 5 到 20 毫秒的抖動(dòng)如果不處理一次按下去可能觸發(fā)兩三次音符切換。常見做法是引入一個(gè)約 10 毫秒的計(jì)數(shù)窗口檢測到電平變化后開始計(jì)時(shí)計(jì)時(shí)結(jié)束電平仍然穩(wěn)定才認(rèn)為按鍵有效。在原理圖里我一般這樣設(shè)計(jì)模塊內(nèi)部結(jié)構(gòu) 1. 50MHz 時(shí)鐘經(jīng) 20 級計(jì)數(shù)器分頻得到約 1kHz 采樣時(shí)鐘 2. 每次采樣時(shí)鐘上升沿將按鍵電平移入 4 位移位寄存器 3. 僅當(dāng) 4 位寄存器全為 0 或全為 1 時(shí)判定為有效電平 4. 有效電平送入 3 位優(yōu)先編碼器生成音符索引原理圖里體現(xiàn)為一個(gè)分頻計(jì)數(shù)器生成采樣脈沖兩個(gè)串行移位寄存器做延時(shí)濾波再加一個(gè)優(yōu)先編碼器輸出索引。Quartus 的符號(hào)庫里能找到 7493 這類現(xiàn)成計(jì)數(shù)器也可以直接用 LPM_COUNTER 宏功能模塊不需要自己搭門電路。消抖時(shí)間參數(shù)可以這樣調(diào)采樣時(shí)鐘頻率取 1kHz每個(gè)電平需要連續(xù) 4 次采樣確認(rèn)對應(yīng)約 4ms 的確認(rèn)窗口。如果你覺得 4ms 對比較硬的按鍵還是偏短把采樣頻率降到 500Hz確認(rèn)時(shí)間就變成約 8ms。原理圖里只需要改分頻計(jì)數(shù)器的模值不影響其他區(qū)域。3.2 音符分頻模塊查表驅(qū)動(dòng)計(jì)數(shù)器分頻模塊是發(fā)聲的關(guān)鍵。它接收按鍵編碼器輸出的 3 位索引通過查表取得對應(yīng)的分頻系數(shù)然后用這個(gè)系數(shù)控制計(jì)數(shù)器的翻轉(zhuǎn)時(shí)刻。這里有兩種常見做法一種是用多路選擇器在 8 個(gè)預(yù)置分頻系數(shù)里選一個(gè)另一種是用只讀存儲(chǔ)器 ROM 存放一張 8 深度的分頻系數(shù)表按地址讀取。我更推薦第二種因?yàn)楫?dāng)你要擴(kuò)展成 12 個(gè)半音甚至 16 個(gè)音符時(shí)只需要改 mif 文件內(nèi)容原理圖一根連線都不用動(dòng)。一個(gè) 8 音符版本的 mif 文件長這樣-- freq_table.mif 片段8 音符版本 DEPTH 8; WIDTH 17; ADDRESS_RADIX DEC; DATA_RADIX DEC; CONTENT BEGIN 0 : 95556; -- C4 261.63Hz 1 : 85138; -- D4 293.66Hz 2 : 75846; -- E4 329.63Hz 3 : 71588; -- F4 349.23Hz 4 : 63776; -- G4 392.00Hz 5 : 56818; -- A4 440.00Hz 6 : 50619; -- B4 493.88Hz 7 : 47778; -- C5 523.25Hz END;mif 文件寫好之后在原理圖里放一個(gè) altsyncram 或 LPM_ROM 宏功能模塊數(shù)據(jù)文件指向這個(gè) mifROM 地址來自按鍵編碼器輸出數(shù)據(jù)輸出直接接到計(jì)數(shù)器預(yù)置值輸入端。整個(gè)過程不需要寫任何 HDL 代碼這是原理圖設(shè)計(jì)最舒服的地方。ROM 輸出的分頻系數(shù)需要配合一個(gè)加載信號(hào)配合使用按鍵變化時(shí)產(chǎn)生一個(gè) load 脈沖把新系數(shù)寫入計(jì)數(shù)器預(yù)置端沒有按鍵變化時(shí)計(jì)數(shù)器保持現(xiàn)有分頻系數(shù)繼續(xù)運(yùn)行音符不會(huì)斷。對應(yīng)到原理圖就是一個(gè)計(jì)數(shù)器模塊模值輸入端接 ROM 數(shù)據(jù)輸出加載端接按鍵變化脈沖。為了幫你理解這個(gè)模塊在原理圖里的行為我用一句 Verilog 描述它的參考邏輯實(shí)際工程中你不需要寫這行代碼只需要在原理圖里把 LPM_COUNTER 的模值輸入連好// 分頻計(jì)數(shù)器參考模型原理圖中用宏功能模塊實(shí)例化 module tone_div #(parameter WIDTH 17)( input clk, // 50MHz 系統(tǒng)時(shí)鐘 input [WIDTH-1:0] div,// 來自 ROM 的分頻系數(shù) input load, // 按鍵變化時(shí)產(chǎn)生一個(gè)加載脈沖 output reg tone_out // 輸出方波接無源蜂鳴器 ); reg [WIDTH-1:0] cnt; always (posedge clk) begin if (load) begin cnt 0; tone_out 1b1; end else if (cnt div - 1) begin cnt 0; tone_out ~tone_out; end else begin cnt cnt 1; end end endmodule邏輯說明load 為高時(shí)計(jì)數(shù)器清零并輸出高電平之后每個(gè)時(shí)鐘周期 cnt 加 1計(jì)數(shù)到 div-1 時(shí)輸出翻轉(zhuǎn)。輸出方波周期等于 2 × div × 時(shí)鐘周期因此 div 就是前面算的分頻系數(shù) K。WIDTH 參數(shù)由最大分頻系數(shù)決定中央 C 的 95556 需要 17 位二進(jìn)制表示所以統(tǒng)一取 17 位后續(xù)擴(kuò)展到更低音區(qū)也能放下。3.3 頂層原理圖連線方式頂層 BDF 是把各模塊串起來的地方。一張 8 音符頂層圖的關(guān)鍵連線可以整理成下面的清單實(shí)際畫圖時(shí)在圖紙上對應(yīng)拖放即可源信號(hào)連接目標(biāo)說明8 個(gè)按鍵輸入引腳keyboard_ctrl 模塊輸入按鍵默認(rèn)低電平有效keyboard_ctrl 輸出 note_index[2:0]ROM 地址端選擇音符分頻系數(shù)keyboard_ctrl 輸出 key_pressedtone_div 加載端 load按下或釋放時(shí)觸發(fā)重新加載50MHz 時(shí)鐘引腳keyboard_ctrl 與 tone_div 時(shí)鐘端所有模塊共用同一個(gè)時(shí)鐘源ROM 數(shù)據(jù)輸出 div_coef[16:0]tone_div 分頻系數(shù)輸入位寬必須匹配tone_div 輸出 tone_out輸出引腳 spk_out接無源蜂鳴器或小喇叭連線時(shí)注意幾點(diǎn)所有模塊的時(shí)鐘必須來自同一個(gè)全局時(shí)鐘引腳不要在原理圖中間用門電路產(chǎn)生派生時(shí)鐘否則 Quartus 在做時(shí)序分析時(shí)會(huì)給你報(bào)一堆時(shí)鐘偏斜的問題ROM 地址和數(shù)據(jù)位寬要跟計(jì)數(shù)器預(yù)置值匹配不一致時(shí)編譯會(huì)提示長度不匹配輸出引腳建議加一個(gè)輸出緩沖或直接連普通 IO避免下載后出現(xiàn)多個(gè)驅(qū)動(dòng)源互相拉扯電平。編譯順序建議這樣先單獨(dú)編譯 keyboard_ctrl 模塊用仿真確認(rèn)消抖和編碼正確再單獨(dú)編譯 tone_div 模塊給定一個(gè)固定分頻系數(shù)看輸出頻率對不對最后拼裝頂層統(tǒng)一編譯。每個(gè)模塊先獨(dú)立驗(yàn)證再做系統(tǒng)集成能減少至少一半的排查時(shí)間。4. 常見問題與避坑仿真、下載與硬件調(diào)試實(shí)錄4.1 現(xiàn)象仿真波形正常上板完全無聲這是我自己踩過最狠的一個(gè)坑。分頻器仿真波形每個(gè)翻轉(zhuǎn)點(diǎn)都對下載到板子后卻一點(diǎn)聲音沒有。排查到最后才發(fā)現(xiàn)板子上那個(gè)蜂鳴器是有源的它只需要直流電平就能響并不需要外部方波。工程輸出引腳接錯(cuò)到了有源蜂鳴器的控制端方波的快速高低變化在里面被當(dāng)成開關(guān)信號(hào)處理效果就是極其微弱甚至聽不到聲音。解決辦法是查板子原理圖確認(rèn)揚(yáng)聲器類型。無源蜂鳴器才適合接收分頻方波。如果板子上同時(shí)有兩種蜂鳴器檢查是否有跳線切換把輸出引腳切到無源那一路。另外還有一個(gè)容易被忽略的原因輸出方波頻率如果落在 200Hz 以下或 20kHz 以上人耳敏感度很低聽起來就像沒聲音。用示波器或邏輯分析儀測一下 spk_out 引腳的波形頻率很快能確認(rèn)。4.2 現(xiàn)象按鍵響應(yīng)時(shí)快時(shí)慢甚至一鍵觸發(fā)多個(gè)音符這是消抖窗口設(shè)置太短的典型表現(xiàn)。機(jī)械按鍵抖動(dòng)一般持續(xù) 5 到 20 毫秒如果采樣確認(rèn)窗口只有 2 毫秒抖動(dòng)期間的雜散電平會(huì)被當(dāng)成有效信號(hào)編碼器在一個(gè)按鍵事件里輸出了多個(gè)不同的音符索引聽感上就是一個(gè)鍵按下去聲音亂跳。解決方法是在消抖模塊里把采樣時(shí)鐘降到 1kHz 以下讓確認(rèn)窗口覆蓋整個(gè)抖動(dòng)區(qū)間。原理圖上的改動(dòng)通常是把分頻計(jì)數(shù)器的模值調(diào)大把采樣頻率從 2kHz 降到 1kHz確認(rèn)窗口從 2ms 變成 4ms。如果按鍵質(zhì)量比較差可以繼續(xù)降到 500Hz。不要用遮蔽法處理抖動(dòng)就是那種檢測到變化后封鎖輸入一段時(shí)間的方法這種方式容易漏掉連續(xù)按下的第二個(gè)按鍵。4.3 現(xiàn)象每個(gè)音符都偏高或偏低且越往高音偏差越大這類現(xiàn)象跟分頻系數(shù)的取整方式有關(guān)。以 A4 的 440Hz 為例50MHz 除以兩倍頻率等于 56818.18取整到 56818 時(shí)輸出頻率誤差極小人耳聽不出來。但如果你有的音符向下取整有的四舍五入誤差就會(huì)被放大。更常見的錯(cuò)誤是翻轉(zhuǎn)點(diǎn)寫錯(cuò)計(jì)數(shù)器按 K 計(jì)數(shù)時(shí)如果誤在計(jì)數(shù)到 K 時(shí)才清零由于計(jì)數(shù)器從 0 開始實(shí)際等于走了 K1 個(gè)周期每個(gè)音符都偏低約一個(gè)時(shí)鐘周期的比例。解決辦法是統(tǒng)一取整規(guī)則并且嚴(yán)格按“計(jì)數(shù)到 K-1 清零或翻轉(zhuǎn)”來設(shè)計(jì)。高音區(qū)偏差更明顯是因?yàn)轭l率越高 K 越小取整的相對誤差就越大。對 8 音符單手琴來說誤差在 1% 以內(nèi)幾乎聽不出區(qū)別但如果擴(kuò)展成 12 半音版本建議每個(gè)系數(shù)先算到小數(shù)點(diǎn)后兩位再統(tǒng)一向下取整然后用仿真確認(rèn)每個(gè)音的實(shí)際輸出頻率。4.4 現(xiàn)象下載成功但按鍵引腳電平異常相鄰按鍵互相影響第一反應(yīng)是查原理圖連線但實(shí)際上很多是引腳分配沖突。開發(fā)板上的按鍵往往和 LED 或擴(kuò)展排針共用同一個(gè) IO默認(rèn)情況下該引腳可能已經(jīng)被分配成別的用途比如方向被設(shè)為輸出或者在電路上接了強(qiáng)下拉。解決辦法是打開 Pin Planner重新指定按鍵輸入引腳并檢查 .qsf 文件里有沒有同一個(gè)引腳被分配給兩個(gè)信號(hào)。另一類電平異常來自上拉設(shè)置。FPGA 輸入引腳默認(rèn)可能有弱上拉如果按鍵電路是按鍵一端接地、另一端接 IO那么默認(rèn)上拉是合理設(shè)計(jì)按下時(shí)拉低。如果按鍵接的是電源就需要關(guān)掉內(nèi)部上拉或把消抖模塊里的有效電平判斷反過來。我一般把按鍵統(tǒng)一設(shè)計(jì)成低電平有效消抖模塊只判斷低電平狀態(tài)這樣換不同的開發(fā)板時(shí)改動(dòng)最小。4.5 現(xiàn)象增加消抖延遲后出現(xiàn)長按無響應(yīng)這個(gè)坑很隱蔽。為了讓消抖更可靠有人會(huì)把采樣確認(rèn)時(shí)間加長結(jié)果快速連續(xù)按兩個(gè)鍵時(shí)第二個(gè)鍵沒了反應(yīng)。原因是確認(rèn)窗口太長第一個(gè)鍵釋放和第二個(gè)鍵按下都落進(jìn)了同一個(gè)窗口邏輯認(rèn)為還是沒有變化。解決思路是采樣與確認(rèn)分離持續(xù)以固定周期采樣按鍵電平但只在電平狀態(tài)從穩(wěn)定變成另一個(gè)穩(wěn)定時(shí)才產(chǎn)生脈沖。換句話說消抖模塊的職責(zé)是過濾毛刺而不是阻塞輸入。每次采樣都運(yùn)行只是輸出脈沖的條件變嚴(yán)格了。這個(gè)做法在原理圖里實(shí)現(xiàn)也不復(fù)雜把移位寄存器的輸出端加一個(gè)異或門檢邊檢測到邊沿再觸發(fā)加載即可。5. 二次開發(fā)思路從單音電子琴擴(kuò)展成雙音與音色切換5.1 先給音調(diào)分頻器加一個(gè)第二聲部最簡單有效的改造是把 tone_div 模塊復(fù)制一份新模塊使用另一組 ROM 表兩個(gè)模塊的輸出通過一個(gè)或門合并到同一個(gè)蜂鳴器引腳。注意不能直接短路兩個(gè)輸出FPGA 引腳內(nèi)部驅(qū)動(dòng)并聯(lián)會(huì)互相沖突應(yīng)該在輸出級加一個(gè)邏輯門或三態(tài)緩沖器。這樣左手按低音區(qū)按鍵、右手按高音區(qū)按鍵時(shí)兩個(gè)分頻器同時(shí)工作就實(shí)現(xiàn)了雙音效果。改造后按這樣的順序驗(yàn)證先單獨(dú)聽低音分頻器輸出確認(rèn)音準(zhǔn)再單獨(dú)聽高音分頻器確認(rèn)音準(zhǔn)最后把兩個(gè)輸出合并聽有沒有相互搶占時(shí)序?qū)е碌拿搪?。如果合并后聲音變悶或變炸多半是輸出?qū)動(dòng)能力不足在合并點(diǎn)后面加一個(gè)緩沖器就能解決。5.2 用占空比調(diào)節(jié)模擬音色如果你不滿足于方波可以給 tone_div 加一個(gè)占空比參數(shù)。具體做法是在計(jì)數(shù)器后面加兩個(gè)比較器計(jì)數(shù)器計(jì)到半周期時(shí)輸出翻高再計(jì)到一個(gè)偏移值后翻低。例如把高電平時(shí)間固定為周期 50%就是標(biāo)準(zhǔn)方波改成 25%輸出窄脈沖波諧波成分更豐富聽起來更尖銳改成 75% 則圓潤一些。在原理圖上這個(gè)改動(dòng)只需要加兩個(gè)常數(shù)寄存器和一個(gè)比較器不需要重新算分頻系數(shù)。占空比參數(shù)可以做成兩個(gè)撥碼開關(guān)輸入運(yùn)行時(shí)切換音色。加上前面的雙音改造這臺(tái)電子琴就從單音玩具變成了可以玩出一點(diǎn)樣子的實(shí)驗(yàn)平臺(tái)。我把這套工程拆完之后的習(xí)慣是每次改動(dòng)只動(dòng)一個(gè)模塊下載前先在仿真器里看一條音符的輸出頻率確認(rèn)誤差可接受后再上板試聽。這樣手里拿到任何一塊新板子半天之內(nèi)都能把引腳、分頻系數(shù)、蜂鳴器類型這些環(huán)境變量全部適配完。希望這篇拆解幫到你也少走一些我曾經(jīng)走過的彎路。本文還有配套的精品資源點(diǎn)擊獲取