新闻中心

EEPW首页>嵌入式系统>设计应用> 软硬结合——酷我音乐盒的逆天玩法

软硬结合——酷我音乐盒的逆天玩法

作者: 时间:2017-01-18 来源:网络 收藏

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

本文引用地址://m.amcfsurvey.com/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 串口发送函数

  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 }

  >_<:下面将重点介绍如何从距离信息转换为按钮触发消息的!

  6.1、检测手势:

  下图是当有手进入测距区时超声波测距仪采集到的数据,其中横轴为时间,纵轴为距离单位厘米。从图中可以看出当没有障碍物时距离维持在42CM处(这是我在示波器软件中故意设置的一个阈值,硬件代码里也设了阈值即:超出30cm就发送距离为0x88cm)。当手挥进对应区域时出现一个下降沿,当手离开时出现一个上升沿,当手在区域中停留的时间越长其对应跨度越大。(图中共有4个凹槽,表示手4次挥进挥出区域,其中第3次停留时间较长)

  6.2、干扰信号:

  如下图(不要管上面的图标,当时用的时候没修改图表的单位和名称,嘻嘻~)当没有手进入区域时有时候硬件会出现干扰而产生一个很尖的下降和上升沿,其实这时并没有手挥进区域,这个干扰会对结果造成影响,甚至出现错误的控制!!!

  6.3、去除干扰:

  如下图最下面的窗口是距离-时间图,其中第1、2、4为手挥进测距区,第3个是一次干扰。我是这样转换的:将距离-时间图转换为左上角的时长-时间图,每个波的峰值就是对应距离时间图中跳变时间,这样我们就能将每次手进入或者是干扰持续的时间的值获得!(由于干扰几乎都是瞬间跳变,所以滤掉那个最小的第3个时长-时间波峰对应的距离-时间图中的跳变就行啦)

  6.4、时长分段产生将控制信号signal:

  这里将遮蔽时长进行分段产生3种不同的控制信号:[参见5.1.2串口数据接收函数的第21~27行](这里num就是时长,可见:当时长为2~5时产生signal为1的信号,参看Timer部分可以发现这个信号控制点击下一曲;当时长在6~9的时候触发上一曲;当时长在10以上触发暂停)因为我经常要下一曲所以设成手一挥就执行,暂停一般操作较少就让它时长长一点(就像笔记本电脑的关机按钮!),加入上一曲是为了防止失误时能回到上面一个。!!!注意到这里没有把时长为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#串口

评论


相关推荐

技术专区

关闭