我直接试用了方太厨具方案,嘿,可以用!所以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[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结果
}
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
用户1737577 2014-8-9 09:51
用户377235 2014-8-9 08:24