|
说到电容非接触摸技术相信大家并不陌生......
前几天在书城看到匠人的手记.....里面看到这样一个描述用普通IO口加一个电阻实现电容感应的方案...只是大概描述..回来后经过自己分析...由于人体就是导体,通过大地回路形成一个很小的电容.在人体接近感应区域时,人体电容和IO口内部的电容并联,可以通过RC充电方式测量出这个电容,在人体没有接近时,只有IO口内部电容,通过软件处理后可识别是否有人体接近... 由于电容很小,所以电阻要很大才行,现在这里用20M的电阻.......
经过软件仿真.电压5V 电阻20M 测得
电容 = 1P 充电时间大约为 20US
电容 = 5P 充电时间大约为 100US
电容 = 10P 充电时间大约为 200US
电容 = 25P 充电时间大约为 1750US
那就费话少说.....直接上图...上源代码.....
(原文件名:电容感应1.jpg)
(原文件名:电容感应2.JPG)
(原文件名:电容感应3.JPG)
(原文件名:电容感应4.JPG)
(原文件名:电容感应5.JPG)
//引用文件***********************************************************
#include<iom8v.h>
#include<macros.h>
//输出定义***********************************************************
#define Led1On PORTD |= (1 << 7) //输出指示
#define Led1Off PORTD &= ~(1 << 7) //关闭指示
//*******************************************************************
//函数名字; Delay1Ms();
//输入参数; 无
//输出参数; 无
//功能描述; 延时1 毫秒
//建造日期; 2008年08月09日
//*******************************************************************
void Delay1Ms(void) //毫秒延时
{
unsigned int i;
for (i = 0; i < 140; i++); //
}
//*******************************************************************
//函数名字; DelayNms(n);
//输入参数; 延时周期参数据
//输出参数; 无
//功能描述; 延时程序
//建造日期; 2008年08月09日
//*******************************************************************
void DelayNms(unsigned int n) //延时周期
{
unsigned int i;
for (i = 0; i < n; i++)
{
Delay1Ms(); //毫秒延时
}
}
//*******************************************************************
//函数名字; PortInit();
//输入参数; 无
//输出参数; 无
//功能描述; 脚位设置
//建造日期;2008年08月09日
//*******************************************************************
void PortInit(void)
{
PORTB = 0xff; //控制输出
DDRB = 0x07;
PORTC = 0x6f; //上拉输入
DDRC = 0x08;
PORTD = 0x00; //控制输出
DDRD = 0xff;
}
//*******************************************************************
//函数名字; DischargeOut();
//输入参数; 无
//输出参数; 无
//功能描述; 电容放电
//建造日期; 2008年08月09日
//*******************************************************************
void DischargeOut(void)
{
PORTC |= (1 << 4); //置高电平
DDRC |= (1 << 4); //开始放电
DelayNms(1); //放电时间
}
//*******************************************************************
//函数名字; SurveyRc();
//输入参数; 无
//输出参数; 无
//功能描述; 测量充电时间
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char SurveyRc(void)
{
unsigned char time = 0; //时间计数
DischargeOut(); //电容放电
DDRC &= ~(1 << 4); //输入设置
PORTC &= ~(1 << 4); //高阻输入
while (PINC & (1 << 4)) //充电计时
{
time++; //计时增加
asm("nop"); //精确10us
if (time > 250) break; //最大限时
}
return time; //返回时间
}
//*******************************************************************
//函数名字; DataAdd(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据总和
//功能描述; 缓冲区所有数据相加
//建造日期; 2008年08月09日
//*******************************************************************
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; //数据相加
}
return add; //返回总和
}
//*******************************************************************
//函数名字; DataMax(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最大值
//功能描述; 选出缓冲区最大值
//建造日期; 2008年08月09日
//*******************************************************************
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) max = buffer; //对比最大
}
return max; //最大数据
}
//*******************************************************************
//函数名字; DataMin(*buffer, size);
//输入参数; 缓冲区首址, 大小
//输出参数; 数据最小大值
//功能描述; 选出缓冲区最小值
//建造日期; 2008年08月09日
//*******************************************************************
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) min = buffer; //对比最小
}
return min; //最小数据
}
//*******************************************************************
//函数名字; DataEqually(idend, isor);
//输入参数; 被除数,除数
//输出参数; 平均值
//功能描述; 数据平均
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char DataEqually(unsigned int idend, unsigned char isor)
{
return (idend / isor); //数据平均
}
//*******************************************************************
//函数名字; FilterData();
//输入参数; 无
//输出参数; 平均值
//功能描述; 取样平均滤波
//建造日期; 2008年08月09日
//*******************************************************************
unsigned char FilterData(void)
{
unsigned char i, max, min, data[10];
unsigned int sum;
for (i = 0; i < 10; i++)
{
data = SurveyRc(); //收集数据
}
sum = DataAdd(data, 10); //数据相加
max = DataMax(data, 10); //取最大值
min = DataMin(data, 10); //取最小值
return (DataEqually((sum - max - min), 8)); //取平均值
}
//*******************************************************************
//函数名字; main();
//输入参数; 无
//输出参数; 无
//功能描述; 主程序
//建造日期; 2008年08月09日
//*******************************************************************
void main(void)
{
unsigned char temp = 0; //上电校准
unsigned char time = 0;
PortInit(); //端口设置
temp = FilterData(); //读取误差
while (1)
{
time = FilterData(); //读取时间
if (time > temp)
{
Led1On; //输出指示
}
else
{
Led1Off; //关闭指示
}
}
} |
|