单片机IO处理 电容触摸按键
原理说明:
通过检测感应按键PAD的电容量变化来判断是否有触摸动作。当手指触摸PAD时,电容量增加,充放电时间变长。
本方案中利用M48的20个双向IO口实现了20个触摸按键,而且所用原器件最少。其中R1~R20的10K电阻是消除干扰用的,如果采用软件算法,用数字滤波来消除干扰,这20个电阻也可以省略。这样就只需要10只1M的充放电电阻(R21~R30)就可以了。
最基本的按键单元是两个PAD分别接M48的两个IO引脚,两个引脚之间用一个1M的电阻相连。如图:
PB1(PAD1) O------/\/\/1M\/\/\------O (PAD2) PB2
有3种方法检测PAD1的电容量变化:
方法1:检测PAD1的充电时间
(1)初始化PB1输出低电平,PB2输出高电平,这时PAD1上的电量被放掉,PB1为低电平;
(2)设置PB1高阻输入,同时记时,使能PB1引脚电平变化中断。这时PB2输出的高电平通过1M的电阻对PAD1充电;
(3)充电到PAD1电平到MOS高电平的最低值时,PB1引脚电平变化中断,在中断里记下充电时间。
方法2:检测PAD1的放电时间
(1)初始化PB1输出高电平,PB2输出低电平,这时PAD1充电,PB1为高电平;
(2)设置PB1高阻输入,同时记时,使能PB1引脚电平变化中断。这时PAD1通过1M的电阻对PB2(地)放电;
(3)放电到PAD1电平到MOS低电平的最高值时,PB1引脚电平变化中断,在中断里记下放电时间。
方法3:检测PAD1的充放电时间
(1)初始化PB1输出低电平,PB2输出高电平,这时PAD1上的电量被放掉,PB1为低电平;
(2)设置PB1高阻输入,同时记时,使能PB1引脚电平变化中断。这时PB2输出的高电平通过1M的电阻对PAD1充电;
(3)充电到PAD1电平到MOS高电平的最低值时,PB1引脚电平变化中断。在中断里设置PB2输出低电平,这时PAD1通过1M的电阻对PB2放电;
(4)放电到PAD1电平到MOS低电平的最高值时,PB1引脚电平变化中断。在中断里记下充放电的总时间。
多次测量取滑动平均值(可以去掉最大、最小值后取平均值)来消除干扰。
定时检测PAD1的充放电时间t0,t1,t2......tk,tk+1,所有数据的平均值作为参考值,最近几次采样值的平均值作为当前值,用来判断充放电时间的增减。当充放电时间的增量超过一个设定的门限值时就认为有按键动作。修改这个门限值可以改变按键的灵敏度。
一个按键的检测过程就是这样的。其它按键同理。
检测到按键后,通过I2C接口发送按键码。测试视频里只用了一个LED来指示按键动作,有键按下灯亮,按键释放灯灭。
源程序:
//ICC-AVR application builder : 2011/12/1 20:30:09 // Target : m48 // Crystal: 8.0000Mhz #include <iom48v.h> #include <macros.h> #define PSCL PC5 //LED+ #define PSDA PC4 //LED- // 按键编号 引脚编号 #define P07 PB5 // 5 //SCK #define P08 PB4 // 4 //MISO #define P12 PB3 // 3 //MOSI #define on 1 #define off 0 //引脚编号=K[按键编号] unsigned ]={,,,,,,,,,,,,,,,,,,,,}; void led(unsigned char on_off) { if(on_off) PORTC &= ~BIT(PSDA); else PORTC |= BIT(PSDA); } void key_tst_prep(unsigned char k) { PORTB = 0xFF; DDRB = 0x00; PORTC |= 0x6F; DDRC = 0x30; PORTD = 0xFF; DDRD = 0x00; PCMSK0 = 0x00; //pin change mask 0 PCMSK1 = 0x00; //pin change mask 1 PCMSK2 = 0x00; //pin change mask 2 PCIFR = 0x07; //clear pin change flag2...0 PCICR = 0x07; //pin change enable ) { PORTB &= ~(<<k); DDRB |= (<<k); } ) { k-=; PORTC &= ~(<<k); DDRC |= (<<k); } ) { k-=; PORTD &= ~(<<k); DDRD |= (<<k); } } void key_tst_start(unsigned char k) { PCIFR = 0x07; //clear pin change flag2...0 ) { PCMSK0 = (<<k); //pin change mask 0 DDRB &= ~(<<k); } ) { k-=; PCMSK1 = (<<k); //pin change mask 1 DDRC &= ~(<<k); } ) { k-=; PCMSK2 = (<<k); //pin change mask 2 DDRD &= ~(<<k); } TCNT0 = 0x00; } //4,7,8,12,14,17,19,20 unsigned ,KF[]={};//按键标记 1按下 0未按 //按键编号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 unsigned ]={,,,,,,,,,,,,,,,,,,,,};//门限值 #pragma interrupt_handler key_tst:iv_PCINT0 #pragma interrupt_handler key_tst:iv_PCINT1 #pragma interrupt_handler key_tst:iv_PCINT2 void key_tst(void) { unsigned char i; if(TCNT0>D[KEYNUM]) KF[KEYNUM]=on; else KF[KEYNUM]=off; ;i<;i++) { ]=i; break;} ]=; } led(KF[]); ) KEYNUM = ; } //TIMER0 initialize - prescale:1 // WGM: Normal // desired value: 0.125uSec // actual value: 0.125uSec (0.0%) void timer0_init(void) { TCCR0B = 0x00; //stop TCNT0 = 0xFF; //set count TCCR0A = 0x00; TCCR0B = 0x02; //start timer TIMSK0 = 0x00; //timer 0 interrupt sources } //TIMER2 initialize - prescale:32 // WGM: Normal // desired value: 1mSec // actual value: 1.000mSec (0.0%) void timer2_init(void) { TCCR2B = 0x00; //stop ASSR = 0x00; //set async mode TCNT2 = 0x00; //setup OCR2A = 0x83; TCCR2A = 0x00; TCCR2B = 0x02; //start TIMSK2 = 0x03; //timer 2 interrupt sources } #pragma interrupt_handler timer2_compa_isr:iv_TIM2_COMPA void timer2_compa_isr(void) { key_tst_start(K[KEYNUM]); } #pragma interrupt_handler timer2_ovf_isr:iv_TIM2_OVF void timer2_ovf_isr(void) { //TCNT2 = 0x06; //reload counter value key_tst_prep(K[KEYNUM]); } //TWI initialize // bit rate:1 void twi_init(void) { TWCR= 0X00; //disable twi TWBR= 0x01; //set bit rate TWSR= 0x01; //set prescale TWAR= 0x00; //set slave address TWCR= 0x44; //enable twi } //call this routine to initialize all peripherals void init_devices(void) { //stop errant interrupts until set up CLI(); //disable all interrupts key_tst_prep(K[KEYNUM]); timer0_init(); timer2_init(); //twi_init(); MCUCR = 0x00; EICRA = 0x00; //extended ext ints EIMSK = 0x00; PRR = 0x0F; //power controller SEI(); //re-enable interrupts //all peripherals are now initialized } // void main(void) { init_devices(); }
有不明白的地方可以随时咨询我:
欢迎致电:15267845422
研发部经理:代品川
QQ:350998385
地址:宁波北仑恒晶电子科技有限公司
电话:15267845422
传真:0574-55128828
企业网址:www.hengtaimcu.com
浙江宁波北仑恒晶电子科技有限公司专业为客人定制各种电容式触控液晶TN、HTN、LCD液晶屏、LCD液晶显示屏,LCD液晶显示器,笔段式液晶、IC邦定加工等业务,现有8台510邦定机,两条LCD前后段生产线;工厂在深圳、潮州、惠州、江西,工厂现在员人3000余人,占地面积45000平方米,LCD生产线能完成从前段的投料到后段切割、灌晶、电检、丝印、贴片、装脚等工艺操作。LCD交货周期: 客户提供详细LCD资料=>3天出图纸(客户确认)=>15天交样品(客户确认)=>20天出货(不装金属脚)/25天出货(装金属脚)
产品服务类型:1.产品主要技术参数
1)触控类型:电容式触控
1)外型尺寸:285×345mm以下;
2)导电玻璃厚度:0.4、0.55、0.7、1.1mm;
3)象素最小间隙:10um;
4)占空比:1/240duty以下;
5)连接方式:导电胶条、斑马纸、金属插脚、TAB、COG等。
2.产品型式
1)显示方式:正性、负性;
2)光学模式:反射型、透射型、半透半反型、全息型等;
3) LCD类别:TN型、HTN型、STN型、FSTN型、VATN型; 4)颜色模式:黄绿、灰、黑、白、蓝等模式。
在本公司订购产品的客户均可以享受到我们的专业技术团队的配合,以帮助您更好的更快的吧我们的产品接口道你们的产品上。
单片机IO处理 电容触摸按键的更多相关文章
- STM32系列单片机IO口模式设置
STM32单片机的每组IO口都有4个32位配置寄存器用于配置GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR和GPIOx_PUPDR,2个32位数据寄存器用于配置输入和 ...
- 单片机IO口驱动能力
以STM32的IO口为例,最大的输出电流和灌入电流在芯片手册上都有说明.单个IO口一般都是十几mA到几十mA,同时总的VDD电流也有限制,大概为150mA.所以单片机驱动外设时,如果不是信号型而是功率 ...
- 实验1 单片机IO口应用及数码管显示
1. 单片机驱动蜂鸣器的实验: a) 说明:Lab51单片机实验板的蜂鸣器连接到单片机的P1.5 b) 基本要求:控制蜂鸣器每2秒响0.5秒. #include &l ...
- 关于51单片机IO引脚的驱动能力与上拉电阻
单片机的引脚,可以用程序来控制,输出高.低电平,这些可算是单片机的输出电压.但是,程序控制不了单片机的输出电流. 单片机的输出电流,很大程度上是取决于引脚上的外接器件. 单片机输出低电平时,将允许外部 ...
- 关于51单片机IO引脚的驱动能力与上拉电阻设计方案
转载自:http://bbs.dianyuan.com/article/20312-2 单片机的引脚,可以用程序来控制,输出高.低电平,这些可算是单片机的输出电压.但是,程序控制不了单片机的输出电流. ...
- 如何检测 51单片机IO口的下降沿
下降沿检测,说白了就是满足这样一个逻辑,上次检测是1,这次检测是0,就是下降沿. 从这个条件可知,要确保能够正确检测到一个下降沿,负脉冲的宽度,必须大于一个检测周期,当负脉冲宽度小于一个检测周期,就有 ...
- 51单片机:IO口扩展芯片用法(74HC165,74HC595)
IO口扩展芯片,主要是解决单片机IO口太少. 74HC165:数据从并转串 74HC595:数据从串转并 两种芯片,都是通过时序电路,加上移位功能,进行数据传输 74HC165:数据从并转串.以下实例 ...
- 单片机小白学步系列(二十) IO口原理
IO口操作是单片机实践中最基本最重要的一个知识,本篇花了比較长的篇幅介绍IO口的原理. 也是查阅了不少资料,确保内容正确无误,花了非常长时间写的. IO口原理原本须要涉及非常多深入的知识,而这里尽最大 ...
- MSP430 IO 使用
MSP430内部上拉下拉使用注意——IO口测高低电平 MSP430单片机IO口用来检测高低电平时,是不需要外部上拉下拉的,因为其内部有上拉和下拉.在用作高低电平检测时,需要开启上拉或下拉. ...
随机推荐
- ssl https服务 需要 php5.3以上
php 5.2 升级 5.3 http://wdlinux.cn/bbs/viewthread.php?tid=37512&highlight=5.3 默认的升级不支持 pdo 升级前编辑升级 ...
- [RxJS] Transformation operator: bufferToggle, bufferWhen
bufferToggle(open: Observable, () => close: Observalbe : Observalbe<T[]>) bufferToggle take ...
- Linux 常用命令使用方法大搜刮(转)
1.# 表示权限用户(如:root),$ 表示普通用户 开机提示:Login:输入用户名 password:输入口令 用户是系统注册用户成功登陆后,可以进入相应的用户环境. 退出当前shel ...
- easy ui example
http://www.jeasyui.com/tutorial/index.php http://www.w3cschool.cc/jeasyui/jqueryeasyui-tutorial.html
- UITableView beginUpdate和endUpdate使用的前提
转载地址:http://blog.csdn.net/vieri_ch/article/details/46893023 UITableView有两个方法,用于单元格动画变化的方法,beginUpdat ...
- iOS 高仿:花田小憩3.0.1
前言 断断续续的已经学习Swift一年多了, 从1.2到现在的2.2, 一直在语法之间徘徊, 学一段时间, 工作一忙, 再捡起来隔段时间又忘了.思来想去, 趁着这两个月加班不是特别多, 就决定用swi ...
- clearTimeout(timeoutfunc) 是否有必要执行
当使用 setTimeout() 方法的时候,是否必须执行 clearTimeout() ? 在 setTimeout() 内的函数执行之前,如果想要阻止执行该方法,是有必要执行 cleartTime ...
- unlocker208安装之后看不到Apple macos选项,解决办法.
前段时间升级了win10,最新的unlocker208安装以后看不到mac os的选项,为什么呢?我们在管理员允许win-install.cmd的过程中,会在cmd中看到这么一句话:LookupErr ...
- 在Weex中定制自定义组件
1.配置自定义组件 public class MyViewComponent extends WXComponent{ public MyViewComponent(WXSDKInstance ins ...
- 图论——读书笔记(基于BFS广度优先算法的广度优先树)
广度优先树 对于一个图G=(V,E)在跑过BFS算法的过程中会创建一棵广度优先树. 形式化一点的表示该广度 优先树的形成过程是这样的: 对于图G=(V,E)是有向图或是无向图, 和图中的源结点s, 我 ...