專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開發(fā)工具、應(yīng)用測試 完善的開發(fā)代碼案例庫分享
從全面的產(chǎn)品導(dǎo)入到強(qiáng)大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無限潛能!
十年專注單片機(jī)方案開發(fā)的方案公司英銳恩,分享PIC16F84A單片機(jī)實(shí)現(xiàn)非接觸式電容觸摸感應(yīng)試驗(yàn)。英銳恩現(xiàn)提供服務(wù)產(chǎn)品涉及主控芯片:8位單片機(jī)、16位單片機(jī)、32位單片機(jī)及各類運(yùn)算放大器等。
說到電容非接觸摸技術(shù)相信大家并不陌生......
由于人體就是導(dǎo)體,通過大地回路形成一個(gè)很小的電容.在人體接近感應(yīng)區(qū)域時(shí),人體電容和IO口內(nèi)部的電容并聯(lián),可以通過RC充電方式測量出這個(gè)電容,在人體沒有接近時(shí),只有IO口內(nèi)部電容,通過軟件處理后可識(shí)別是否有人體接近... 由于電容很小,所以電阻要很大才行,現(xiàn)在這里用4M7的電阻.......
//引入頭文件*********************************************************
#include "delay.h"
#include "delay.c"
#include
//感應(yīng)輸入***********************************************************
#define RcIn RA3 //感應(yīng)輸入
//輸出定義***********************************************************
#define RcSu TRISA3 //方向輸出設(shè)置
//公用變量***********************************************************
unsigned char follow; //跟蹤校準(zhǔn)
//*******************************************************************
//函數(shù)名字; PortInit();
//輸入?yún)?shù); 無
//輸出參數(shù); 無
//功能描述; 端口設(shè)置
//建造日期; 2008年08月14日
//*******************************************************************
void PortInit(void)
{
PORTA = 0x00; //
PORTB = 0x00; //
TRISA = 0xff; //A 口設(shè)置
TRISB = 0x00; //B 口設(shè)置
}
//*******************************************************************
//函數(shù)名字; DischargeOut();
//輸入?yún)?shù); 無
//輸出參數(shù); 無
//功能描述; 電容放電
//建造日期; 2008年08月14日
//*******************************************************************
void DischargeOut(void)
{
RcIn = 1; //置高電平
RcSu = 0; //開始放電
asm("nop"); //放電時(shí)間
asm("nop"); //精確 5uS
asm("nop");
asm("nop");
asm("nop");
}
//*******************************************************************
//函數(shù)名字; SurveyRc();
//輸入?yún)?shù); 無
//輸出參數(shù); 無
//功能描述; 測量充電時(shí)間
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char SurveyRc(void)
{
unsigned char time = 0; //時(shí)間計(jì)數(shù)
DischargeOut(); //電容放電
RcSu = 1; //高阻輸入
while (RcIn) //充電計(jì)時(shí)
{
time++; //計(jì)時(shí)增加
asm("nop"); //精確10uS
if (time > 250) break; //最大限時(shí)
}
return time; //返回時(shí)間
}
//*******************************************************************
//函數(shù)名字; DataAdd(*buffer, size);
//輸入?yún)?shù); 緩沖區(qū)首址, 大小
//輸出參數(shù); 數(shù)據(jù)總和
//功能描述; 緩沖區(qū)所有數(shù)據(jù)相加
//建造日期; 2008年08月14日
//*******************************************************************
unsigned int DataAdd(unsigned char *buffer, unsigned char size)
{
unsigned int add;
unsigned char i;
add = 0; //數(shù)據(jù)清零
for (i = 0; i < size; i++)
{
add += buffer[i]; //數(shù)據(jù)相加
}
return add; //返回總和
}
//*******************************************************************
//函數(shù)名字; DataMax(*buffer, size);
//輸入?yún)?shù); 緩沖區(qū)首址, 大小
//輸出參數(shù); 數(shù)據(jù)最大值
//功能描述; 選出緩沖區(qū)最大值
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char DataMax(unsigned char *buffer, unsigned char size)
{
unsigned char max, i;
max = buffer[0]; //假設(shè)最大
for (i = 1; i < size; i++)
{
if (max < buffer[i]) max = buffer[i]; //對(duì)比最大
}
return max; //最大數(shù)據(jù)
}
//*******************************************************************
//函數(shù)名字; DataMin(*buffer, size);
//輸入?yún)?shù); 緩沖區(qū)首址, 大小
//輸出參數(shù); 數(shù)據(jù)最小大值
//功能描述; 選出緩沖區(qū)最小值
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char DataMin(unsigned char *buffer, unsigned char size)
{
unsigned char min, i;
min = buffer[0]; //假設(shè)最小
for (i = 1; i < size; i++)
{
if (min > buffer[i]) min = buffer[i]; //對(duì)比最小
}
return min; //最小數(shù)據(jù)
}
//*******************************************************************
//函數(shù)名字; DataEqually(idend, isor);
//輸入?yún)?shù); 被除數(shù),除數(shù)
//輸出參數(shù); 平均值
//功能描述; 數(shù)據(jù)平均
//建造日期; 2008年08月14日
//*******************************************************************
unsigned char DataEqually(unsigned int idend, unsigned char isor)
{
return (idend / isor); //數(shù)據(jù)平均
}
//*******************************************************************
//函數(shù)名字; FilterData();
//輸入?yún)?shù); 無
//輸出參數(shù); 平均值
//功能描述; 取樣平均濾波
//建造日期; 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(); //收集數(shù)據(jù)
}
sum = DataAdd(data, 5); //數(shù)據(jù)相加
max = DataMax(data, 5); //取最大值
min = DataMin(data, 5); //取最小值
return (DataEqually((sum - max - min), 3)); //取平均值
}
//*******************************************************************
//函數(shù)名字; KeyState();
//輸入?yún)?shù); 無
//輸出參數(shù); 無
//功能描述; 按鍵處理
//建造日期; 2008年08月14日
//*******************************************************************
void KeyState(void)
{
static unsigned char release = 0; //釋放記數(shù)
static unsigned char count = 0; //按下記數(shù)
static unsigned char valid = 0; //有效標(biāo)志
static unsigned char reach = 0; //長按標(biāo)志
static unsigned char trail = 0; //跟蹤記數(shù)
if (valid == 1) //是否有效
{
if (FilterData() > follow) //按鍵按下
{
release = 0; //釋放清零
if (reach == 0) //長按無效
{
if (++count > 5) //防誤處理
{
reach = 1; //長按置位
PORTB ^= (1 << 7); //取反輸出
}
}
}
else if (++release > 5) //釋放記數(shù)
{
valid = 0; //有效清零
reach = 0; //長按清零
count = 0; //記數(shù)清零
}
}
else
{
if (FilterData() > follow)
{
trail = 0; //數(shù)據(jù)清零
valid = 1; //有效置位
}
else
{
if (++trail > 200) //漂移跟蹤
{
follow = FilterData(); //更新誤差
PORTB ^= (1 << 6); //跟蹤指示
trail = 0; //數(shù)據(jù)清零
}
}
}
}
//*******************************************************************
//函數(shù)名字; main();
//輸入?yún)?shù); 無
//輸出參數(shù); 無
//功能描述; 主程序
//建造日期; 2008年08月14日
//*******************************************************************
void main(void)
{
PortInit(); //端口設(shè)置
follow = FilterData(); //讀取誤差
while (1)
{
KeyState(); //按鍵處理
DelayMs(5); //定時(shí)掃描
}
(文源網(wǎng)絡(luò),侵刪)