❶ 求:c語言數字濾波器;要求:1Khz低通;20個數x0,x1,x2----x19;結果y0---y19
1,低通濾波器傳函k*f^2/(s^2+s*f/Q+f^2),確定你的電壓增壓k和品質因數,還有截止頻率f。我就以f=1k,q=0.707,k=1為例。
2,進行離散化。離散化方法以雙線性變換為例。。。。然後得到Transfer function:
1.039e-005 z + 6.53e-006
------------------------
z^2 - 1.243 z + 0.2431
Sampling time: 0.001
3,然後就改寫成差分方程。。。。把z^(-n)中的(-n)寫成(k-n)即可。自己移相試試 就知道了。
❷ 誰有pulsesensor心率感測器 的c語言程序,帶注釋的。在線等挺急的
這個是主程序和部分代碼由於字數限制所以你還是留個郵箱吧
void main(void)
{
unsigned char i;
sys_init();
beep = 1;
LCD12864_DisplayOneLine(0x80,ucStr1); //顯示信息1
LCD12864_DisplayOneLine(0x90,ucStr2); //顯示信息2
LCD12864_DisplayOneLine(0x88,ucStr3); //顯示信息3
LCD12864_DisplayOneLine(0x98,ucStr4); //顯示信息4
while(1)
{
sendDataToProcessing('S', Signal); // 發送並處理原始脈搏感測器數據
if (QS == true){ // 確定發現一個心跳
fadeRate = 255; // Set 'fadeRate' Variable to 255 to fade LED with pulse
sendDataToProcessing('B',BPM); // 發送一個'B'和心率
sendDataToProcessing('Q',IBI); // send time between beats with a 'Q' prefix
QS = false; // reset the Quantified Self flag for next time
LCD_disp_list_char(2,4,DisBuff);//在LCD12864上顯示BPM
}
delay(138); // 延時 19.6ms
LCD_disp_list_char(4,4,DisBuff2);
//ledFadeToBeat();
if(Pressure<100){
for(i=0;i<8;i++){
delay(1000);}
if (Pressure<100){
beep = 0;}}
if(BPM<60|BPM>100){
for(i=0;i<9;i++){
delay(1000);}
if(BPM<60|BPM>100){
beep = 0;}
for(i = 0;i<16;i++) //依次執行寫入操作
{
putchar(ucStr1[i]);
}
for(i = 0;i<16;i++) //依次執行寫入操作
{
putchar(ucStr2[i]);
}
for(i=0;i<3;i++)
{
putchar(DisBuff[i]);}
for(i = 0;i<16;i++) //依次執行寫入操作
{
putchar(ucStr3[i]);
}
for(i = 0;i<16;i++) //依次執行寫入操作
{
putchar(ucStr4[i]);
}
for(i=0;i<4;i++)
{
putchar(DisBuff2[i]);}
}
}
//void ledFadeToBeat(){
// fadeRate -= 15; // set LED fade value
// fadeRate = constrain(fadeRate,0,255); // keep LED fade value from going into negative numbers!
// analogWrite(fadePin,fadeRate); // fade LED
// }
/******************************************************************************
函數名稱:GetADCResult
函數功能:獲取AD轉換結果函數
入口參數:BYTE ch(通道選擇)
返回值:result(A/D轉換結果)
備註:無
*******************************************************************************/
unsigned int GetADCResult(BYTE ch)
{ unsigned int result; //AD轉換結果result
ADC_CONTR&=0xf8; //清除ADC控制寄存器ADC CONTR的CHS2、CHS1、CHS0(清除通道選擇)
_nop_(); //設置ADC CONTR控制寄存器後,要加4個空操作延時才可以正確讀到ADC CONTR寄存器的值
_nop_();
_nop_();
_nop_();
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START; //開ADC電源,選擇AD轉換速率,並選擇AD通道,開始AD轉換
_nop_(); //設置ADC CONTR控制寄存器後,要加4個空操作延時才可以正確讀到ADC CONTR寄存器的值
_nop_();
_nop_();
_nop_();
while (!(ADC_CONTR & ADC_FLAG));//等待AD轉換結束
ADC_CONTR &= ~ADC_FLAG; //關閉ADC
result=ADC_RES; //將AD轉換結果的高兩位賦給result
result=result<<8; //將result循環左移8位
result+=ADC_RESL; //將AD轉換結果的底8位加高兩位共10位給result
return result; //返回10位AD轉換結果
}
void sendDataToProcessing(char symbol, int dat ){
putchar(symbol); // symbol prefix tells Processing what type of data is coming
printf("%d\r\n",dat); // the data to send culminating in a carriage return
}
void UART_init(void)
{
TMOD = 0x20; //定時器工作在定時器1的方式2
PCON = 0x00; //不倍頻
SCON = 0x50; //串口工作在方式1,並且啟動串列接收
TH1 = 0xFd; //設置波特率 9600
TL1 = 0xFd;
TR1 = 1; //啟動定時器1
}
char putchar(unsigned char dat)
{
TI=0;
SBUF=dat;
while(!TI);
TI=0;
return SBUF;
}
void _nop_ (void)
{}
void T0_init(void){
// Initializes Timer0 to throw an interrupt every 2mS.
TMOD |= 0x01; //16bit TIMER
TL0=T0MS;
TH0=T0MS>>8;
TR0=1; //start Timer 0
ET0=1; //enable Timer Interrupt
EA=1; // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED
}
void T1_init(void){
// Initializes Timer0 to throw an interrupt every 2mS.
TMOD |= 0x01; //16bit TIMER
TL1=T0MS2;
TH1=T0MS2>>8;
TR1=1; //start Timer 0
ET1=1; //enable Timer Interrupt
EA=1; // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED
}
void ADC_init(unsigned char channel)
{
P1ASF=ADC_MASK<<channel; //選擇P1. channel作為A/D輸入來用
ADC_RES=0; //清除ADC結果寄存器RES
ADC_RESL=0; //清除ADC結果寄存器RESL
AUXR1 |= 0x04; //調整ADC格式的結果
}
void Timer1_rountine(void) interrupt 1
{}
unsigned int analogRead(unsigned char channel)
{
unsigned int result;
while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
ADC_CONTR &=!ADC_FLAG; //clear ADC FLAG
result=ADC_RES;
result=result<<8;
result+=ADC_RESL;
// ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
return result;
}
// Timer 0中斷子程序,每2MS中斷一次,讀取AD值,計算心率值
void Timer0_rountine(void) interrupt 1
{
int N;
unsigned char i;
// keep a running total of the last 10 IBI values
unsigned int runningTotal = 0; // clear the runningTotal variable
EA=0; // 關定時器中斷
TL0=T0MS;
TH0=T0MS>>8; //重裝16位定時器初值
Pressure = (GetADCResult(PressurePin)); //****************
DisBuff2[3] = Pressure%10+48;//取個位數
DisBuff2[2] = Pressure%100/10+48; //取十位數
DisBuff2[1] = Pressure%1000/100+48; //百位數 ***************
DisBuff2[0] = Pressure/1000+48;//取千位數
Signal = GetADCResult(PulsePin); // 讀脈搏感測器
sampleCounter += 2; // 使用這個值跟蹤記錄脈搏時間間隔在ms級
N = sampleCounter - lastBeatTime; // 減上個節拍的時間來避免雜訊
// 找到脈搏波的波峰和波谷
if(Signal < thresh && N > (IBI/5)*3){ // 如果脈搏感測器輸出小於電源電壓一半 並且 消除雜訊時間小於 3/5個脈搏時間間隔
if (Signal < Trough){ // 如果脈搏感測器輸出小於波谷
Trough = Signal; // 跟蹤脈搏波的最低點
}
}
if(Signal > thresh && Signal > Peak){ // 如果輸出大於電源電壓一半並且大於波峰
Peak = Signal; // 將新值設為波峰
} // 跟蹤脈搏波的波峰
if (N > 250){ // 避免高頻雜訊
if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){
Pulse = true; // 當檢測到一個脈搏時將脈搏標志設為真
blinkPin=0; // 點亮脈搏燈
IBI = sampleCounter - lastBeatTime; // 測量兩個脈搏的時間in mS
lastBeatTime = sampleCounter; // 跟蹤脈搏時間
if(secondBeat){ // 如果這是第二個脈搏
secondBeat = false; // 清除標識
for(i=0; i<=9; i++){ // 全部的數據作為真實脈搏BMP
rate[i] = IBI;
}
}
if(firstBeat){ // 如果是第一個脈搏
firstBeat = false; // 清除標志
secondBeat = true; // 設置第二脈搏標志
EA=1; //開中斷
return; // IBI 值是不可靠的所以拋棄
}
for(i=0; i<=8; i++){ // 移動數據在rate數組中
rate[i] = rate[i+1]; // 頂替舊值
runningTotal += rate[i]; // 加上第九個新值
}
rate[9] = IBI; // 加最後的IBI到rate數組中
runningTotal += rate[9]; // 加上一個IBI到runningTotal
runningTotal /= 10; // 取平均值
BPM = 60000/runningTotal; // 一分鍾可以檢測到多少個心跳及 BPM!
if(BPM>200)BPM=200; //限制BPM最高顯示值
if(BPM<30)BPM=30; //限制BPM最低顯示值
DisBuff[2] = BPM%10+48;//取個位數
DisBuff[1] = BPM%100/10+48; //取十位數
DisBuff[0] = BPM/100+48; //百位數
if(DisBuff[0]==48)
DisBuff[0]=32;
QS = true; // 設置QS標志
// QS FLAG IS NOT CLEARED INSIDE THIS ISR
}
}
if (Signal < thresh && Pulse == true){ // 當電壓歸零節拍結束
blinkPin=1; // 熄滅脈搏燈
Pulse = false; // 重置脈搏標識我們可以重新測
amp = Peak - Trough; // 得到脈搏波的峰峰值
thresh = amp/2 + Trough; // 設置thresh位脈搏峰峰值的一半
Peak = thresh; // 為下一次測試重置波峰
Trough = thresh;
}
if (N > 2500){ //如果超過2.5秒沒有檢測到一個脈搏
thresh = 512; // 重新設置波谷
Peak = 512; // 重新設置波峰
Trough = 512; // 重新設置間隔
lastBeatTime = sampleCounter; // 把最後的節拍時間更新
firstBeat = true; // 重新設置標志避免雜訊
secondBeat = false; // 當我們得到心跳的時候
}
EA=1; // 開中斷
}// end isr
❸ 脈搏計數器的程序(用C語言編寫程序)
#include <reg51.h>
unsigned char i,j,t,m,DelayTime,DispBuf[3];
unsigned int n,mb;
unsigned char code
BitTab[3]={0xf7,0xef,0xdf};//位驅動碼
unsigned char code
DispTab[10]={0x81,0xcf,0x92,0x86,0xcc,0xa4,0xa0,0x8f,0x80,0x84};//字形碼
sbit P3_0=P3^0;
void delay(DelayTime);
main() //主程序
{
TMOD=0x01; //定時器T0工作於方式1
TH0=0xec;
TL0=0x78; //T0定時時間為5ms
IE=0X83; //開中斷
IT0=1; //外部中斷0為邊沿觸發方式
TR0=1; //開定時器T0
for(;;) //脈搏指示燈控制
{
if(P3_0==0)
{
delay(200);
P3_0=1;
}
}
}
external0() interrupt 0//外部中斷服務程序
{
P3_0=0; //點亮指示燈
if(n==0)
mb=0;
else
mb=12000/n; //計算每分鍾脈搏數
DispBuf[2]=mb%10;//取個位數
mb=mb/10;
DispBuf[1]=mb%10;//取十位數
DispBuf[0]=mb/10;//取百位數
n=0;
}
Timer0() interrupt 1//定時中斷服務程序
{
TH0=0xec;
TL0=0x78;
t=BitTab[j];//取位值
P3=P3|0x38;//P3.3-P3.5送1
P3=P3&t; //P3.3-P3.5輸出取出的位值
t=DispBuf[j];//取出待顯示的數
t=DispTab[t];//取字形碼
P1=t; //字型碼由P3輸出顯示
j++; //j作為數碼管的計數器,取值0-2,顯示程序通過它確認顯示哪個數碼管
if(j==3)
j=0;
n++;
if(n==2000)//10秒鍾測不到心率,n復位
n=0;
}
void delay(DelayTime)//延時子程序
{
for(;DelayTime>0;DelayTime--)
{
for(i=0;i<250;i++)
;
}
}