完整word版声音定位系统Word下载.docx

上传人:b****6 文档编号:16465348 上传时间:2022-11-23 格式:DOCX 页数:16 大小:72.80KB
下载 相关 举报
完整word版声音定位系统Word下载.docx_第1页
第1页 / 共16页
完整word版声音定位系统Word下载.docx_第2页
第2页 / 共16页
完整word版声音定位系统Word下载.docx_第3页
第3页 / 共16页
完整word版声音定位系统Word下载.docx_第4页
第4页 / 共16页
完整word版声音定位系统Word下载.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

完整word版声音定位系统Word下载.docx

《完整word版声音定位系统Word下载.docx》由会员分享,可在线阅读,更多相关《完整word版声音定位系统Word下载.docx(16页珍藏版)》请在冰豆网上搜索。

完整word版声音定位系统Word下载.docx

用RC无源滤波器。

通过计算可以较方便的通过匹配电阻电容得出所需要的通频带。

该滤波电路抗干扰性较强,有较好的低频特性,并且选用标准的阻容元件易得。

用有源滤波器。

有源滤波器是利用可关断电力电子器件,产生与负荷电流中谐波分量大小相等、相位相反地电流来抵消谐波的滤波装置。

有源滤波器除了滤除谐波外,同时还可以动态补偿无功功率。

其优点是反映动作迅速,滤除谐波可达到95%以上,补偿无功细致。

方案比较:

方案一中,谐波滤除率一般只有80%,对基波的无功补偿也是一定的,并且通频带比计算出的要宽,不太符合设计要求。

方案二中,电路比较复杂,但通过匹配后能较好的完成带通滤波,能达到预期的要求。

因此选择多路负反馈二阶有源带通滤波器,即方案二。

二、定位算法理论分析与计算

根据题目要求,A,B,C,D为声音接收模块,现对元坐标系进行坐标变换,以A点为坐标原点,建立笛卡尔坐标系,动点P(x,y)至点A,B,C,D的距离之差为一常数,建立数学模型:

三、电路与程序设计

1.声响模块电路设计

声响模块是由STM32单片机输出频率为500Hz的正弦波,然后从单片机引脚输出,输出的信号经过功率放大电路放大后,再接入到蜂鸣器,驱动发声。

2.声音接收放大器电路设计

接收部分是用拾音器接收声音信号。

由于拾音器接收到的信号在不经过放大时信号很小,不易检测,故后级利用放大电路将接收的信号进行处理。

图1放大电路

3.测量、数据处理电路设计

根据要求只有当接收到的信号为500Hz时,我们才能保证接收到的信号是由声源发出的。

而拾音器接收到的声音信号是任意频率的,故此处要进行滤波处理。

滤波采用的是带通滤波器,通过电容电阻的匹配,最终滤波器的中心频率为500Hz,带宽为50Hz。

拾音器接收到的信号经过带通滤波器后,能够将声源发出的信号滤出,正符合本题要求。

图2二阶有源滤波电路

滤波后的信号为正弦波,但该信号不便于用单片机进行处理,故在后级加入了相移检测电路。

其基本功能是对两路正弦波信号进行比较,并根据比较结果输出一路方波信号。

并由此来判断声音信号的位置差。

能够用单片机然后用单片机进行捕获处理,效果比较满意。

图3相移检测电路

4.程序设计

4.1该系统程序设计主要分为四部分:

用STM32产生500hz正弦波;

利用STM32的输入捕获捕获相移检测电路后的方波信号;

利用定位算法,通过单片机对检测到的相位差信号进行处理,得到声源位置坐标;

将得到的声源位置坐标送TFT屏显示,并将位置坐标存入数组中,实现连续显示声源位置轨迹的功能

四、测试方案与测试结果

1.测试方法与仪器

声源定位测试方法:

将声源放在坐标纸上的任意坐标,不让声源发声,记下坐标值(x0,y0)。

然后启动声源,让声源发出1s左右的声音信号,同时单片机接收信号后开始进行计算,计算出的坐标值(x1,y1)通过TFTLCD屏显示出来。

2.测试结果与分析

该系统的软件部分设计经验证,实现了捕获、处理、定位功能,如图所示为当声源信号位于(200,100)mm位置时,通过单片机定位算法得到的位置坐标:

图4捕获的到的高电平及单片机处理得到的位置信息

该系统的缺陷为功率放大模块和滤波模块没有做好,滤波模块实际滤波中心频率约为460hz,带宽100hz。

效果不够理想。

五、思考与总结

经过几天的努力,终于基本完成了声音定位系统的制作与程序设计,在此过程中,收益颇多,熟悉了功放、滤波、放大等模块的制作以及如何利用STM32单片机完成一个系统设计等。

在此过程中也认识到了许多不足,为以后的学习指明了方向。

六、参考文献(略)

七、附录

1、主程序

#include"

led.h"

delay.h"

key.h"

sys.h"

lcd.h"

usart.h"

timer.h"

math.h"

//全局变量x,y为坐标,以坐标纸左下角为原点,单位mm

s32xx=0,yy=0;

u8xp=0,yp=0;

u8xp1=0,yp1=0;

u16cap_num1=0,cap_num2=0;

u32sum1=0,sum2=0;

s16t1=0,t2=0;

u16pointx[280];

//定义点的位置数组

u16pointy[280];

u8DrawLine_flag=0;

//定义画线标志位

externu8TIM5CH1_CAPTURE_STA;

//输入捕获状态

externu16TIM5CH1_CAPTURE_VAL;

//输入捕获值

externu8TIM5CH2_CAPTURE_STA;

externu16TIM5CH2_CAPTURE_VAL;

voidDisplay_Change(void);

//对声源信号进行处理,得到声源位置

//当t1、t2情况为负值时,情况如何?

voidpxf(intt1,intt2)

{

inta=500;

intb=350;

floatv=340;

floatc1=t1*v/1000;

floatc2=t2*v/1000;

floatdelta=(b*b-c1*c1)/(a*a-c2*c2);

floatsita=atan2(b,delta*a)+acos((c2*delta-c1)/sqrt(delta*delta*a*a+b*b));

floatR=(b*b-c1*c1)/2/(c1+b*sin(sita));

xx=-R*cos(sita);

yy=R*sin(sita);

}

intmain(void)

{

u32temp1=0,temp2=0;

u16i=0,j=0;

Display_Change();

//通过读取A3管脚IO口的状态选择打点还是画线

delay_init();

//延时函数初始化

NVIC_Configuration();

//设置NVIC中断分组2:

2位抢占优先级,2位响应优先级

uart_init(9600);

//串口初始化为9600

LED_Init();

//LED端口初始化

LCD_Init();

TIM3_Int_Init(1999,719);

//每5ms进一次定时器3中断,进行液晶屏显示

TIM5_Cap_Init(0XFFFF,72-1);

//以1Mhz的频率计数(每计数一次为1u秒)

POINT_COLOR=RED;

LCD_Clear(YELLOW);

//背景色为黄色

LCD_ShowChar(10,210,'

('

16,0);

LCD_ShowChar(90,210,'

)'

LCD_ShowChar(50,210,'

'

while

(1)

{

for(i=0;

i<

400;

i++)//进行400次输入捕获,理论应该执行800ms,待验证

{

if(TIM5CH1_CAPTURE_STA&

0X80)//成功完成一次捕获

{

cap_num1++;

temp1=TIM5CH1_CAPTURE_STA&

0X3F;

temp1*=65536;

//溢出时间总和

temp1+=TIM5CH1_CAPTURE_VAL;

//得到总的高电平时间

sum1+=temp1;

TIM5CH1_CAPTURE_STA=0;

//开启下一次捕获

}

if(TIM5CH2_CAPTURE_STA&

cap_num2++;

temp2=TIM5CH2_CAPTURE_STA&

temp2*=65536;

temp2+=TIM5CH2_CAPTURE_VAL;

sum2+=temp2;

TIM5CH2_CAPTURE_STA=0;

}

t1=sum1/cap_num1;

//求平均值,提高捕获精度

printf("

\r\n通道1High:

%dus\r\n"

t1);

sum1=0;

cap_num1=0;

t2=sum2/cap_num2;

\r\n通道2High:

t2);

sum2=0;

cap_num2=0;

pxf(t1,t2);

xp=xx/2.5;

yp=140-yy/2.5;

if(xp>

10&

&

xp<

210&

yp>

yp<

150)//判断点的坐标是否在正常范围内

//把点存入数组

if(xp!

=xp1|yp!

=yp1)

{

pointx[j]=xp;

pointy[j]=yp;

j++;

if(j==280)//只存280个点的位置

{

j=0;

}

xp1=xp;

//将上一次的位置值进行保存,与下一次进行比较,看是否有变化

yp1=yp;

}

}

}

2、定时器部分程序

externs32xx,yy;

externu8xp,yp;

//注意:

对变量声明时不可以同时进行赋值

externu8xp1,yp1;

externu8DrawLine_flag;

//在定时器3中断中进行液晶显示

voidTIM3_Int_Init(u16arr,u16psc)

TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;

NVIC_InitTypeDefNVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

//时钟使能

//定时器TIM3初始化

TIM_TimeBaseStructure.TIM_Period=arr;

//设置在下一个更新事件装入活动的自动重装载寄存器周期的值

TIM_TimeBaseStructure.TIM_Prescaler=psc;

//设置用来作为TIMx时钟频率除数的预分频值

TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;

//设置时钟分割:

TDTS=Tck_tim

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;

//TIM向上计数模式

TIM_TimeBaseInit(TIM3,&

TIM_TimeBaseStructure);

//根据指定的参数初始化TIMx的时间基数单位

TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

//使能指定的TIM3中断,允许更新中断

//中断优先级NVIC设置

NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;

//TIM3中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

//IRQ通道被使能

NVIC_Init(&

NVIC_InitStructure);

//初始化NVIC寄存器

TIM_Cmd(TIM3,ENABLE);

//使能TIMx

//定时器3中断服务程序(声源位置显示)

voidTIM3_IRQHandler(void)//TIM3中断

if(TIM_GetITStatus(TIM3,TIM_IT_Update)!

=RESET)//检查TIM3更新中断发生与否

TIM_ClearITPendingBit(TIM3,TIM_IT_Update);

//清除TIMx更新中断标志

LCD_ShowNum(20,210,xx,3,16);

//显示数字

LCD_ShowNum(65,210,yy,3,16);

LCD_DrawRectangle(10,10,210,150);

//画矩形

LCD_DrawPoint(xp,yp);

//画点

if((xp!

=yp1)&

DrawLine_flag==1)

LCD_DrawLine(xp1,yp1,xp,yp);

ShowChinese(10,170);

//显示汉字

//定时器5通道1和通道2输入捕获配置

TIM_ICInitTypeDefTIM5_ICInitStructure;

voidTIM5_Cap_Init(u16arr,u16psc)

{

GPIO_InitTypeDefGPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

//使能TIM5时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

//使能GPIOA时钟

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;

//PA0清除之前设置

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;

//PA0下拉输入

GPIO_Init(GPIOA,&

GPIO_InitStructure);

GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1);

//初始化定时器时基参数TIM5

//设定计数器自动重装值

//预分频器

TIM_TimeBaseInit(TIM5,&

//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

//初始化TIM5输入捕获1参数

TIM5_ICInitStructure.TIM_Channel=TIM_Channel_1;

//CC1S=01选择输入端IC1映射到TI1上

TIM5_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;

//上升沿捕获

TIM5_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;

//映射到TI1上

TIM5_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;

//配置输入分频,不分频

TIM5_ICInitStructure.TIM_ICFilter=0x00;

//IC1F=0000配置输入滤波器不滤波

TIM_ICInit(TIM5,&

TIM5_ICInitStructure);

//初始化TIM5输入捕获2参数

TIM5_ICInitStructure.TIM_Channel=TIM_Channel_2;

//中断分组初始化

NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;

//TIM5中断

//先占优先级2级

NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

//从优先级0级

//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2,ENABLE);

//允许更新中断,允许CC1IE捕获中断

//TIM_IT_CC1:

TIM捕获/比较1中断源

TIM_Cmd(TIM5,ENABLE);

//使能定时器5

u8TIM5CH1_CAPTURE_STA=0;

//输入捕获状态

u16TIM5CH1_CAPTURE_VAL;

//输入捕获值

u8TIM5CH2_CAPTURE_STA=0;

u16TIM5CH2_CAPTURE_VAL;

//定时器5中断服务程序

voidTIM5_IRQHandler(void)

{

//通道1进行捕获

if((TIM5CH1_CAPTURE_STA&

0X80)==0)//表示还未成功完成捕获

{

if(TIM_GetITStatus(TIM5,TIM_IT_Update)!

=RESET)//表示更新中断已经发生

{

0X40)//表示已经捕获到高电平了

if((TIM5CH1_CAPTURE_STA&

0X3F)==0X3F)//判断高电平太长了

TIM5CH1_CAPTURE_STA|=0X80;

//强制标记成功捕获了一次

TIM5CH1_CAPTURE_VAL=0XFFFF;

elseTIM5CH1_CAPTURE_STA++;

}

if(TIM_GetITStatus(TIM5,TIM_IT_CC1)!

=RESET)//表示捕获1发生捕获事件

{

0X40)//表示捕获到一个下降沿

{

TIM5CH1_CAPTURE_STA|=0X80;

//标记成功捕获了一次

TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);

//得到高电平的值

TIM_OC1Po

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 小升初

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1