由于人体就是导体,通过大地回路形成一个很小的电容.在人体接近感应区域时,人体电容和IO口内部的电容并联,可以通过RC充电方式测量出这个电容,在人体没有接近时,只有IO口内部电容,通过软件处理后可识别是否有人体接近... 由于电容很小,所以电阻要很大才行,现在这里用4M7的电阻.......
那就费话少说.....直接上图...上源代码.....
500) {this.resized=true; this.width=500; this.alt='这是一张缩略图,点击可放大。\n按住CTRL,滚动鼠标滚轮可自由缩放';this.style.cursor='hand'}" onclick="if(!this.resized) {return true;} else {window.open('http://u.dianyuan.com/bbs/u/68/1073571218686947.jpg?x-oss-process=image/watermark,g_center,image_YXJ0aWNsZS9wdWJsaWMvd2F0ZXJtYXJrLnBuZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxQXzQwCg,t_20');}" onmousewheel="return imgzoom(this);">500) {this.resized=true; this.width=500; this.alt='这是一张缩略图,点击可放大。\n按住CTRL,滚动鼠标滚轮可自由缩放';this.style.cursor='hand'}" onclick="if(!this.resized) {return true;} else {window.open('http://u.dianyuan.com/bbs/u/68/1073571218686954.jpg?x-oss-process=image/watermark,g_center,image_YXJ0aWNsZS9wdWJsaWMvd2F0ZXJtYXJrLnBuZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxQXzQwCg,t_20');}" onmousewheel="return imgzoom(this);">500) {this.resized=true; this.width=500; this.alt='这是一张缩略图,点击可放大。\n按住CTRL,滚动鼠标滚轮可自由缩放';this.style.cursor='hand'}" onclick="if(!this.resized) {return true;} else {window.open('http://u.dianyuan.com/bbs/u/68/1073571218686963.jpg?x-oss-process=image/watermark,g_center,image_YXJ0aWNsZS9wdWJsaWMvd2F0ZXJtYXJrLnBuZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxQXzQwCg,t_20');}" onmousewheel="return imgzoom(this);">500) {this.resized=true; this.width=500; this.alt='这是一张缩略图,点击可放大。\n按住CTRL,滚动鼠标滚轮可自由缩放';this.style.cursor='hand'}" onclick="if(!this.resized) {return true;} else {window.open('http://u.dianyuan.com/bbs/u/68/1073571218686971.jpg?x-oss-process=image/watermark,g_center,image_YXJ0aWNsZS9wdWJsaWMvd2F0ZXJtYXJrLnBuZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxQXzQwCg,t_20');}" onmousewheel="return imgzoom(this);"> 1073571218686981.rar
//引入头文件*********************************************************
#include "delay.h"
#include "delay.c"
#include
//感应输入***********************************************************
#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); //定时扫描
}
}