前言
这个芯片第一次用的时候,我花了不少心思,在网上找不到相关的编程资料,说实话,规格书都看的费劲,写下这篇博文来分享一下如何使用这颗芯片。
规格书分析
初看这个时序图时,人可能会有点懵,这个是芯片的输出管脚发出的波形,在写程序时,目的就是解析时序,分析判断出数据是“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的使用总结了,函数可以实现功能,但是可能比较长,不是很精简,抛砖引玉嘛,希望能引出读者朋友们更好的使用方式。