物理競賽麥克風(fēng)傳感器作品(未經(jīng)授權(quán)嚴(yán)禁復(fù)制或轉(zhuǎn)載)
信號處理與實驗數(shù)據(jù)收集
在對聲信號的收集過程中,我隊擬用數(shù)模轉(zhuǎn)換技術(shù)處理流經(jīng)麥克風(fēng)傳感器的信號。由于老型號的89C52單片機(jī)無法直接將來自傳感器的模擬信號轉(zhuǎn)為電信號,通過綜合考慮,我隊采用市場上廣泛使用的美制ADC0832芯片進(jìn)行編程處理。使用過程簡述如下,我們先將CS端口置于低電位,使能芯片;再向CLK發(fā)出第一個CLK脈沖,在脈沖上升沿處賦給DI一個高電平,決定芯片工作方式;當(dāng)Clk第三個時間脈沖上升沿選取通道,最后在第四個時間脈沖下降沿讀取AD轉(zhuǎn)換數(shù)據(jù)。此處為確保數(shù)據(jù)有效性需連續(xù)讀取兩次,第二次讀取的數(shù)據(jù)作為校驗。實現(xiàn)數(shù)模轉(zhuǎn)換之后,可通過程序內(nèi)降噪排除一定干擾并帶入計算公式得出結(jié)果。成果演示如下圖。由于麥克風(fēng)傳感器內(nèi)部結(jié)構(gòu)設(shè)計,其獲得的數(shù)據(jù)與聲音響度成相反趨勢。通過測量不同響度的聲音,可以此擬合出信號-響度關(guān)系曲線,為后續(xù)進(jìn)行人工信號降噪處理提供數(shù)據(jù)支持。
#include <reg52.h>
#include <intrins.h>?
sbit CS ? = P1^4;
sbit Clk = P1^2;
sbit DATI = P1^3;
sbit DATO = P1^3;? ?
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;? ? ? ??
unsigned char dat = 0;? ? ??
unsigned char CH=0;? ? ? ?
unsigned int sum=0;? ??
unsigned char m=0;
bit bdata flag;? ? ??
uchar set;? ? ? ?
uchar ? K_ZERO=40;? ? ??
int j,k,r,q;
char smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
extern void Key();
void delay()? ? ??
{
?int i;
? for(i=0;i<300;i++);
}
int temp=0;
unsigned char adc0832(unsigned char CH)
{
?unsigned char i,test,adval;
?adval = 0x00;
?test = 0x00;
?Clk = 0; ?//初始化。Clk拉低??
?DATI = 1;
?CS = 0; ? //ADC0832芯片使能
?Clk = 1; ?//使能后,第一個時間脈沖上升
?if ( CH == 0x00 ) ? ?//工作方式選取。此處默認(rèn)采用方式0??
?{
? Clk = 0; ?//送出時間脈沖,供其選擇通道方式(默認(rèn)通道0)
? DATI = 1; ?//通道0的第一位激活? ??
? Clk = 1;
? Clk = 0;
? DATI = 0; ?//通道0第二位激活? ?
? Clk = 1;
?}?
?Clk = 0; ? //選取工作方式的時間脈沖結(jié)束
?DATI = 1; ?//將DI變?yōu)楦咦钁B(tài)。此時已可以從DO口讀取數(shù)據(jù)
?for( i = 0;i < 8;i++ )? ? ??
?{
? adval <<= 1; ?//每次循環(huán)后由于從高位讀取,需向前移動一位
? Clk = 1;
? Clk = 0; ?//從最高位開始讀取數(shù)據(jù),每次下降沿處將進(jìn)行讀取
? if (DATO) ?//始終判斷DO是否為1,給變量adval賦終值
? adval |= 0x01;
? else
? adval |= 0x00;
?}
?for (i = 0; i < 8; i++) ?//建立test進(jìn)行比較,確保值的有效性
?{
? test >>= 1;
? if (DATO)
? test |= 0x80;
? else?
? test |= 0x00;
? Clk = 1;
? Clk = 0;
?}
?if (adval == test) ?//檢驗前八位與后八位是否相同。不相同則舍
?dat = test;
?CS = 1;? ? ? ??
?DATO = 1;
?Clk = 1;
?return dat; ?//將adval值返回給dat,數(shù)模轉(zhuǎn)換完成
}
void init() ?//計時器。每隔50毫秒進(jìn)行中斷
{
?TMOD=0x01;? ?
? TL0=0xb0;
? TH0=0x3c;? ?
? EA=1;? ??
?ET0=1;? ??
? TR0=1;? ??
}
void display() ?//顯示器,快速給四個數(shù)碼管分別賦值
{
?LSA=0;LSB=0;LSC=1;
?P0=smgduan[q];
?delay();
?LSA=1;LSB=1;LSC=0;
?P0=smgduan[r];
?delay();
?LSA=0;LSB=1;LSC=0;
?P0=smgduan[k];
?delay();
?LSA=1;LSB=0;LSC=0;
?P0=smgduan[j];
?delay();
}
void main()? ??
{
?int numb; ?//數(shù)碼管刷新間隔變量
?unsigned char LSA,LSB,LSC;
?LSA=0;
?LSB=0;
?LSC=0;
?init();? ? ? ??
?while(1)? ? ??
?{
? for(m=0;m<20;m++)? ?
? sum = adc0832(0)+sum; //將數(shù)模轉(zhuǎn)換得的dat值代入公式
? temp=sum/20; ?//最終結(jié)果(與聲音強(qiáng)弱趨勢相反)??
? if (temp > K_ZERO) ? //在一定程度上消抖降噪
? ? temp = (temp - K_ZERO)/2.0;? ? ? ? ? ? ??
? else
? ? temp= 0;?
? sum=0;? ??
? q=temp/1000;
? r=temp/100;
? k=temp/10;?
? j=temp%10;? ??
? for(numb=0;numb<30;numb++)
? {
? ?display();
? }
?}
}?