軟硬結(jié)合——酷我音樂(lè)盒的逆天玩法
1 /***********************************************************
本文引用地址:http://www.biyoush.com/article/201701/343047.htm1 /***********************************************************************************************************/
2 //HC-SR04 超聲波測(cè)距模塊應(yīng)用程序
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初始函數(shù)包括所有需要的中斷和時(shí)鐘,超聲波時(shí)鐘也在內(nèi)]
26 ---------------------------------------------*/
27 void USRT_init()
28 {
29 TMOD=0x21; //設(shè)置T1定時(shí)器工作方式2,設(shè)T0為方式1,GATE=1;
30 SCON=0x50;
31 TH1=0xfd; //T1定時(shí)器裝初值
32 TL1=0xfd;
33 TH0=0; //超聲波測(cè)距計(jì)時(shí)器裝初始值
34 TL0=0;
35 TR1=1; //啟動(dòng)T1定時(shí)器
36 TR0=1;
37 REN=1; //允許串口中斷接收、
38 ET0=1; //允許T0中斷
39 SM0=0; //設(shè)定串口工作方式
40 SM1=1;
41 EA=1; //開(kāi)總中斷
42 ES=1; //開(kāi)串口中斷
43 }
44 /*--------------------------------------------
45 串口發(fā)送函數(shù)
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 超聲波距離計(jì)算函數(shù)
64 ---------------------------------------------*/
65 void Conut(void)
66 {
67 time=TH0*256+TL0;
68 TH0=0;
69 TL0=0;
70 S=(int)(time*1.87)/100; //算出來(lái)是CM
71 if(flag==1 || S>30) //超出測(cè)量或無(wú)效數(shù)據(jù)
72 {
73 flag=0;
74 SeriPushSend(0x88);
75 }
76 else
77 {
78 SeriPushSend(S);
79 }
80 }
81 /*--------------------------------------------
82 毫秒延時(shí)函數(shù)
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 超聲波測(cè)距中斷函數(shù)[計(jì)時(shí)用]
98 ---------------------------------------------*/
99 void zd0() interrupt 1 //T0中斷用來(lái)計(jì)數(shù)器溢出,超過(guò)測(cè)距范圍
100 {
101 flag=1; //中斷溢出標(biāo)志
102 }
103 /*--------------------------------------------
104 超聲波測(cè)距啟動(dòng)函數(shù)
105 ---------------------------------------------*/
106 void StartModule() //T1中斷用來(lái)掃描數(shù)碼管和計(jì)800MS啟動(dòng)模塊
107 {
108 TX=1; //800MS 啟動(dòng)一次模塊
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函數(shù)
134 ---------------------------------------------*/
135 void main(void)
136 {
137 USRT_init();
138 while(1)
139 {
140 StartModule();
141 while(!RX); //當(dāng)RX為零時(shí)等待
142 TR0=1; //開(kāi)啟計(jì)數(shù)
143 while(RX); //當(dāng)RX為1計(jì)數(shù)并等待
144 TR0=0; //關(guān)閉計(jì)數(shù)
145 Conut(); //計(jì)算
146 delayms(10); //10MS
147 }
148 }
>_<:下面將重點(diǎn)介紹如何從距離信息轉(zhuǎn)換為按鈕觸發(fā)消息的!
6.1、檢測(cè)手勢(shì):
下圖是當(dāng)有手進(jìn)入測(cè)距區(qū)時(shí)超聲波測(cè)距儀采集到的數(shù)據(jù),其中橫軸為時(shí)間,縱軸為距離單位厘米。從圖中可以看出當(dāng)沒(méi)有障礙物時(shí)距離維持在42CM處(這是我在示波器軟件中故意設(shè)置的一個(gè)閾值,硬件代碼里也設(shè)了閾值即:超出30cm就發(fā)送距離為0x88cm)。當(dāng)手揮進(jìn)對(duì)應(yīng)區(qū)域時(shí)出現(xiàn)一個(gè)下降沿,當(dāng)手離開(kāi)時(shí)出現(xiàn)一個(gè)上升沿,當(dāng)手在區(qū)域中停留的時(shí)間越長(zhǎng)其對(duì)應(yīng)跨度越大。(圖中共有4個(gè)凹槽,表示手4次揮進(jìn)揮出區(qū)域,其中第3次停留時(shí)間較長(zhǎng))
![](http://www.eeworld.com.cn/uploadfile/2017/0115/1484472165175214.png)
6.2、干擾信號(hào):
如下圖(不要管上面的圖標(biāo),當(dāng)時(shí)用的時(shí)候沒(méi)修改圖表的單位和名稱,嘻嘻~)當(dāng)沒(méi)有手進(jìn)入?yún)^(qū)域時(shí)有時(shí)候硬件會(huì)出現(xiàn)干擾而產(chǎn)生一個(gè)很尖的下降和上升沿,其實(shí)這時(shí)并沒(méi)有手揮進(jìn)區(qū)域,這個(gè)干擾會(huì)對(duì)結(jié)果造成影響,甚至出現(xiàn)錯(cuò)誤的控制!!!
![](http://www.eeworld.com.cn/uploadfile/2017/0115/1484472165781683.png)
6.3、去除干擾:
如下圖最下面的窗口是距離-時(shí)間圖,其中第1、2、4為手揮進(jìn)測(cè)距區(qū),第3個(gè)是一次干擾。我是這樣轉(zhuǎn)換的:將距離-時(shí)間圖轉(zhuǎn)換為左上角的時(shí)長(zhǎng)-時(shí)間圖,每個(gè)波的峰值就是對(duì)應(yīng)距離時(shí)間圖中跳變時(shí)間,這樣我們就能將每次手進(jìn)入或者是干擾持續(xù)的時(shí)間的值獲得!(由于干擾幾乎都是瞬間跳變,所以濾掉那個(gè)最小的第3個(gè)時(shí)長(zhǎng)-時(shí)間波峰對(duì)應(yīng)的距離-時(shí)間圖中的跳變就行啦)
![](http://www.eeworld.com.cn/uploadfile/2017/0115/1484472165894251.png)
6.4、時(shí)長(zhǎng)分段產(chǎn)生將控制信號(hào)signal:
這里將遮蔽時(shí)長(zhǎng)進(jìn)行分段產(chǎn)生3種不同的控制信號(hào):[參見(jiàn)5.1.2串口數(shù)據(jù)接收函數(shù)的第21~27行](這里num就是時(shí)長(zhǎng),可見(jiàn):當(dāng)時(shí)長(zhǎng)為2~5時(shí)產(chǎn)生signal為1的信號(hào),參看Timer部分可以發(fā)現(xiàn)這個(gè)信號(hào)控制點(diǎn)擊下一曲;當(dāng)時(shí)長(zhǎng)在6~9的時(shí)候觸發(fā)上一曲;當(dāng)時(shí)長(zhǎng)在10以上觸發(fā)暫停)因?yàn)槲医?jīng)常要下一曲所以設(shè)成手一揮就執(zhí)行,暫停一般操作較少就讓它時(shí)長(zhǎng)長(zhǎng)一點(diǎn)(就像筆記本電腦的關(guān)機(jī)按鈕!),加入上一曲是為了防止失誤時(shí)能回到上面一個(gè)。!!!注意到這里沒(méi)有把時(shí)長(zhǎng)為1的包含在內(nèi),這就是上面分析的結(jié)果,即所謂的濾波!消除干擾~
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 }
![](http://www.eeworld.com.cn/uploadfile/2017/0115/1484472184511418.png)
7、總結(jié):
哈哈,終于寫(xiě)完啦!>_<:快天亮啦~其實(shí)我本來(lái)想用腦電波來(lái)控制的,但是現(xiàn)在手頭有點(diǎn)吃緊,買不起腦電波呀~只能又一次玩廉價(jià)消費(fèi)品啦~不過(guò)想一下連揮一揮手都不用的操作,是不是酷炫極啦!
評(píng)論