大家周末快乐!今天体验了一下开发板的串口打印以及电容触摸按键功能,当初申请该开发套件的时候,我就是想体验一下沁恒的电容触摸按键的灵敏度与之前使用过的赛元隔空按键进行对比,结果很明显,沁恒采用在CH549上的触摸按键很是给力,接触手感好,反应很灵敏。其原理图上连接如下所示:
正如之前的搭建编译、下载环境的帖子中提到,该开发板有两种下载方式,可以使用串口调试口下载,也可以直接使用USB口下载,也就是P6口,利用“WCHISPTool”的下载工具下载。这里,我使用USB口下载方式将”\CH549开发资料汇总\CH549EVT\EVT\EXAM\TouchKey“目录下的TouchKey.hex文件下到板子上,然后将连接在板上的USB端再拔出,连接在调试串口端,PC端打开串口调试助手,实时观察按键打印信息。
根据以上操作,不管是根据调试串口打印的实时数据信息,还是板子上的LED灯显示,说明触摸按键很灵敏。从外观上看这四个触摸弹簧按键很漂亮,但不知道是什么材质的,时间长了会不会生锈,防不防静电?这些环境因素也应当考虑进去。之前使用过的赛元电子隔空触摸按键,他们的设计按键也可以通过软件采集,提取调整触摸按键的灵敏度,按键的工艺采用隔空触摸的方式,操作起来也蛮不错。
这里略带提及一下按键处理及LED显示的程序:
#include ".\TouchKey\TouchKey.H"
#pragma NOAREGS
#if EN_ADC_INT
UINT8 GetValueFlag = 0; //获取到有效值标志
UINT16 IntCurValue = 0; //中断采集到的当前值
#endif
/*******************************************************************************
* Function Name : TouchKey_Init
* Description : 触摸按键初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TouchKey_Init( void )
{
//Touch采样通道设置为高阻输入
P0_MOD_OC &= 0xF0; //P00 P01 P02 P03高阻输入
P0_DIR_PU &= 0xF0;
ADC_CFG |= (bADC_EN|bADC_AIN_EN); //开启ADC模块电源,选择外部通道
ADC_CFG = ADC_CFG & ~(bADC_CLK0 | bADC_CLK1); //选择ADC参考时钟
ADC_CHAN = (3<<4); //默认选择外部通道0
ADC_CTRL = bADC_IF; //清除ADC转换完成标志,写1清零
#if EN_ADC_INT
SCON2 &= bU2IE; //和UART2中断地址共用,故中断需2选1
IE_ADC = 1; //开启ADC中断使能
EA = 1; //开启总中断使能
#endif
}
/*******************************************************************************
* Function Name : TouchKey_Init
* Description : 触摸按键初始化
* Input : 通道号选择ch:0~15,分别对应P10~P17、P00~P07
充电脉冲宽度 cpw:0~127
cpw由 外部触摸按键电容、VDD电压、主频三者决定。
计算公式:count=(Ckey+Cint)*0.7VDD/ITKEY/(2/Fsys)
TKEY_CTRL=count > 127 ? 127 : count (其中Cint为15pF,ITKEY为50u)
简化公式:cpw = (Ckey+15)*0.35*VDD*Fsys/50
cpw = cpw>127?127:cpw
* Output : None
* Return : 返回触摸检测电压
*******************************************************************************/
UINT16 TouchKeySelect( UINT8 ch,UINT8 cpw )
{
ADC_CHAN = ADC_CHAN & (~MASK_ADC_CHAN) | ch; //外部通道选择
//电容较大时可以先设置IO低,然后恢复浮空输入实现手工放电,≤0.2us
#if EN_ADC_INT
GetValueFlag = 0; //标志位清0
#endif
TKEY_CTRL = cpw; //充电脉冲宽度配置,仅低7位有效(同时清除bADC_IF,启动一次TouchKey)
#if EN_ADC_INT
while(GetValueFlag == 0); //等待采用完成
#else
while(ADC_CTRL&bTKEY_ACT);
#endif
return (ADC_DAT&0xFFF);
}
#if EN_ADC_INT
/*******************************************************************************
* Function Name : ADC_ISR( )
* Description : ADC 中断服务函数
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void ADC_ISR(void) interrupt INT_NO_ADC
{
if(ADC_CTRL&bADC_IF)
{
ADC_CTRL = bADC_IF; //清除ADC转换完成标志
IntCurValue = (ADC_DAT&0xFFF); //采样值保存到变量IntCurValue
GetValueFlag = 1; //采样完成标志
}
}
#endif
#include ".\Public\CH549.H"
#include ".\Public\DEBUG.H"
#include ".\TouchKey\TouchKey.H"
#pragma NOAREGS
UINT16 PowerValue[16]; //保存触摸按键上电未触摸值
volatile UINT16 Press_Flag = 0; //按下标志位
UINT8C CPW_Table[16] = { 30,30,30,30, 30,30,30,30, //与板间电容有关的参数,分别对应每个按键
30,30,30,30, 30,30,30,30,
};
/*******************************************************************************
* Function Name : ABS
* Description : 求两个数差值的绝对值
* Input : a,b
* Output : None
* Return : 差值绝对值
*******************************************************************************/
UINT16 ABS(UINT16 a,UINT16 b)
{
if(a>b)
{
return (a-b);
}
else
{
return (b-a);
}
}
/*******************************************************************************
* Function Name : LED_Port_Init
* Description : LED引脚初始化,推挽输出
* P22~P25
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void LED_Port_Init(void)
{
P2 |= (0xF<<2); //默认熄灭
P2_MOD_OC &= ~(0xF<<2);
P2_DIR_PU |= (0xF<<2);
}
/*******************************************************************************
* Function Name : LED_Control
* Description : 点灯控制
* Input : LEDx: 0~3 分别对应P22~P25四个LED灯(低驱)
* status: 0:灭 1:亮
* Output : None
* Return : None
*******************************************************************************/
void LED_Control(UINT8 LEDx,UINT8 status)
{
if(LEDx>3)
{
return;
}
if(status) //点亮
{
P2 &= ~(1<<(2+LEDx));
}
else //熄灭
{
P2 |= (1<<(2+LEDx));
}
}
//主函数
void main()
{
UINT8 ch;
UINT16 value;
UINT16 err; //触摸模拟变化差值
CfgFsys( ); //CH549时钟选择配置
mDelaymS(20);
mInitSTDIO( ); //串口0初始化
printf("TouchKey demo start ...\n");
LED_Port_Init();
TouchKey_Init();
Press_Flag = 0; //无按键按下
/* 获取按键初值 */
for(ch = 8; ch!=12; ch++)
{
PowerValue[ch] = TouchKeySelect( ch,CPW_Table[ch] );
printf("%d ",PowerValue[ch] );
}
printf("\n");
while(1)
{
/* 按键检测 */
for(ch = 8; ch!=12; ch++)
{
value = TouchKeySelect( ch,CPW_Table[ch] );
err = ABS(PowerValue[ch],value);
if( err > DOWM_THRESHOLD_VALUE ) //差值大于阈值,认为按下
{
if((Press_Flag & (1<<ch)) == 0) //说明是第一次按下
{
printf("ch %d pressed,value:%d\n",(UINT16)ch, value);
/* 点灯处理 */
LED_Control(ch-8,1);
}
Press_Flag |= (1<<ch);
}
else if( err < UP_THRESHOLD_VALUE ) //说明抬起或者未按下
{
if(Press_Flag & (1<<ch)) //刚好一抬起
{
Press_Flag &= ~(1<<ch);
printf("ch %d up,value:%d\n",(UINT16)ch, value);
/* 灭灯处理 */
LED_Control(ch-8,0);
}
}
}
}
}
最后,上传一段体验电容触摸按键的效果视频,后续有时间再对CH549的其它外设进行开发设计,体验CH549的各种接口通讯方式。此次分享到此结束,欢迎各位网友前来围观,谢谢!
此内容由EEWORLD论坛网友yin_wu_qing原创,如需转载或用于商业用途需征得作者同意并注明出处