热度 28
2014-8-18 17:13
2146 次阅读|
7 个评论
最近需要一个经过8mm厚的钢化玻璃的触摸方案,在网上找了2种方案,一种是ST的方案,还有一种是方太厨具方案。附件有2种方案的介绍。 我直接试用了方太厨具方案,嘿,可以用!所以ST的方案就没有试验了。单片机是STC的,用了一个PWM口、一个AD口。PWM频率为140KHz左右(几十K的频率试了也有用),AD采集的是一个直流信号,0.1uf的电容对抗干扰也有帮助。 下面有部分代码,主函数:上电初始化,待环境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 = GetADC10Result(ADCCHANNEL); Delay(1); ADCResult = GetADC10Result(ADCCHANNEL); Delay(1); ADCResult = GetADC10Result(ADCCHANNEL); if(((ADCResult -ADCResult )2) ((ADCResult -ADCResult )2) ((ADCResult -ADCResult )2) ((ADCResult -ADCResult )2) ((ADCResult -ADCResult )2) ((ADCResult -ADCResult )2)) { TouchInit =ADCResult ; 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(TimeCnt500ms80) { TimeCnt500ms = 0; Lock = 1; P17 = !P17; } } } if(Test_OneSedA) { Clr_OneSedA; ADCtemp = GetADC10Result(ADCCHANNEL); SendData(0xea); SendData(0xeb); SendData(ADCtemp8); SendData(ADCtemp); } } } //----------------------------------------------- /* Timer0 interrupt routine */ void tm0_isr() interrupt 1 using 1 { TimeCnt10ms++; TimeCnt1s++; if(TimeCnt1s1000) { 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_cnt10;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结果 }