軟硬結合——酷我音樂盒的逆天玩法
1 /***********************************************************
本文引用地址:http://m.butianyuan.cn/article/201701/343047.htm1 /***********************************************************************************************************/
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、總結:
哈哈,終于寫完啦!>_<:快天亮啦~其實我本來想用腦電波來控制的,但是現在手頭有點吃緊,買不起腦電波呀~只能又一次玩廉價消費品啦~不過想一下連揮一揮手都不用的操作,是不是酷炫極啦!
評論