本版名称: 【PIC单片机】

版       主: 芝锐

收藏本版 | 写博客 | 我的所有文章

收藏 订阅 推荐 打印

[原创文章] PIC16F690做电容式触摸按键

PIC16F690做电容式触摸按键

 

设计参考了应用笔记AN1101-1104;


使用串口通信来读取振荡频率,通过读取没有按下和按下按键的不同频率来确定阀值。


程序运行中也可读取每个按键通道的没有触摸时的1/16平均值,通道的扫描时间为10ms循环。


 


配置字是,__CONFIG (0x3BC4);


#include<pic.h>
#define uchar unsigned char
#define uint unsigned int
uchar COMP1[]={0x94,0x95,0x96,0x97};//按键通道切换
uchar COMP2[]={0xa0,0xa1,0xa2,0xa3};//按键通道切换
uint average[]={0,0,0,0};//按键振荡计数平均值
uint trip[]={400,400,250,320};//按键振荡计数阀值
uchar ltmr1,htmr1;//计时器1的高8位和低8位暂存
uint raw;//16位传感器当前振荡计数值
uchar index=0; //按键标号
uchar keya,keyb,keyc,keyd; //按键状态
//-----------------------------
uchar usdata=0;//串口发送数据端口号
uchar rbuff; //接收缓存
uchar a1,a2,a3,a4,a5;
void init();//初始化配置
void usart();//串口通信
void touchkey();//按键判断
void main()
{
 init();//初始化配置
 while(1)
 { 
  usart();//串口通信
  touchkey();//按键判断
 }
}
void interrupt intcon()
{
 if((T0IF)&&(T0IE))
 {
  T0IF=0;
  //进入中断时,10ms读取tmr1的计数值
  htmr1=TMR1H; //读取计数器高8位       
  ltmr1=TMR1L;//读取计数器低8位
  raw=raw|htmr1;
  raw=(raw<<8)|ltmr1;
  // 按钮判断并置位按钮状态
  if(raw<((long)average[index]-(long)trip[index]))
  {
   switch(index)
   {
    case 0:  keya=1; break;
    case 1:  keyb=1; break;
    case 2:  keyc=1; break;
    case 3:  keyd=1; break;
    default:   break;
   }
  }
  // 按钮判断并置位按钮状态滞后量选200
  else if(raw>((long)average[index]-(long)trip[index]+150))
  {
   switch(index)
   {
    case 0:  keya=0; break;
    case 1:  keyb=0; break;
    case 2:  keyc=0; break;
    case 3:  keyd=0; break;
    default:   break;
   }
   //求平均值
   average[index]=average[index]+((long)raw-(long)average[index])/16; 
  }
  //按键通道切换每10ms切换
  index=(++index)&0x03;
  CM1CON0=COMP1[index];
  CM2CON0=COMP2[index];  
  //清零寄存器为扫描下一通道准备
  raw=0;
  ltmr1=0;
  htmr1=0;
  TMR0=100;
  TMR1H=0;
  TMR1L=0;
 }
 if((TMR1IF)&&(TMR1IE))
 {
  TMR1IF=0;
  TMR1H=0;
  TMR1L=0;   
 }


 if((RCIE)&&(RCIF))
 {
  rbuff=RCREG;//读取接收缓存的数据
  if(OERR==1)
  {
   CREN=0;
   asm("nop");
   CREN=1;
  }
/*  TXEN=1; //打开发送使能
  TXREG=rbuff;//把接收到的数据送到发送缓存
  while(!TRMT);//等待发送完成
  TXEN=0; //关闭发送使能
*/
 }
}
//*********初始化配置****************
void init()
{
 OSCCON=0x70; //振荡器控制寄存器
 GIE=1;//总中断开
 PEIE=1;
//------定时器0的配置----
 OPTION=0x86; //选项寄存器配置
 T0IF=0;//请定时器零中断标志位
 T0IE=1;//开定时器零中断
 TMR0=100;
//----------------------
//------计数器1的配置--------
 T1CON=0x07;
 TMR1IF=0;
 TMR1IE=1;
 TMR1H=0;
 TMR1L=0;
//---------------------------
//-------比较器的配置--------
 CM1CON0=0x94;
 CM2CON0=0xa0;
 VRCON=0xcd;
 SRCON=0xf0;
 CM2CON1=0x02;
//---------------------------
//---------USART的配置-------
 TXSTA=0x0c;//发送状态寄存器设置(暂时关闭要发时再开)
 RCSTA=0x90;//接收状态寄存器控制
 BAUDCTL=0x80;//波特率控制
 SPBRG=51;//波特率9600
 SPBRGH=0x00;//波特率9600
 RCIE=1; //接收中断打开
 TXIE=0; //发送中断关闭
//---------------------------
//-----IO口的配置-------
 ANSEL=0xf2;// |设为数字IO口
 ANSELH=0x00;//|
 TRISA=0x22;
 PORTA=0x00;
 TRISB=0x20;
 PORTB=0x00;
 TRISC=0x0f;
 PORTC=0x00;
 RA0=1;
}
//**********USART**************
void usart()
{
 if(rbuff==0x74)
 {
  //------------------------
   a1=usdata/10000;
   a2=usdata%10000/1000;
   a3=usdata%1000/100;
   a4=usdata%100/10;
   a5=usdata%10;
   a1=a1|0x30;
   a2=a2|0x30;
   a3=a3|0x30;
   a4=a4|0x30;
   a5=a5|0x30;
  //------------------------


   TXEN=1; //打开发送使能
   TXREG=a1;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a2;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a3;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a4;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a5;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXEN=0; //关闭发送使能
   rbuff=0; 
 }
 if(rbuff==0x72)
 {
  //------------------------
   a1=average[usdata]/10000;
   a2=average[usdata]%10000/1000;
   a3=average[usdata]%1000/100;
   a4=average[usdata]%100/10;
   a5=average[usdata]%10;
   a1=a1|0x30;
   a2=a2|0x30;
   a3=a3|0x30;
   a4=a4|0x30;
   a5=a5|0x30;
  //------------------------


   TXEN=1; //打开发送使能
   TXREG=a1;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a2;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a3;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a4;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXREG=a5;//把接收到的数据送到发送缓存
   while(!TRMT);//等待发送完成
   TXEN=0; //关闭发送使能
   rbuff=0; 
 }
 if(rbuff==0x30)
 {
  usdata=0;
  rbuff=0;
 }
 if(rbuff==0x31)
 {
  usdata=1;
  rbuff=0;
 }
 if(rbuff==0x32)
 {
  usdata=2;
  rbuff=0;
 }
 if(rbuff==0x33)
 {
  usdata=3;
  rbuff=0;
 }
}
//***************************
//------按键判断
void touchkey()
{
 if(keya==1)
 {
  RA2=1;
  RA4=0;
  RB4=0;
  RB6=1;
  RC5=1;
  RC6=1;
  RC7=1; 
 }
 if(keyb==1)
 {
  RA2=0;
  RA4=0;
  RB4=1;
  RB6=0;
  RC5=0;
  RC6=1;
  RC7=0;
 }
 if(keyc==1)
 {
  RA2=0;
  RA4=0;
  RB4=0;
  RB6=0;
  RC5=1;
  RC6=1;
  RC7=0;
 }
 if(keyd==1)
 {
  RA2=1;
  RA4=0;
  RB4=0;
  RB6=1;
  RC5=1;
  RC6=0;
  RC7=0;
 }  
}



[本帖最后由 QQ175744595 于 2012-2-3 10:28 编辑 ]

附件

 EEWORLD提示:为减少服务器的压力,请尽量不要使用迅雷等下载软件。
showimg.jpg (167.88 KB)

2012-2-3 10:17

PIC16F690做电容式触摸按键

showimg.jpg

01102A_CN.pdf (487.88 KB)

2012-2-3 10:27, 下载次数: 29
, 售价: 芯币 1 枚  [记录]

01103A_CN.pdf (510.69 KB)

2012-2-3 10:27, 下载次数: 28
, 售价: 芯币 1 枚  [记录]

01104A_CN.pdf (346.46 KB)

2012-2-3 10:27, 下载次数: 24
, 售价: 芯币 1 枚  [记录]

电容式触摸按键(简介).pdf (438.19 KB)

2012-2-3 10:27, 下载次数: 49
, 售价: 芯币 1 枚  [记录]

回复 |  引用 |  评分 |  建议精华 |  建议删除 |  道具 TOP↑

有原理图不?

回复 |  引用 |  评分 |  建议精华 |  建议删除 |  道具 TOP↑

相关链接

查看积分策略说明

快速回复主题

内容

[完成后可按 Ctrl+Enter 发布]  预览帖子 恢复数据  清空内容

更多>>社区最新活动

24小时排行榜

G億僀儞僩億僀妶Amazon Yahoo 妝揤

柍椏儂乕儉儁乕僕 妝揤儌僶僀儖[UNLIMIT偑崱側傜1墌] 奀奜奿埨峲嬻寯 奀奜椃峴曐尟偑柍椏両