• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

PIC16F84A实现非接触式电容触摸感应试验成功

说到电容非接触摸技术相信大家并不陌生......

     由于人体就是导体,通过大地回路形成一个很小的电容.在人体接近感应区域时,人体电容和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);                                         //定时扫描
      }  
}
全部回复(13)
正序查看
倒序查看
2008-08-14 12:11
该版本软件对按键按下,释放的时间进行优化,响应时间更快,在试验时没有出现误动作.......在连续2S没有检测到按键,就自动更新校准参数...实现自动跟踪漂移...在宽电压范围内都可正常工作....欢迎大家进行公测试验.....提供改进建议...
0
回复
nokia1234
LV.3
3
2008-08-14 13:48
@点点滴滴
该版本软件对按键按下,释放的时间进行优化,响应时间更快,在试验时没有出现误动作.......在连续2S没有检测到按键,就自动更新校准参数...实现自动跟踪漂移...在宽电压范围内都可正常工作....欢迎大家进行公测试验.....提供改进建议...
楼主不错,顶起来!!!
0
回复
renad
LV.4
4
2008-08-15 21:06
@点点滴滴
该版本软件对按键按下,释放的时间进行优化,响应时间更快,在试验时没有出现误动作.......在连续2S没有检测到按键,就自动更新校准参数...实现自动跟踪漂移...在宽电压范围内都可正常工作....欢迎大家进行公测试验.....提供改进建议...
我前几天才想到,你应做出来了,比用AD转换的软硬件成本都低.
0
回复
2008-08-16 10:40
强烈要求加精.....
0
回复
2008-08-21 15:16
@点点滴滴
强烈要求加精.....
电源网要是多几个像楼主这样的人就好了,电源网已经颓废了
0
回复
2008-08-22 09:37
@luohongzhi
电源网要是多几个像楼主这样的人就好了,电源网已经颓废了
此帖已被删除
0
回复
whatcall
LV.5
8
2008-08-23 14:01
@点点滴滴
此帖已被删除
君之所叹亦是我之所哀.
缺乏原创力是论坛的最大不足,当然国内技术行业的浮躁心态也是一个重要因素.
0
回复
2008-08-24 19:53
@whatcall
君之所叹亦是我之所哀.缺乏原创力是论坛的最大不足,当然国内技术行业的浮躁心态也是一个重要因素.
这也是电源网里有些人的心态有问题,前几天我说要免费帮人家写个程序,有个疯狗就咬我了,大家看他给我的短信:
fengxz: 2008-08-21 15:08
老兄,你很傻很天真
luohongzhi: 2008-08-21 15:11
我是很傻很天真,比很黄很暴力强多了
fengxz: 2008-08-24 14:05
不知道比我强多少,我觉的一个傻帽和天真的人肯定不怎样,至少这个世界没钱肯定强不了
luohongzhi: 2008-08-24 19:47
你这个狗日的我怎么得罪你了,你他妈的别给你脸不要脸
0
回复
veloce
LV.4
10
2009-03-20 14:21
人才啊,兄弟我佩服的五体投地,如果加上用定时器去读这个值,主程序还可以再处理一些其它功能,这样单片机的功能利用就完全了.

QQ:285730977,TEL:13510917769,方先生,希望多交流.
0
回复
huayuguo
LV.3
11
2009-04-11 08:25
点兄,砸有碰见你了,哈哈.
0
回复
xqtkj
LV.4
12
2009-04-11 16:00
@luohongzhi
这也是电源网里有些人的心态有问题,前几天我说要免费帮人家写个程序,有个疯狗就咬我了,大家看他给我的短信:fengxz:2008-08-2115:08老兄,你很傻很天真luohongzhi:2008-08-2115:11我是很傻很天真,比很黄很暴力强多了fengxz:2008-08-2414:05不知道比我强多少,我觉的一个傻帽和天真的人肯定不怎样,至少这个世界没钱肯定强不了luohongzhi:2008-08-2419:47你这个狗日的我怎么得罪你了,你他妈的别给你脸不要脸
也许你这样做对于他来说是不可思义,因为你免费帮人设计,而他是要钱或者是很多高的报酬才能做,所以他认为你们是天敌……
0
回复
hxdjb
LV.4
13
2009-04-15 13:04
请勿见笑.如何理解端口电容和人体电容的接法.
0
回复
hxdjb
LV.4
14
2009-04-15 13:06
@hxdjb
请勿见笑.如何理解端口电容和人体电容的接法.
忘了发图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/76/147461239771980.jpg');}" onmousewheel="return imgzoom(this);">
0
回复