娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2025年05月31日(星期六)

2019年05月31日 | STM32掌機教程6,電子琴

發布者:真誠相伴 來源: eefocus關鍵字:STM32  掌機教程  電子琴 手機看文章 掃描二維碼
隨時隨地手機看文章

??本節原來是想講一講無源蜂鳴器發聲的原理,用于添加BGM功能。為了講原理,就寫了一些通俗的代碼,沒想到越寫越多,后來,干脆就形成了一個小小的項目吧——基于STM32與無源蜂鳴器的電子琴。


燈光效果

??首先想到的是做一個燈光的效果,按下哪個按鍵,哪個按鍵的燈要亮;松手后,燈滅掉。順帶,檢測一下帶松手檢測的按鍵功能好不好用。后續還可以做成通過亮燈提示需要按下那個按鍵,類似于節奏大師的功能——哪里要響點哪里。




??我去掉了無關的代碼,主函數里通過死循環,來確保按鍵按下的時候,燈是亮起來的 :


//main.c 

while(1)

{

AllLED_OFF();

while(!SKEY1)

{

SLED1 = LED_ON;

}

while(!SKEY2)

{

SLED2 = LED_ON;

}

while(!SKEY3)

{

SLED3 = LED_ON;

}

while(!SKEY4)

{

SLED4 = LED_ON;

}

while(!SKEY5)

{

SLED5 = LED_ON;

}

while(!SKEY6)

{

SLED6 = LED_ON;

}

while(!SKEY7)

{

SLED7 = LED_ON;

}

while(!SKEY8)

{

SLED8 = LED_ON;

}

if(PAUSE_PRES == KEY_Scan(0))

{

LED1 = !LED1;

}

}



??下載程序并看看現象。


無源蜂鳴器的音調控制

??音調和頻率是息息相關的,可以在網上查找到頻率和音調對應的表格。本文的代碼參考了這篇文章,表示感謝

在這里插入圖片描述

??根據圖片,可以做宏定義,中音的C調:


#define CM1 523

#define CM2 587


??為了講清楚原理,這里蜂鳴器先當做LED用。引腳給高電平,蜂鳴器就能響(只有一瞬間有聲音)。然而,只給高電平,無源蜂鳴器不能自己持續發出聲音;需要馬上給低電平,然后再給一個高電平。即在一個很短的周期內,無源蜂鳴器在高電平持續器件工作,在低電平持續器件休息。周期的倒數就是頻率。

??蜂鳴器的引腳是PB1,初始化跟LED一樣,我直接寫在了LED的初始化函數里。

??接下來先寫兩個按鍵的功能,用按鍵1和2來演奏C調的哆和唻。我定義了一個變量,是us為單位的時間,這是蜂鳴器的一個周期。它的值就是1000000us(1百萬us就是1s)除以頻率。頻率是查表得到的。在周期內,高電平持續的時間和低電平持續的時間各占一半。


//main.c

u32 F_us;   //特定頻率對應的周期時間,單位us

while(!SKEY1)

{

    SLED1 = LED_ON;

    F_us = 1000000/CM1;

    BEEP = 1;

    delay_us(F_us/2);

    BEEP = 0;

    delay_us(F_us/2);

}

while(!SKEY2)

{

    SLED2 = LED_ON;

    F_us = 1000000/CM2;

    BEEP = 1;

    delay_us(F_us/2);

    BEEP = 0;

    delay_us(F_us/2);

}


??下載程序,按下按鍵1或2,就可以聽到不同的音調。原理就是這么簡單。


音量控制

??無源蜂鳴器可以用高電平持續的時間調整音量,在一個周期中,高電平持續的時間越長,蜂鳴器聲音越大;高電平持續的時間越短,蜂鳴器的聲音越小。這句話還有一個時髦的描述方法——脈寬調制

在這里插入圖片描述

??原理很簡單,實現起來也不復雜。在上一個案例的基礎上,我把高電平持續的時間由50%改成了通過變量volum來計算。如果volum=1,那么高電平持續的時間就是周期的一半(右移一位等于除以2);如果volum=5,那么高電平持續的時間就是周期的64分之1,(右移n位等于除以2的n次方)。為了方便比較,我先讓按鍵1和2的音調一樣,音量不一樣。


//main.c

u32 F_us;   //特定頻率對應的周期時間,單位us

u32 time_ON;   //蜂鳴器響的時間

u32 time_OFF;   //蜂鳴器不響的時間

u8 volum;    //音量

while(!SKEY1)

{

    SLED1 = LED_ON;

    F_us = 1000000/CM1;

    volum = 1;

    time_ON = F_us>>volum;

    time_OFF = F_us - time_ON;

    BEEP = 1;

    delay_us(time_ON);

    BEEP = 0;

    delay_us(time_OFF);

}

while(!SKEY2)

{

    SLED2 = LED_ON;

    F_us = 1000000/CM1;

    volum = 6;

    time_ON = F_us>>volum;

    time_OFF = F_us - time_ON;

    BEEP = 1;

    delay_us(time_ON);

    BEEP = 0;

    delay_us(time_OFF);

}


??按下兩個按鍵,可以聽出響度是不一樣。事實上我調整過比例,感覺,50%的占空比可能是最大的聲音了,,volum < 4之前都聽不大出來。


提取函數

??既然按鍵1和按鍵2都既能控制音調,用能控制音量了,別的按鍵把代碼復制粘貼就能實現功能了。只不過,復制粘貼是代碼不好的表現。


??所以,再次提取出一個函數,傳入音調和音量,就能發出聲音。


void play(u32 tone,u8 tvolum)

{

u32 F_us;   //特定頻率對應的周期時間,單位us

u32 time_ON;   //蜂鳴器響的時間

u32 time_OFF;   //蜂鳴器不響的時間

F_us = 1000000/tone;

time_ON = F_us>>tvolum;

time_OFF = F_us - time_ON;

BEEP = 1;

delay_us(time_ON);

BEEP = 0;

delay_us(time_OFF);

}


??然后修改死循環。我有8個帶燈按鍵,但是音調只有7個,所以預留8和pause用于升降調,這兩個按鍵無需松手檢測。其它按鍵按下時,調用play函數。


while(1)

{

key = KEY_Scan(0);

if(KEY8_PRES == key)

{

LED2 = !LED2;

}

else if(PAUSE_PRES == key)

{

LED1 = !LED1;

}

else

{

AllLED_OFF();

}

while(!SKEY1)

{

SLED1 = LED_ON;

play(CM1,volum);

}

while(!SKEY2)

{

SLED2 = LED_ON;

play(CM2,volum);

}

while(!SKEY3)

{

SLED3 = LED_ON;

play(CM3,volum);

}

while(!SKEY4)

{

SLED4 = LED_ON;

play(CM4,volum);

}

while(!SKEY5)

{

SLED5 = LED_ON;

play(CM5,volum);

}

while(!SKEY6)

{

SLED6 = LED_ON;

play(CM6,volum);

}

while(!SKEY7)

{

SLED7 = LED_ON;

play(CM7,volum);

}

}


??至此,就已經實現了最簡單的電子琴的功能。


升調和降調功能

??默認情況下,我們演奏的都是C調中間那個音階。我定義按鍵8升調,按鍵PAUSE為降調(其實調整的不是音調而是音階)。然后定義個變量用于儲存當前是C調還是F調,也就是音階?


while(1)

{

key = KEY_Scan(0);

if(KEY8_PRES == key)

{

LED2 = !LED2;

tone_level++;

}

else if(PAUSE_PRES == key)

{

LED1 = !LED1;

tone_level--;

}

else

{

AllLED_OFF();

}

        。。。

     }


??修改play函數,根據音階與音調來計算周期。


void play(u32 tone,u8 tvolum)

{

u32 F_us;   //特定頻率對應的周期時間,單位us

u32 time_ON;   //蜂鳴器響的時間

u32 time_OFF;   //蜂鳴器不響的時間

if(tone_level<1)

tone_level = 1;

else if(tone_level>12)

tone_level = 12;

if(1 == tone_level)

{

switch(tone)

{

case 1:F_us = 1000000/CL1;

case 2:F_us = 1000000/CL2;

case 3:F_us = 1000000/CL3;

case 4:F_us = 1000000/CL4;

case 5:F_us = 1000000/CL5;

case 6:F_us = 1000000/CL6;

case 7:F_us = 1000000/CL7;

}

}

else if(2 == tone_level)

{

switch(tone)

{

case 1:F_us = 1000000/CM1;

case 2:F_us = 1000000/CM2;

case 3:F_us = 1000000/CM3;

case 4:F_us = 1000000/CM4;

case 5:F_us = 1000000/CM5;

case 6:F_us = 1000000/CM6;

case 7:F_us = 1000000/CM7;

}

}

//F_us = 1000000/tone;

time_ON = F_us>>tvolum;

time_OFF = F_us - time_ON;

BEEP = 1;

delay_us(time_ON);

BEEP = 0;

delay_us(time_OFF);

}


??這段代碼太糟糕了,才寫了兩種音階我就受不了了。之前音調的信息都是宏定義,為了方便調用,我改成數組。


//beep.c

u16 CL[7]={262,294,330,349,392,440,494};

u16 CM[7]={523,587,659,698,784,880,988};

u16 CH[7]={1047,1175,1319,1397,1568,1760,1976};

u16 DL[7]={294,330,370,392,440,494,554};

u16 DM[7]={587,659,740,784,880,988,1109};

u16 DH[7]={1175,1319,1480,1568,1760,1976,2217};

u16 EL[7]={330,370,415,440,494,554,622};

u16 EM[7]={659,740,831,880,988,1109,1245};

u16 EH[7]={1319,1480,1661,1760,1976,0,0};

u16 FL[7]={349,392,440,466,523,587,659};

u16 FM[7]={698,784,880,932,1047,1175,1319};

u16 FH[7]={1397,1568,1760,1865,0,0,0};


??然后修改演奏函數。


void play(u32 tone,u8 tvolum)

{

u32 F_us;   //特定頻率對應的周期時間,單位us

u32 time_ON;   //蜂鳴器響的時間

u32 time_OFF;   //蜂鳴器不響的時間

if(tone_level<1)

tone_level = 1;

else if(tone_level>12)

tone_level = 12;

switch(tone_level)

{

case 1: F_us = 1000000/CL[tone];break;

case 2: F_us = 1000000/CM[tone];break;

case 3: F_us = 1000000/CH[tone];break;

case 4: F_us = 1000000/DL[tone];break;

case 5: F_us = 1000000/DM[tone];break;

case 6: F_us = 1000000/DH[tone];break;

case 7: F_us = 1000000/EL[tone];break;

case 8: F_us = 1000000/EM[tone];break;

case 9: F_us = 1000000/EH[tone];break;

case 10:F_us = 1000000/FL[tone];break;

case 11:F_us = 1000000/FM[tone];break;

case 12:F_us = 1000000/FH[tone];break;

}

//F_us = 1000000/tone;

time_ON = F_us>>tvolum;

time_OFF = F_us - time_ON;

BEEP = 1;

delay_us(time_ON);

BEEP = 0;

delay_us(time_OFF);

}


??主函數調用的部分也修改了。注意,數組的索引是從零開始的。


while(1)

{

key = KEY_Scan(0);

if(KEY8_PRES == key)

{

LED2 = !LED2;

tone_level++;

}

else if(PAUSE_PRES == key)

{

LED1 = !LED1;

tone_level--;

}

else

{

AllLED_OFF();

}

while(!SKEY1)

{

SLED1 = LED_ON;

play(0,volum);//數組的第一個元素是0

}

while(!SKEY2)

{

SLED2 = LED_ON;

play(1,volum);

}

while(!SKEY3)

{

SLED3 = LED_ON;

play(2,volum);

}

while(!SKEY4)

{

SLED4 = LED_ON;

play(3,volum);

}

while(!SKEY5)

{

SLED5 = LED_ON;

play(4,volum);

}

while(!SKEY6)

{

SLED6 = LED_ON;

play(5,volum);

}

while(!SKEY7)

{

SLED7 = LED_ON;

play(6,volum);

}

}


??也可以把音階的信息作為一個變量傳入參數,避免使用全局的變量。

??實際演奏時,還發現了小小的BUG,E和F的高音,數組不夠7個,如果傳入的參數是0,那么F_us的時候分母是0,程序可能卡死,所以把0音調改成1了。當然也可以用判斷語句來避免這種情況。

??我還設想了很多功能,比如屏幕顯示個樂譜,屏幕顯示音調;按鍵亮起作為提示,然后按下對應的按鍵,發出聲音。想法越來越多,我只好趕緊收手了,畢竟,,,我原來的計劃是打地鼠掌機啊!電子琴只是為了講蜂鳴器的原理啊!

??放上兩只老虎的簡譜,來彈奏一曲吧。

關鍵字:STM32  掌機教程  電子琴 引用地址:STM32掌機教程6,電子琴

上一篇:STM32掌機教程7,演奏音樂
下一篇:STM32掌機教程5,程序框架,隨機,加命與升級

推薦閱讀

  大難臨頭的中興“躲過一劫”,雖然面臨13億美元的天價罰款,但是留得青山在,不怕沒柴燒。美國懂得了“變通”,那么中國是否該“禮尚往來”了?下面就隨手機便攜小編一起來了解一下相關內容吧。  如果是,這份“大禮”很可能就是放行高通收購恩智浦(NXP)。據知情人士稱,中國反壟斷審核機構對高通收購恩智浦一案的反壟斷審核已經清除所有實質性障礙,...
安裝STM32CubeMX??安裝STM32CubeMX之前,電腦中要有java運行時環境(JRE),否則會報錯:??雙擊JavaSetup8u201.exe即可安裝JRE。在安裝過程中,需要在線下載一些資源,所以應當保持網絡連接。??然后雙擊SetupSTM32CubeMX-5.0.1.exe。??建議放在默認的文件夾下。??安裝過程也比較簡單,不再贅述。新建STM32CubeMX工程??可以通過選擇單片機來創...
協作機器人夾爪制造商OnRobot推出2.5D視覺系統Eyes,適用于各家先進機器手臂,提供外加的深度感知和零件辨識功能。 據報導,機器手臂經常遇到的難題,就是無法拾放大小、形狀或擺放方向不一的物品,通常需要外加夾具、送料盤等其它硬件協助作業,但也因此增加作業成本和復雜度,局限了設備的應用范圍。 OnRobot新推出的2.5D視覺系統Eyes,只要照一張...
在2021中國(成都)水電創新應用成果大會上,四川東方水利智能裝備工程股份有限公司發布了公司首創的“河寶”H系列水上智能清污機器人。本次發布的四款新型水域機器人,將清污機器人產業向水面保潔、巡邏監測、應急救援、魚類生態保護等方面衍生發展,并采用“制造+服務”的商業模式,通過大數據平臺進行智能化運營管理,市場黏度高,可復制性強,通過產品創...

史海拾趣

問答坊 | AI 解惑

CC2430+CC2591 2.4G超遠低功率的無線模塊

CC2430+CC2591 模塊是在CC2430模塊上擴展了CC2591 CC2430+CC2591模塊是第一個符合ZigBee 的SOC芯片CC2430精心設計的加PA+LNA無線收發模塊;工作載頻為2.4GHZ,采用擴頻技術,另CC2430器件的性能已超過了IEEE802.15.4規范的要求;同時還具有優異的選擇 ...…

查看全部問答∨

項目設計:傳送帶速度測量

要求是在傳送帶的2端分別放置光電傳感器,中間用4個“7劃數碼管”(就是電子顯示的那個8)顯示傳送帶的速度 需要自行安裝排布所有的電路并分析 我們已完成光電傳感器的電路 問題在于如何使光電傳感器的輸出電壓作為測量速度的開始和結束?(需自 ...…

查看全部問答∨

求一份學習路線圖

本人想學有關底層的東西,就是為以后考研做準備,但不知道那個大學的研究生對os 的研究好。 想在這里求兩件事: 1)os 學好的的路線圖(列出書也可以)2)說說那個大學的os 研究好一點。…

查看全部問答∨

請問兩個問題??

1.如何用單擊代替雙擊?即單擊圖標即可打開 2.sd卡默認掛載Storage Card,怎么改這個名字??…

查看全部問答∨

求思路,關于指令優化運用的計算機組成的知識,高分啊

我們計算機組成原理考試,老師讓我們自己上網搜索具體運用了計算機組成原理知識的一些程序優化技術,比如沒優化時是怎樣的,運用了相關計算機組成知識優化后現在時間周期提高了多少, 望前輩們隨便舉個相關案例, 指個大方向也好, 我自己去查查, 急求, ...…

查看全部問答∨

關于Eboot添加USB下載功能 給假期疲勞的調劑 見者有分

硬件 友善 MINI2440    做了個BSP已經實現網絡下載   客戶要求實現DNW+USB下載   在網上down了個 三星原廠的CE5.0bsp%2C包括eboot,nboot,kernel,driver。實現了kitl,directdraw驅動+eboot有usb下載功能__2440b ...…

查看全部問答∨

無線教學產品開發經驗的硬件/軟件人員

您好! 急尋有無線教學產品開發經驗的硬件/軟件人員, 最好是開發過無線課堂互動系統,待遇優厚! 15321523579…

查看全部問答∨

SHLoadImageFile函數

我想打開png圖片,上網查到要用SHLoadImageFile函數可以,但是使用SHLoadImageFile函數需要aygshell.lib,我在網上找不到aygshell.lib,卻下載了AYGSHELL.DLL,可是光有AYGSHELL.DLL卻不知道應該怎么用它。 希望高人指點一下怎么用AYGSHELL.DLL來 ...…

查看全部問答∨

用單臺處理機順序計算表達式:f=a+be+ce^2+de^3,需幾級?若用三臺處理機計算此表達式,則只需幾級?

用單臺處理機順序計算表達式:f=a+be+ce^2+de^3,需幾級?若用三臺處理機計算此表達式,則只需幾級? …

查看全部問答∨

標準CE5BSP+2440+128MB SDRAM SD卡無法顯示盤符問題

我以優龍的2440+標準ce5的開發板為基礎做了自己的板子,并采用你的方法升級SDRAM為128M,系統可以啟動,但是啟動后無法識別SD卡,在控制面板中的存儲器管理器中也看不到SD卡,不知可能是什么原因??SD卡部分的硬件電路與優龍開發板的一樣,驅動 ...…

查看全部問答∨
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 阿拉尔市| 崇义县| 贵港市| 纳雍县| 海宁市| 柳州市| 沽源县| 西乡县| 酒泉市| 夹江县| 澄城县| 漳州市| 陇西县| 崇左市| 乌兰察布市| 旺苍县| 莱芜市| 津南区| 青州市| 阜康市| 禹州市| 宝兴县| 马公市| 高台县| 麻江县| 江西省| 固镇县| 萨迦县| 上思县| 会泽县| 洞头县| 阳朔县| 岗巴县| 广灵县| 新津县| 和林格尔县| 塘沽区| 昆明市| 青龙| 洞头县| 丹江口市|