PIC单片机 电容式触摸检测
目录
- ADC触摸检测原理
- ADC的使用
- 触摸检测程序设计
ADC触摸检测原理
ADC内部电容Chold与外部引脚所接电容Csensor并联,等效电容为二者之和。首先将内部电容Chold充电,将外接电容Csensor放电,然后连接二者,将二者电荷量Q保持为恒定值。根据电容公式 Q = CU 可知,当手触摸外部电容Csensor导致其电容增大时,等效电容随之增大,而电荷量Q恒定所以电压U下降。测量得出触摸与未触摸时电压的阈值后就可以根据电压变化来判断是否触摸。
ADC的使用
1、引脚PORT配置
TRISx寄存器控制引脚数据传输方向,ANSELx寄存器控制引脚数据类型为模拟信号还是数字信号。
2、CHANNEL 选择
ADPCH寄存器决定channel。
注意,在改变channel后要delay一会儿才能开始下一次转换。
3、选取参考电压
ADREF的ADPREF位选择正参考电压,ADREF的ADNREF位选择负参考电位。
4、CLOCK 选择
通过ADCON0寄存器的ADCS位和ADCLK寄存器来选择。
5、输出格式控制
ADC转换结果保存为10bit数据存入ADRES,有两种对齐方式,ADCON0的ADFRM0位决定result的左 / 右对齐。
6、开启ADC
把ADCON0的ADON位置1
7、预充电和采样
只有外接电容,使用CVD方法实现触摸检测时才进行预充电,作用是对Chold和Csensor充/放电,但是仅仅是进行AD转换则不需要预充电。可通过ADPRE寄存器控制预充电时长。采样是在AD转换之前进行的,时长由ADACQ寄存器设置。必须等待采样结束才能开始AD转换。
8、开启AD转换
把ADCON0的ADGO位置1时开启AD转换,转换结束时ADGO自动清0。应当循环或者定时判断ADGO是否等于0,重复开启AD转换。
9、读取结果
AD转换结果保存在ADRES0L和ADRES0H寄存器,对齐方式在上面已提到。
触摸检测程序设计
实现效果:
按下按键,4位数码管<2:0>显示“YES”,未按下时显示“NO”;数码管<3>显示按下次数,最多记到16次;按下按键时LED灯闪亮。
引脚使用:
PORTA<3:0>为数码管片选位,PORTC<7:0>为数码管段选位;PORTB<7>为LED灯位。
设计思路:
ADC模块循环预充电、采样、AD转换,获取电压变化并与阈值比较判断是否触摸;定时器5ms中断一次,判断ADC是否转换完成,计数并把ADRES中的转换结果同步到数码管的显示缓冲区,随后再次预充电、采样并开启AD转换。
基于PIC16F18854单片机的cC语言源代码:
#include <xc.h>
#ifndef BOOTLOADER//配置段// PIC16F18854 Configuration Bit Settings// 'C' source line config statements// CONFIG1
#pragma config FEXTOSC = OFF // External Oscillator mode selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINT1 // Power-up default value for COSC bits (HFINTOSC (1MHz))
#pragma config CLKOUTEN = OFF // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = ON // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)// CONFIG2
#pragma config MCLRE = ON // Master Clear Enable bit (MCLR pin is Master Clear function)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config LPBOREN = OFF // Low-Power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = ON // Brown-out reset enable bits (Brown-out Reset Enabled, SBOREN bit is ignored)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
#pragma config ZCD = OFF // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
#pragma config PPS1WAY = OFF // Peripheral Pin Select one-way control (The PPSLOCK bit can be set and cleared repeatedly by software)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)// CONFIG3
#pragma config WDTCPS = WDTCPS_31 // WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = SWDTEN // WDT operating mode (WDT enabled/disabled by SWDTEN bit in WDTCON0)
#pragma config WDTCWS = WDTCWS_7 // WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC // WDT input clock selector (Software Control)// CONFIG4
#pragma config WRT = WRT_upper // UserNVM self-write protection bits (0x0000 to 0x01FF write protected)
#pragma config SCANE = not_available // Scanner Enable bit (Scanner module is not available for use)
#pragma config LVP = ON // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.)// CONFIG5
#pragma config CP = OFF // UserNVM Program memory code protection bit (Program Memory code protection enabled)
#pragma config CPD = OFF // DataNVM code protection bit (Data EEPROM code protection disabled)// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#endifunsigned char seq_table[16] = {0b00111111, //00b00000110, //10b01011011, //20b01001111, //30b01100110, //40b01101101, //50b01111101, //60b00000111, //70b01111111, //80b01101111, //90b01110111, //a0b01111100, //b0b00111001, //c0b01011110, //d0b01111001, //e0b01110001 //f
}; //段码表unsigned char code_table[4] = {0b11110111,0b11111011,0b11111101,0b11111110}; //位码表unsigned char display_table[4]; //显示缓冲区
int touch_count; //按动次数计时器
int touch_flag; //按动记录标志位
int mode = 0; //mode == 0 means print "yes" or "no"; mode == 1 means print voltage ADC numbervoid __interrupt() ISR(void);
void seq_code_sel(int i);
void Init();
void Init_timer();
void Init_ADC();void main(void)
{unsigned char i = 0;touch_count = 0;touch_flag = 0;Init();while (1){seq_code_sel(i);i = (i + 1) % 4;}
}void __interrupt() ISR(void)
{PIR0bits.TMR0IF = 0; //clear the signal bitTMR0H = 0x3c;TMR0L = 0xb0;if (mode){if (ADRES){display_table[0] = touch_count;display_table[1] = (ADRES / 100) % 10;display_table[2] = (ADRES / 10) % 10;display_table[3] = ADRES % 10;}}else{if (ADRES > 800) //设置阈值为 800{PORTB = 0;display_table[0] = seq_table[touch_count];display_table[1] = 0;display_table[2] = 0x37;display_table[3] = 0x3f;touch_flag = 1;}if (ADRES < 800){PORTB = 0x80;if (touch_flag){touch_count = (touch_count + 1) % 16;touch_flag = 0;}display_table[0] = seq_table[touch_count];display_table[1] = 0x6e;display_table[2] = 0x7b;display_table[3] = 0x6d;}}if (ADCON0bits.ADGO == 0){ADPRE = 0b00010000; //Precharge time is 128 clocks of the selected ADC clockADACQ = 0b00010000; //Acquisition time is 128 clocks of the selected ADC clockfor (int wait = 0; wait < 16; wait++); //wait for acquisition timeADCON0bits.ADGO = 1;}
}void Init()
{//Init PORTA,PORTB,PORTCPORTA = 0;LATA = 0;ANSELA = 0x80;TRISA = 0x80; //Set RA7 to inputPORTB = 0;LATB = 0;ANSELB = 0;TRISB = 0;PORTC = 0;LATC = 0;ANSELC = 0;TRISC = 0;Init_timer();Init_ADC();
}void Init_ADC()
{//Init ADCADCLKbits.ADCCS = 0b000001; //FOSC/4ADCON1bits.ADPPOL = 0; //IO pin shorted to VSS, Chold shorted to AVDDADCON0bits.ADCS = 0; //Clock supplied by FOSC, divided according to ADCLK registerADCON0bits.ADFRM0 = 1; //ADRES and ADPREV data are right-justifiedADREFbits.ADPREF = 0b11; //VREF+ is connected to FVRADREFbits.ADNREF = 0b0; // VREF- is connected to VSSFVRCONbits.FVREN = 1; //FVR enableFVRCONbits.ADFVR = 0b11; //ADC FVR Buffer Gain is 4x, (4.096V)FVRCONbits.FVRRDY = 1; //Fixed Voltage Reference output is ready for useADCON1 = 0b00000000; // default ADPPOL, no ADDSENADCON2 = 0b00000000; // legacy modeADCON3 = 0b00000000; // default, no interruptADPCH = 0b000111; //ADC Positive Input Channel Selection == RA7ADCAP = 0b101; //ADC Additional Sample Capacitor == 5pFADPRE = 0b00010000; //Precharge time is 128 clocks of the selected ADC clockADACQ = 0b00010000; //Acquisition time is 128 clocks of the selected ADC clockfor (int wait = 0; wait < 16; wait++);//wait for acquisition timeADCON0bits.ADON = 1; //Turn ADC On
}void Init_timer()
{//Timer interruptINTCONbits.GIE = 1;PIR0bits.TMR0IF = 0; //clear the signal bitPIE0bits.TMR0IE = 1; //interrupt enable//Timer0 configurationT0CON0 = 0b00010000;T0CON1 = 0b01000000;TMR0H = 0x3c;TMR0L = 0xb0;T0CON0bits.T0EN = 1;
}void seq_code_sel(int i)
{PORTA = code_table[i];if (mode){PORTC = seq_table[display_table[i]];}else{PORTC = display_table[i];}for (int temp = 0; temp < 100; temp++);
}
PIC单片机 电容式触摸检测相关推荐
- PIC单片机 按键检测识别
目录 按键和PIC单片机 一.按键 二.按键的物理连接与检测 三.PIC16F18854单片机 按键检测及显示实验 按键排布 预期效果 总体流程 中断服务程序 PIC汇编程序 按键和PIC单片机 一. ...
- pic单片机低电压检测_pic单片机汇编语言讲解(上)
pic 单片机为最常用单片机之一,许多程序均基于 pic 单片机进行开发.因此,熟练 pic 单片机编程尤为重要.为保证大家能准确.熟练掌握 pic 单片机的使用,本文特带来 pic 单片机的各种汇编 ...
- 16F877A和24C02通信汇编语言,pic单片机IIC通信读24C02程序例 16F877A 主频4M
#define _iic_h_//pic单片机IIC通信初始化函数声明 void iiccsh(void); //pic单片机IIC通信读外围设备函数声明 //功能:传送一个8位地址,返回一个8位数据 ...
- PIC单片机之电容触摸按键
电容触摸的硬件设计 PIC单片机电容触摸按键,最方便的地方就是外围电路简单,不需要任何外围元器件.只要从引脚连接出一条线到焊盘上即可. 电容按键触摸的原理 PIC单片机通过松弛振荡器是一个自激 RC ...
- PIC单片机入门_定时器/计数器TMR0详解与实例
1.前言: PIC 系列单片机内部配备有数量不等的定时器/计数器模块:例如PIC17CX系列和PIC18CX系列都都配置了4个定时器/计数器模块:而PIC16F87X系列都配置了3个定时器/计数器模块 ...
- PIC单片机RC振荡器的使用及校准方法
在PIC的单片机--MSP430F1611IPM中有多种型号有内部RC振荡器的功能,从而省去了晶振,不但节省了成本,并且我们还多了两个IO端口可以使用. 但是,由于RC振荡器中电阻.电容的离散性很大, ...
- PIC单片机-测试例程汇总
内容包括PIC单片机常用外设的测试例程.紫色文字是超链接,点击自动跳转至相关博文.持续更新,原创不易! 目录: 一.端口的定义与while(1)的使用 二.延时 1.通过语句延时程序(带参数) 2. ...
- pic常用子程序c语言,手把手教你使用PIC单片机做RS232串口通信实验(C语言版)
这一期,我们将一起来学习一下PIC单片机如何与PC机进行通信,一起来完成一个简单的RS232通信实例,我们不做太多的理论,从实例出发,相信能够给大家一个比较通俗.透彻地认识,掌握了它的原理,那你就可以 ...
- PIC单片机485通讯
目录 PIC单片机485通信发送 PIC单片机485通信接收 串行口RS4485通讯协议 概述 通讯协议说明 通讯网组方式 通讯协议方式 通讯接口方式 ASCII通讯方式 字符结构 通讯资料结构 校验 ...
最新文章
- pandas 官方API
- 用粑粑治疗自闭症!男孩接受6次粪菌移植,目前效果显著
- 查找所有的(字符相同但顺序不同) Find All Anagrams in a String
- NYOJ 625 笨蛋的难题(二)
- 02-线性结构2 一元多项式的乘法与加法运算 (20 分
- 吴恩达《深度学习》 学习笔记1
- c语言strlren函数的原代码,VB常用函数
- 什么?print 函数还可以打印彩色围棋局面?
- Security+ 学习笔记43 无线网络
- ENVI基于遥感影像的几何配准方法
- bash给脚本加进度条_shell脚本进度条。
- Python实现统计代码行数功能
- 【静态网页制作大作业——个人博客搭建(HTML+CSS+Javascript)】
- 魔兽争霸3运行速度慢的一些优化办法。
- 基于BS模型与基于二叉树模型的欧式期权定价与希腊字母结果对比
- 游戏美术资源网站推荐
- python:series详解和数据获取
- 2022最新可用免费天气预报API接口
- 使用python调整图片大小
- Photoshop Elements 10 All-in-One For Dummies 免积分下载