这是我大三时的电子课程设计,做的声音定位系统,课设具体要求如下:
附件里包含了,整个系统的源码,设计报告(含原理图)
本次设计采用 STC89C52RC 单片机进行运算处理和驱动 LCD12864 液晶显示
屏显示定位结果,即利用单片机内部定时器 0 计时,由外部中断 0、外部中断 1和定时器 1触发,检测接收信号的下降沿,通过这种方式计算声音传播后,不同模块接收到信号的时间差,通过时间差计算出声源信号到接收模块距离,然后由单片机编程计算出声源的位置坐标,最终显示在液晶屏上。 STC89C52RC 单片机小系统电路和 LCD12864驱动电路如下图所示:
五、算法与程序设计
5.1数据处理原理:
本算法基于时间差算出未知点的坐标点。从理论上分析,只需三个已知点就可以对声音源进行定位,我们首先先将问题简化为二维平面内对声音源进行定位。 如下图所示,在一个平面内分布有三个传感器A、 B和C坐标分别为(0,350)、(0,0)、(500,0)。当平面内某处 S(x,y)发出声音时,3 个传感器将先后接收到信号,设信号到达A,B的时间差为 t1,到达B,C的时间差为 t2,则有:
六、测试方案
6.1 主要的测试仪器、仪表
本次主要使用的测试仪器与仪表有,函数信号发生器、示波器与数字万用表。
6.2 测试方法
在硬件测试中,按键发声模块通过示波器测试电路输出波形,调节电位器改变电阻值来调节触发时间,保证发出的声响持续时间为 1s;另外使用数字万用表测量按键发声模块的功耗。声音接收模块通过数字万用表,测量当发声模块距接收模块不同距离时,比较器输出电压,直至调节电位器,改变比较器灵敏度使输出电压在要求距离内能受到信号,并以下降沿触发单片机。声响模块和接收模块都可以使用函数发生器和示波器来检测电路的连接是否正常。
在软件测试中,我们组软件调试的中心思想是分模块调试。先将程序分为三个接受模块,算法模块,显示模块,我们在分块调试时,将各个模块的输出都显示出来以便于观察各模块是否正确。运用这种方法,可以将软件上的错误精确定位到某一个环节,大大提高了调试的效率。以下是具体方法:
1、将程序中的标志位signalA,signalB,signalC 通过LCD屏幕显示出来,以方便
观察是否所有传感器都收到了信号。
2、将各信号间的时间差通过 LCD 屏幕显示出来,以方便观察各传感器的响应速度以及接受信号的先后顺序是否与实际一致。
3、在接入传感器前,先用另一片单片机模仿传感器发出的信号,并通过程序设置时间差等参数,用于检查算法是否正确。
七、系统调试
7.1 按键发声模块
测试输出电流(通过测量蜂鸣器串联的 1Ω的电阻得到电流值),从图中可知
为0.042A:
7.2 声音接收模块
当声响模块离接收模块距离较近时,接收模块输出电压达到 3.6V 左右。
当声响模块离接收模块较远时(但坐标仍属于坐标纸的范围),接收模块输出电压将会变小。这个时候就需要调节电位器,改变电阻值以减小比较器 LM358 输入端参考电压的值。
7.3 LCD 液晶显示模块
进行测试时,LCD12864 液晶显示模块除了显示坐标 X 与 Y的值外,还会显示A、B、C 三个声音接收模块的中断触发标志值(如下图显示屏中第一行所显示的内容,其中显示值为 0 表示未触发,为 1 则表示已触发),以及 A、B 和 C 三个声音接收模块依次收到信号时的计时时刻(其中从右到左依次为0us,65us和68us,此时模块 C 最先收到声音信号) ,这样方便系统调试。 下图坐标 X 与Y值在误差范围内,满足测量要求。
从表 8.2 可以看出,当电位器阻值较小时即比较器输入端参考电压接近 0 时更易收到信号,但实际上这样做也更容易受到干扰。接收模块 C 相较于A、B 模块了,由于焊接工艺的问题,灵敏度较低。合理调节电位器阻值之后,三个模块最终都能受到信号,满足设计要求。
8.3 声源实测坐标记录表
对处于不同坐标的声源进行了实际测量,最终得到了以下的一些实测数据如下
从表中可以看出,除个别点外,坐标纸的四个方向边缘区域以及中间区域共取了5个点,其实测坐标基本满足设计要求。而个别点的误差可能是由于接收模块放置的位置不准确或声源放置地不准确而产生。
九、总结
本次设计以 STC89C52 为核心部件,利用了声音检测与辨识技术,利用严密的数学方法实现和确定了声源的准确定位。在系统设计过程中,力求硬件电路简单,降低硬件成本,节约功耗。
在这次课程设计中,我们遇到了许多问题,这些问题我们之前从未遇到过,
但最终我们都找到了解决这些问题的办法,这对我们来说是一次很好的锻炼。在程序设计与软件调试的过程之中,由于我们同时使用了 STC89C52 单片机中的四个中断进行控制处理,对于单片机各个中断的优先级与触发的考虑更为复杂,但只要结合函数信号发生器模拟声音信号触发单片机得到调试结果,并且根据这些结果不断改正程序,就能得到最优的程序设计。另外在程序设计过程,由于子程序中数据处理十分重要,我们查阅了许多的资料,对于 C51中的数据类型以及常用的库函数也更加的熟悉。 在硬件调试过程中,出现了声音接收模块电路不稳定,易受到干扰,以及放大电路难以调试的问题。对于接下来课程设计之后,我们也会考虑重新设计相关电路,例如采用双比较器电路进行比较放大,来提高电路的性能。
主程序源码
- #include<reg52.h>
- #include<stdio.h>
- #include "delay.h"
- #include "lcd.h"
- #include<math.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define BOOL bit
- #define BYTE unsigned char
- #define WORD unsigned int
- uchar signalA,signalB,signalC;
- uchar wolsignalA,wolsignalB,wolsignalC;
- uchar wolCount,obv;
- unsigned int posX,posY; //坐标取值
- code unsigned char byValidShow[] = {" V值: "};
- code unsigned char DispX[] = {" X轴: "};
- code unsigned char DispY[] = {" Y轴: "};
- void Init_Show() //LCD初始化显示子程序
- {
- Delay400Ms();
- LCDInit();
- LCDClear();
- Delay5Ms();
- LCDClear();
- //DisplayListChar(0,1,byValidShow);
- DisplayListChar(0,2,DispX);
- DisplayListChar(0,3,DispY);
- Delay5Ms();
- }
- void Init_isr() //中断初始化设置子程序
- {
- EA = 0;
- TMOD = 0x62;
- /*外部中断0*/
- IT0 = 1; EX0 = 1;
- /*外部中断1*/
- IT1 = 1; EX1 = 1;
- /* 计数器 0*/
- TH1 = 0xFF; TL1 = 0xFF; TR1 = 1; ET1 = 1;
- /* 定时器 1*/
- TH0 = 246; TL0 = 246; TR0 = 0; ET0 = 0;
- /***********/
- IE0=0;IE1=0;TF1=0;TF0=0;
- EA = 1;
- }
- void signalchuli(float m,float n) //坐标定位计算程序
- {
- BOOL r1=0;
- BOOL r2=0; //方程是否成立变量
- BOOL suc=0; //解题是否成功变量
- float x,y;
- for(x=10;x<=500;x+=10)
- {
- for(y=10;y<=350;y+=10)
- {
- if(fabs(sqrt(x*x+(350-y)*(350-y))- sqrt(x*x+y*y)-m)<=20.0)
- r1=1;
- //else r1=0;
- if(fabs(sqrt(x*x+y*y)-sqrt(y*y+(500-x)*(500-x)) -n)<=20.0)
- r2=1;
- //else r2=0;
- if(r1&&r2)
- {
- suc=1;
- break;
- }
- else
- {
- r1=0;
- r2=0;
- }
- }
- if(suc)
- break;
- }
-
- posX=x;
- posY=y;
-
- }
- void main()
- {
- float cha1,cha2;
- uchar cha1_temp,cha2_temp;
- EA=0;
- Init_Show();
- Init_isr();
- while(1)
- {
- if( signalA && signalB && signalC)
- {
- EA = 0;
- TR0=0;
- obv++;
- cha1_temp = wolsignalA - wolsignalB;
- cha2_temp = wolsignalB - wolsignalC;
- if(wolsignalA < wolsignalB)
- {
- cha1_temp = 65536 - cha1_temp;
- cha1 = -(3.4*cha1_temp);
- }
- else
- {
- cha1 = 3.4*cha1_temp;
- }
- if(wolsignalB < wolsignalC)
- {
- cha2_temp = 65536 - cha2_temp;
- cha2 = -(3.4*cha2_temp);
- }
- else
- {
- cha2 = 3.4*cha2_temp;
- }
- signalchuli(cha1,cha2);
- DisplayADData(4,2,posX);
- DisplayADData(4,3,posY); //显示坐标
- signalA = 0;
- signalB = 0;
- signalC = 0;
- wolCount = 0;
- Init_isr();
- }
- DisplayADData(0,4,wolsignalA);
- DisplayADData(3,4,wolsignalB);
- DisplayADData(6,4,wolsignalC); //显示时间插值,方便调试
- DisplayADData(0,1,signalA);
- DisplayADData(3,1,signalB);
- DisplayADData(6,1,signalC); //显示触发标志位,方便调试
- }
- }
- void JsA_isr() interrupt 0 //外部中断0,下降沿触发
- {
- EX0 = 0;
- if(wolCount == 0)
- {
- wolsignalA = 0;
- TR0 = 1;
- ET0 = 1;
- }
- else
- {
- wolsignalA = wolCount;
- }
- signalA = 1;
- }
- void JsB_isr() interrupt 2 //外部中断1,下降沿触发
- {
-
- if(wolCount == 0)
- {
- wolsignalB = 0;
- TR0 = 1;
- ET0 = 1;
- }
- else
- {
- wolsignalB = wolCount;
- }
- signalB =1;
- EX1 = 0;
- }
- void Timer1_isr() interrupt 3 //计数器1,工作方式2
- {
- if(wolCount == 0)
- {
- wolsignalC = 0;
- TR0 = 1;
- ET0 = 1;
- }
- else
- {
- wolsignalC = wolCount;
- }
- signalC = 1;
- ET1 = 0;
- }
- void Timer0_isr() interrupt 1 //定时器0,工作方式2 , 10us
- {
- wolCount++;
- }
复制代码 仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
全部资料51hei下载地址:
声音定位系统.rar
(1.6 MB, 下载次数: 353)
|