新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > 軟硬結合——酷我音樂盒的逆天玩法

軟硬結合——酷我音樂盒的逆天玩法

作者: 時間:2017-01-18 來源:網絡 收藏

  1 /***********************************************************

本文引用地址:http://m.butianyuan.cn/article/201701/343047.htm

  1 /***********************************************************************************************************/

  2 //HC-SR04 超聲波測距模塊應用程序

  3 //MCU: STC89C52/STC89C51

  4 //晶振:11。0592

  5 //接線:模塊TRIG接 P1.2 ECH0 接P1.1

  6 //波特率9600

  7 /***********************************************************************************************************/

  8 #include

  9 #include

  10 #include

  11

  12 #define uchar unsigned char

  13 #define uint unsigned int

  14 #define RX P1_1

  15 #define TX P1_2

  16

  17

  18 unsigned int time=0;

  19 unsigned int timer=0;

  20 unsigned char S=0,a;

  21 bit flag =0,usart_flag;

  22

  23

  24 /*--------------------------------------------

  25 USAR初始函數包括所有需要的中斷和時鐘,超聲波時鐘也在內]

  26 ---------------------------------------------*/

  27 void USRT_init()

  28 {

  29 TMOD=0x21; //設置T1定時器工作方式2,設T0為方式1,GATE=1;

  30 SCON=0x50;

  31 TH1=0xfd; //T1定時器裝初值

  32 TL1=0xfd;

  33 TH0=0; //超聲波測距計時器裝初始值

  34 TL0=0;

  35 TR1=1; //啟動T1定時器

  36 TR0=1;

  37 REN=1; //允許中斷接收、

  38 ET0=1; //允許T0中斷

  39 SM0=0; //設定工作方式

  40 SM1=1;

  41 EA=1; //開總中斷

  42 ES=1; //開串口中斷

  43 }

  44 /*--------------------------------------------

  45 串口發(fā)送函數

  46 ---------------------------------------------*/

  47 void SeriPushSend(unsigned send_data)

  48 {

  49 SBUF=send_data;

  50 while(!TI);

  51 TI=0;

  52 }

  53 /*--------------------------------------------

  54 串口中斷程序

  55 ---------------------------------------------*/

  56 void ser()interrupt 4

  57 {

  58 RI=0;

  59 a=SBUF;

  60 usart_flag=1;

  61 }

  62 /*--------------------------------------------

  63 超聲波距離計算函數

  64 ---------------------------------------------*/

  65 void Conut(void)

  66 {

  67 time=TH0*256+TL0;

  68 TH0=0;

  69 TL0=0;

  70 S=(int)(time*1.87)/100; //算出來是CM

  71 if(flag==1 || S>30) //超出測量或無效數據

  72 {

  73 flag=0;

  74 SeriPushSend(0x88);

  75 }

  76 else

  77 {

  78 SeriPushSend(S);

  79 }

  80 }

  81 /*--------------------------------------------

  82 毫秒延時函數

  83 ---------------------------------------------*/

  84 void delayms(unsigned int ms)

  85 {

  86 unsigned char i=100,j;

  87 for(;ms;ms--)

  88 {

  89 while(--i)

  90 {

  91 j=10;

  92 while(--j);

  93 }

  94 }

  95 }

  96 /*--------------------------------------------

  97 超聲波測距中斷函數[計時用]

  98 ---------------------------------------------*/

  99 void zd0() interrupt 1 //T0中斷用來計數器溢出,超過測距范圍

  100 {

  101 flag=1; //中斷溢出標志

  102 }

  103 /*--------------------------------------------

  104 超聲波測距啟動函數

  105 ---------------------------------------------*/

  106 void StartModule() //T1中斷用來掃描數碼管和計800MS啟動模塊

  107 {

  108 TX=1; //800MS 啟動一次模塊

  109 _nop_();

  110 _nop_();

  111 _nop_();

  112 _nop_();

  113 _nop_();

  114 _nop_();

  115 _nop_();

  116 _nop_();

  117 _nop_();

  118 _nop_();

  119 _nop_();

  120 _nop_();

  121 _nop_();

  122 _nop_();

  123 _nop_();

  124 _nop_();

  125 _nop_();

  126 _nop_();

  127 _nop_();

  128 _nop_();

  129 _nop_();

  130 TX=0;

  131 }

  132 /*--------------------------------------------

  133 main函數

  134 ---------------------------------------------*/

  135 void main(void)

  136 {

  137 USRT_init();

  138 while(1)

  139 {

  140 StartModule();

  141 while(!RX); //當RX為零時等待

  142 TR0=1; //開啟計數

  143 while(RX); //當RX為1計數并等待

  144 TR0=0; //關閉計數

  145 Conut(); //計算

  146 delayms(10); //10MS

  147 }

  148 }

  >_<:下面將重點介紹如何從距離信息轉換為按鈕觸發(fā)消息的!

  6.1、檢測手勢:

  下圖是當有手進入測距區(qū)時超聲波測距儀采集到的數據,其中橫軸為時間,縱軸為距離單位厘米。從圖中可以看出當沒有障礙物時距離維持在42CM處(這是我在示波器軟件中故意設置的一個閾值,硬件代碼里也設了閾值即:超出30cm就發(fā)送距離為0x88cm)。當手揮進對應區(qū)域時出現一個下降沿,當手離開時出現一個上升沿,當手在區(qū)域中停留的時間越長其對應跨度越大。(圖中共有4個凹槽,表示手4次揮進揮出區(qū)域,其中第3次停留時間較長)

    

 

  6.2、干擾信號:

  如下圖(不要管上面的圖標,當時用的時候沒修改圖表的單位和名稱,嘻嘻~)當沒有手進入區(qū)域時有時候硬件會出現干擾而產生一個很尖的下降和上升沿,其實這時并沒有手揮進區(qū)域,這個干擾會對結果造成影響,甚至出現錯誤的控制!!!

    

 

  6.3、去除干擾:

  如下圖最下面的窗口是距離-時間圖,其中第1、2、4為手揮進測距區(qū),第3個是一次干擾。我是這樣轉換的:將距離-時間圖轉換為左上角的時長-時間圖,每個波的峰值就是對應距離時間圖中跳變時間,這樣我們就能將每次手進入或者是干擾持續(xù)的時間的值獲得!(由于干擾幾乎都是瞬間跳變,所以濾掉那個最小的第3個時長-時間波峰對應的距離-時間圖中的跳變就行啦)

    

 

  6.4、時長分段產生將控制信號signal:

  這里將遮蔽時長進行分段產生3種不同的控制信號:[參見5.1.2串口數據接收函數的第21~27行](這里num就是時長,可見:當時長為2~5時產生signal為1的信號,參看Timer部分可以發(fā)現這個信號控制點擊下一曲;當時長在6~9的時候觸發(fā)上一曲;當時長在10以上觸發(fā)暫停)因為我經常要下一曲所以設成手一揮就執(zhí)行,暫停一般操作較少就讓它時長長一點(就像筆記本電腦的關機按鈕!),加入上一曲是為了防止失誤時能回到上面一個。!!!注意到這里沒有把時長為1的包含在內,這就是上面分析的結果,即所謂的濾波!消除干擾~

  1 if (num > 1 && num < 6){

  2 signal = 1;

  3 }else if (num > 5 && num < 10){

  4 signal = 2;

  5 }else if (num > 9){

  6 signal = 3;

  7 }

    

 

  7、總結:

  哈哈,終于寫完啦!>_<:快天亮啦~其實我本來想用腦電波來控制的,但是現在手頭有點吃緊,買不起腦電波呀~只能又一次玩廉價消費品啦~不過想一下連揮一揮手都不用的操作,是不是酷炫極啦!


上一頁 1 2 3 下一頁

關鍵詞: C# 串口

評論


相關推薦

技術專區(qū)

關閉