原创 [博客大赛]硬件设计-8mm玻璃的触摸按键

2014-8-18 17:13 2128 20 27 分类: MCU/ 嵌入式 文集: 硬件设计

    最近需要一个经过8mm厚的钢化玻璃的触摸方案,在网上找了2种方案,一种是ST的方案,还有一种是方太厨具方案。附件有2种方案的介绍。

    我直接试用了方太厨具方案,嘿,可以用!所以ST的方案就没有试验了。单片机是STC的,用了一个PWM口、一个AD口。PWM频率为140KHz左右(几十K的频率试了也有用),AD采集的是一个直流信号,0.1uf的电容对抗干扰也有帮助。
20140807115301692.jpg
下面有部分代码,主函数:上电初始化,待环境AD值稳定,记录下来TouchInit 。 主循环每10ms检测一下AD,与TouchInit比较,如果差值大于TOUCHTHRE,则认为有按键按下。
 
void main()
{
SCON = 0x5a;                //设置串口为8位可变波特率
    AUXR = 0x40;                //定时器1为1T模式
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
    TL1 = 0xd8;                 //设置波特率重装值
    TH1 = 0xff;                 //115200 bps(65536-18432000/4/115200)
    TR1 = 1;                    //定时器1开始启动
 
    ACC = P_SW1;
    ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=0 CCP_S1=0
    P_SW1 = ACC;                    //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)
 
    CCON = 0;                       //初始化PCA控制寄存器
                                    //PCA定时器停止
                                    //清除CF标志
                                    //清除模块中断标志
    CL = 0;                         //复位PCA寄存器
    CH = 0;
    CMOD = 0x02;                    //设置PCA时钟源
                                    //禁止PCA定时器溢出中断
    PCA_PWM1 = 0x80;                //PCA模块1工作于6位PWM
    CCAP1H = CCAP1L = 0x20;         //PWM1的占空比为50% ((40H-20H)/40H)
    CCAPM1 = 0x42;                  //PCA模块1为7位PWM模式
 
    CR = 1;                         //PCA定时器开始工作
 
    P1ASF = 0x20;                   //设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
 
    AUXR |= 0x80;                 //定时器0为1T模式
P1M0 = 0x20; //P0.4推挽输出,其他双向口
P1M1 = 0x00;
    TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
    TL0 = T1MS;                     //初始化计时值
    TH0 = T1MS >> 8;
    TR0 = 1;                        //定时器0开始计时
    ET0 = 1;                        //使能定时器0中断
while(1)
{
ADCResult[0]= GetADC10Result(ADCCHANNEL); Delay(1);
ADCResult[1]= GetADC10Result(ADCCHANNEL); Delay(1);
ADCResult[2]= GetADC10Result(ADCCHANNEL); 
if(((ADCResult[0]-ADCResult[1])<2) && ((ADCResult[1]-ADCResult[0])<2) && 
  ((ADCResult[0]-ADCResult[2])<2) && ((ADCResult[2]-ADCResult[0])<2) &&
  ((ADCResult[3]-ADCResult[1])<2) && ((ADCResult[1]-ADCResult[3])<2))
{
TouchInit =ADCResult[2];
break;
}
}
 
    EA = 1;
 
    while (1)
{
if(Test_10mSedA)
{
Clr_10mSedA;
ADCtemp = GetADC10Result(ADCCHANNEL);
if(ADCtemp>(TouchInit-15)){Lock = 0;TimeCnt500ms = 0;}
 
if((ADCtemp<(TouchInit-TOUCHTHRE)) && (Lock == 0)) 
{
TimeCnt500ms++;
if(TimeCnt500ms>80)
{
TimeCnt500ms = 0;
Lock = 1;
P17 = !P17;
}
}
}
if(Test_OneSedA)
{
Clr_OneSedA;
ADCtemp = GetADC10Result(ADCCHANNEL);
SendData(0xea); 
SendData(0xeb); 
SendData(ADCtemp>>8);
SendData(ADCtemp); 
}
}
}
 
//-----------------------------------------------
 
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 using 1
{
TimeCnt10ms++;
TimeCnt1s++;
if(TimeCnt1s>1000)
{
Set_OneSedA;
TimeCnt1s = 0;
}
if(TimeCnt10ms > 10)
{
Set_10mSedA;
TimeCnt10ms = 0;
}
}
/***********************************************************************************
* Function: GetADCResult();
* Description: 连续10次读取ADC结果求和,去除最大和最小值之后再平均
* Input:  ch-ADC通道
* Return: 转换结果
* Note:   none;
************************************************************************************/
uint GetADC10Result(uchar ch)
{
    uint admax,admin,temp;
uchar ad_cnt;
uint ad_result = 0;
 
for(ad_cnt=0;ad_cnt<10;ad_cnt++)
{
EA = 0;
   ADC_CONTR = ADC_POWER | ADC_SPEEDH | ch | ADC_START;
   _nop_();                         //等待4个NOP
   _nop_();
   _nop_();
   _nop_();
   while (!(ADC_CONTR & ADC_FLAG)); //等待ADC转换完成
EA = 1;
   ADC_CONTR &= ~ADC_FLAG; 
temp = ADC_RES;
temp <<= 2;
temp |= ADC_RESL;         //Close ADC
if(ad_cnt==0) admax = admin = temp;
if(admax < temp) admax = temp;
if(admin > temp) admin = temp;
ad_result += temp;
}
    ad_result -= admin;
    ad_result -= admax;
    ad_result >>= 3; 
 
    return ad_result ;                 //返回ADC结果
}

文章评论7条评论)

登录后参与讨论

185555448_627131652 2014-8-16 14:00

厉害,谢谢分享好文章。

用户1013980 2014-8-12 07:42

不错的文章

用户1013980 2014-8-12 07:38

谢谢分享

用户780633 2014-8-10 14:01

不错的文章

用户440820 2014-8-9 16:07

我们公司做触摸是用的PSOC4.

用户1737577 2014-8-9 09:51

非常感谢同行的分享!!!

用户377235 2014-8-9 08:24

STC15F2K60S2的datasheet有这个电路
相关推荐阅读
用户1527862 2015-11-04 08:42
开关电源(5)-如何入门2
反激式开关电源 第一步确定Lp,之前的文章中提到如何确定。 第二步确定Np,前面有2个重要的公式,确定Np需要第三个重要的公式了,法拉第电磁感应定律E=nΔΦ/Δt...
用户1527862 2015-10-19 14:15
开关电源(4)- 变压器同名端测量
      有的变压器次级线比较粗,而没有焊接到骨架引脚上,只是简单的做了记号,发现有搞错记号的!     现终于找到一个测量变压器同名端的方法,需要一台示波器。示波器通常有个输出校验的端...
用户1527862 2015-10-14 15:58
开关电源(3)-元器件选择注意点
1、肖特基二极管       它的阳极和阴极之间往往存在很大的电容。肖特基二极管两端电压的每次改变(当肖特基两端电压几乎没有电压的时候,变化最大)的时候,这个电容都一定会被充电和放电。流...
用户1527862 2015-10-13 12:14
开关电源(2)-占空比为何小于0.5
一直不清楚为什么反激式开关电源占空比要小于0.5,今天知道了那么一点点!占空比大于50%时系统可能出现不稳定性,可能会产生次谐波振荡;另外,在电路拓扑结构选择上也有局限,在升压型和降压-升压型电路中,...
用户1527862 2015-10-12 11:46
开关电源(1)-如何入门
  在我们的设计电路中,不可缺少的部分就是电源了,以前做电路电源是用工频变压器降压然后整流,后来流行开关电源了,就直接买开关电源模块。 一直很好奇这开关电源模块,想把它直接画在自己设计的电路中...
用户1527862 2015-03-13 14:28
电磁炉入门(6)-硬件分析:线盘
    前面介绍过电磁炉基本原理,主要是LC震荡,这个L就指的是线盘,关于线盘总结一下个人经验:       1、线盘必须用多股线圈绕制而成,为了是防止高频趋肤效应,下面的公式是计算趋肤深...
我要评论
7
20
关闭 站长推荐上一条 /2 下一条