前言

这个芯片第一次用的时候,我花了不少心思,在网上找不到相关的编程资料,说实话,规格书都看的费劲,写下这篇博文来分享一下如何使用这颗芯片。

规格书分析

规格书

初看这个时序图时,人可能会有点懵,这个是芯片的输出管脚发出的波形,在写程序时,目的就是解析时序,分析判断出数据是“0”还是“1”。 芯片在发出数据信号前,会先发送两个周期的低电平,为启动信号,接着就会连续发送16个数据信号,当要发送数据“0”时,其波形时序是1个周期的高电平+1个周期的低电平;当要发送数据“1”时,其波形时序是1个周期的高电平+3个周期的低电平。两个数据的低电平持续时间有区别,所以在判断时,重点也就在这里,可以参考官方的判断数据方法:

规格书

代码分析

po代码

#define LOW_V			0
#define HIGH_V			1

数据结构

这里只有一个全局变量,用于保存16位的键值数据

u16 edited_key_code  = 0;

函数体

/*************************************************************/
/*函数名:hw_key_code_edit
/*输  入:无
/*输  出:无
/*描  述:中断中调用此函数,将按键时序转化为16位的编码值,低位为1号按键
/*************************************************************/
void hw_key_code_edit(void)
{
	static u8 index = 0;
	static u8 high_v_count = 0;
	static u8 low_v_count = 0;
	static u8 last_v = LOW_V;
	volatile u8 now_v = LOW_V;

	now_v = KEY_INPUT;
	
	if(index>=2 && index<=16)			//数据信号
	{
		//状态切换的条件
		if(last_v==LOW_V && now_v==HIGH_V)
		{
			if(low_v_count>=1 && low_v_count<=4)
			{
				editing_key_code &= ~(1<<(index-2));
			}
			else if(low_v_count>=7 && low_v_count<=12)
			{
				editing_key_code |= (1<<(index-2));
			}
			index++;
		}
		
		//2.计数低电平个数
		if(now_v==HIGH_V){
			low_v_count = 0;
		}
		else
		{
			low_v_count++;
		}
		
		//3.异常情况清零,重新等待空闲信号
		if(low_v_count > 12){
			
			index = 0;
			low_v_count = 0;			
		}
		
	}
	else if(index == 0)		//空闲信号
	{
		//1.状态切换的条件
		if((now_v==LOW_V) && (high_v_count>=18 && high_v_count<=33))
		{
			low_v_count = 1;
			index = 1;			
		}					
		
		//2.计数高电平个数
		if(now_v == LOW_V){
			high_v_count = 0;
		}
		else{
			high_v_count++;
		}
		
		//3.异常情况清零,重新等待空闲信号
		if(high_v_count > 33){
			high_v_count = 0;			
		}
		
//		(now_v == 0) ? (high_v_count = 0): (high_v_count++);
	}
	else if(index == 1)	//启动信号
	{
		//1.状态切换的条件
		if((now_v == HIGH_V) && (low_v_count>=5 && low_v_count<=8))
		{
			high_v_count = 1;
			index = 2;
		}
		
		//2.计数低电平个数
		if(now_v == HIGH_V){
			low_v_count = 0;
		}
		else{
			low_v_count++;
		}
		
		//3.异常情况清零,重新等待空闲信号
		if(low_v_count > 8){
			
			index = 0;
			low_v_count = 0;			
		}
		
	}
	else						//最后一个数据信号
	{
		//状态切换的条件
		if(last_v==LOW_V && now_v==HIGH_V)
		{
			if(low_v_count>=1 && low_v_count<=4)
			{
				editing_key_code &= ~(1<<15);
			}
			else if(low_v_count>=7 && low_v_count<=12)
			{
				editing_key_code |= (1<<15);
			}
						
			edited_key_code = editing_key_code;
			
			index = 0;
			editing_key_code &= 0x0000;
		}
		
		//2.计数低电平个数
		if(now_v==HIGH_V){
			low_v_count = 0;
		}
		else
		{
			low_v_count++;
		}
		
		//3.异常情况清零,重新等待空闲信号
		if(low_v_count > 12){
			
			index = 0;
			low_v_count = 0;			
		}
	}
	
	last_v = now_v;
}

代码思路

虽然代码看起来很长,但是整体的思路还是比较简单的,就是通过静态变量来保存读到的高低电平个数,看它是复合数据0还是数据1,如果过程中有错误数据,直接重新等待空闲信号,开始新一轮的判断。

注意事项

这段代码我是放在了单片机100us的定时器中断中,它的作用是解析出16位的键值数据

补充

官方在设计芯片时,为了增加可靠性,16位数据是有校验功能的,上面的函数仅仅是读取到了16位的数据,并没有对其校验,因此我又补充了下面这个函数,作用是:16位数据校验通过后,输出8位的按键键值信息,若未通过校验,则输出0x00(空按键)。

/*************************************************************/
/*函数名:get_key_value
/*输  入:无
/*输  出:u8 key_value
/*描  述:校验编码后的键值,检验成功后返回按键总线按键值,
	 校验失败返回无效键值。
/*************************************************************/
u8 get_key_value(void)
{
	u8 key_value = 0;
	u8 temp_high = 0;
	u8 temp_low  = 0;
	u16 temp_key_code = 0;
	
	temp_key_code = edited_key_code;
	temp_low  = (u8)temp_key_code;
	temp_high = (u8)(temp_key_code>>8);
	
	if(((temp_low&0x0f) + (temp_low>>4)) == 0x0f)
	{
		if(((temp_high&0x0f) + (temp_high>>4)) == 0x0f)
		{	
			key_value = ((temp_low&0x0f) | ((temp_high&0x0f) << 4));
			key_value = (key_value>>1)&0x1f;
		}
		else
		{
			key_value = 0x00;
		}
	}
	else
	{
		key_value = 0x00;
	}
	
	return key_value;	
}

这个函数要被消抖函数调用,用于读取键值信息,通过消抖函数消抖处理后,便是一个可靠的键值了。

总结

以上便是关于FTC333G的使用总结了,函数可以实现功能,但是可能比较长,不是很精简,抛砖引玉嘛,希望能引出读者朋友们更好的使用方式。