|
/script> 說到電容非接觸摸技術相信大家并不陌生...... 由于人體就是導體,通過大地回路形成一個很小的電容.在人體接近感應區域時,人體電容和IO口內部的電容并聯,可以通過RC充電方式測量出這個電容,在人體沒有接近時,只有IO口內部電容,通過軟件處理后可識別是否有人體接近... 由于電容很小,所以電阻要很大才行,現在這里用4M7的電阻.......
那就費話少說.....直接上圖...上源代碼..... 此主題相關圖片如下:
此主題相關圖片如下:
此主題相關圖片如下:
此主題相關圖片如下:
//引入頭文件********************************************************* #include "delay.h" #include "delay.c" #include <pic1684.h> //感應輸入*********************************************************** #define RcIn RA3 //感應輸入 //輸出定義*********************************************************** #define RcSu TRISA3 //方向輸出設置 //公用變量*********************************************************** unsigned char follow; //跟蹤校準 //******************************************************************* //函數名字; PortInit(); //輸入參數; 無 //輸出參數; 無 //功能描述; 端口設置 //建造日期; 2008年08月14日 //******************************************************************* void PortInit(void) { PORTA = 0x00; // PORTB = 0x00; // TRISA = 0xff; //A 口設置 TRISB = 0x00; //B 口設置 } //******************************************************************* //函數名字; DischargeOut(); //輸入參數; 無 //輸出參數; 無 //功能描述; 電容放電 //建造日期; 2008年08月14日 //******************************************************************* void DischargeOut(void) { RcIn = 1; //置高電平 RcSu = 0; //開始放電 asm("nop"); //放電時間 asm("nop"); //精確 5uS asm("nop"); asm("nop"); asm("nop"); } //******************************************************************* //函數名字; SurveyRc(); //輸入參數; 無 //輸出參數; 無 //功能描述; 測量充電時間 //建造日期; 2008年08月14日 //******************************************************************* unsigned char SurveyRc(void) { unsigned char time = 0; //時間計數 DischargeOut(); //電容放電 RcSu = 1; //高阻輸入 while (RcIn) //充電計時 { time++; //計時增加 asm("nop"); //精確10uS if (time > 250) break; //最大限時 } return time; //返回時間 } //******************************************************************* //函數名字; DataAdd(*buffer, size); //輸入參數; 緩沖區首址, 大小 //輸出參數; 數據總和 //功能描述; 緩沖區所有數據相加 //建造日期; 2008年08月14日 //******************************************************************* unsigned int DataAdd(unsigned char *buffer, unsigned char size) { unsigned int add; unsigned char i; add = 0; //數據清零 for (i = 0; i < size; i++) { add += buffer[i]; //數據相加 } return add; //返回總和 } //******************************************************************* //函數名字; DataMax(*buffer, size); //輸入參數; 緩沖區首址, 大小 //輸出參數; 數據最大值 //功能描述; 選出緩沖區最大值 //建造日期; 2008年08月14日 //******************************************************************* unsigned char DataMax(unsigned char *buffer, unsigned char size) { unsigned char max, i; max = buffer[0]; //假設最大 for (i = 1; i < size; i++) { if (max < buffer[i]) max = buffer[i]; //對比最大 } return max; //最大數據 } //******************************************************************* //函數名字; DataMin(*buffer, size); //輸入參數; 緩沖區首址, 大小 //輸出參數; 數據最小大值 //功能描述; 選出緩沖區最小值 //建造日期; 2008年08月14日 //******************************************************************* unsigned char DataMin(unsigned char *buffer, unsigned char size) { unsigned char min, i; min = buffer[0]; //假設最小 for (i = 1; i < size; i++) { if (min > buffer[i]) min = buffer[i]; //對比最小 } return min; //最小數據 } //******************************************************************* //函數名字; DataEqually(idend, isor); //輸入參數; 被除數,除數 //輸出參數; 平均值 //功能描述; 數據平均 //建造日期; 2008年08月14日 //******************************************************************* unsigned char DataEqually(unsigned int idend, unsigned char isor) { return (idend / isor); //數據平均 } //******************************************************************* //函數名字; FilterData(); //輸入參數; 無 //輸出參數; 平均值 //功能描述; 取樣平均濾波 //建造日期; 2008年08月14日 //******************************************************************* unsigned char FilterData(void) { unsigned char i, max, min, data[5]; unsigned int sum; for (i = 0; i < 5; i++) { data[i] = SurveyRc(); //收集數據 } sum = DataAdd(data, 5); //數據相加 max = DataMax(data, 5); //取最大值 min = DataMin(data, 5); //取最小值 return (DataEqually((sum - max - min), 3)); //取平均值 } //******************************************************************* //函數名字; KeyState(); //輸入參數; 無 //輸出參數; 無 //功能描述; 按鍵處理 //建造日期; 2008年08月14日 //******************************************************************* void KeyState(void) { static unsigned char release = 0; //釋放記數 static unsigned char count = 0; //按下記數 static unsigned char valid = 0; //有效標志 static unsigned char reach = 0; //長按標志 static unsigned char trail = 0; //跟蹤記數 if (valid == 1) //是否有效 { if (FilterData() > follow) //按鍵按下 { release = 0; //釋放清零 if (reach == 0) //長按無效 { if (++count > 5) //防誤處理 { reach = 1; //長按置位 PORTB ^= (1 << 7); //取反輸出 } } } else if (++release > 5) //釋放記數 { valid = 0; //有效清零 reach = 0; //長按清零 count = 0; //記數清零 } } else { if (FilterData() > follow) { trail = 0; //數據清零 valid = 1; //有效置位 } else { if (++trail > 200) //漂移跟蹤 { follow = FilterData(); //更新誤差 PORTB ^= (1 << 6); //跟蹤指示 trail = 0; //數據清零 } } } } //******************************************************************* //函數名字; main(); //輸入參數; 無 //輸出參數; 無 //功能描述; 主程序 //建造日期; 2008年08月14日 //******************************************************************* void main(void) { PortInit(); //端口設置 follow = FilterData(); //讀取誤差 while (1) { KeyState(); //按鍵處理 DelayMs(5); //定時掃描 } } |