合泰BS8116A-3触摸芯片开发踩坑指南

一、硬件说明

引脚图:

接线:

 说明:由于用到了唤醒检测,所以KEY16引脚用作IRQ中断唤醒功能,未使用引脚拉低。

二、IIC配置说明

1、最大波特率:

实际单片机配置最好不要设置波特率100Khz容易出错,50Khz就可以了。

2、从机地址:

 注意:这里需要注意的是,从机地址位不包括读写位,实际使用需要右移一位,从机地址是0x50实际发送读是0xA1,写是0xA0。

3、从机忙碌

 这个判断程序里面还是加一下,不加的话一般也能用,但是容易出问题。

三、读写按键寄存器

 1、中断说明:

 

 检测到IRQ引脚低电平开始读取按键状态,高电平停止读取。

2、工作模式:

 这里需要注意在8秒按键没有按下时,会进入低功耗状态。两种状态下的按键唤醒速度是不同的,体验有明显差异,且无法修改进入休眠时间。

3、读取按键状态

 4、读写配置寄存器

 注意:最后是一个字节的校验和,只是简单的单字节累加从合泰同类型其他手册里找到说明了。

 5、配置寄存器

注意:触发门槛值越低敏感度越高,门槛值数值越高敏感度越低。

 免大家去查表直接复制过来了。

四、代码片段

1、配置寄存器数据结构

#define KEY_ADDR1_8		0x08
#define KEY_ADDR9_12	0x09

#define REG_CFG_ADDR	0xB0
#define REG_CFG_CNT		21

#pragma pack(1) //单字节对齐

typedef union {
	uint8_t reg[REG_CFG_CNT+1];
	struct {
		uint8_t opt1_oms : 1;
		uint8_t opt1_17_res:7;
		uint8_t res1;
		uint8_t res2;
		uint8_t res3;
		uint8_t opt2_05_res : 6;
		uint8_t opt2_6_lsc : 1;
		uint8_t opt2_7_res : 1;
		uint8_t k1_th_val : 6;
		uint8_t k1_th_res : 1;
		uint8_t k1_th_wu : 1;
		uint8_t k2_th_val : 6;
		uint8_t k2_th_res : 1;
		uint8_t k2_th_wu : 1;
		uint8_t k3_th_val : 6;
		uint8_t k3_th_res : 1;
		uint8_t k3_th_wu : 1;
		uint8_t k4_th_val : 6;
		uint8_t k4_th_res : 1;
		uint8_t k4_th_wu : 1;
		uint8_t k5_th_val : 6;
		uint8_t k5_th_res : 1;
		uint8_t k5_th_wu : 1;
		uint8_t k6_th_val : 6;
		uint8_t k6_th_res : 1;
		uint8_t k6_th_wu : 1;
		uint8_t k7_th_val : 6;
		uint8_t k7_th_res : 1;
		uint8_t k7_th_wu : 1;
		uint8_t k8_th_val : 6;
		uint8_t k8_th_res : 1;
		uint8_t k8_th_wu : 1;
		uint8_t k9_th_val : 6;
		uint8_t k9_th_res : 1;
		uint8_t k9_th_wu : 1;
		uint8_t k10_th_val : 6;
		uint8_t k10_th_res : 1;
		uint8_t k10_th_wu : 1;
		uint8_t k11_th_val : 6;
		uint8_t k11_th_res : 1;
		uint8_t k11_th_wu : 1;
		uint8_t k12_th_val : 6;
		uint8_t k12_th_res : 1;
		uint8_t k12_th_wu : 1;
		uint8_t k13_th_val : 6;
		uint8_t k13_th_res : 1;
		uint8_t k13_th_wu : 1;
		uint8_t k14_th_val : 6;
		uint8_t k14_th_res : 1;
		uint8_t k14_th_wu : 1;
		uint8_t k15_th_val : 6;
		uint8_t k15_th_res : 1;
		uint8_t k15_th_wu : 1;
		uint8_t k16_th_val : 6;
		uint8_t k16_th_mod : 1;
		uint8_t k16_th_wu : 1;
		uint8_t checksum;
	}setting;
} key_setting_t;

#pragma pack()

 2、初始化配置寄存器

void TK_Module_Cfg(void)
{
	int i;
	rt_int32_t ret = 0;
	key_setting_t write_setting = {{0x00,0x00,0x83,0xf3,0xd8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x4f,0},},read_setting={0};
	for(i=0;i<REG_CFG_CNT;i++){
		write_setting.setting.checksum += write_setting.reg[i];
	}
	for(i=0;i<30;i++){
		TK_WriteReg(&write_setting);
		rt_thread_mdelay(1);
		TK_ReadReg(&read_setting);
		ret = rt_memcmp(&write_setting,&read_setting,REG_CFG_CNT);
		if(ret==0){
			break;
		}
	}
}

3、寄存器读写

//写寄存器
int TK_I2c_WriteReg(uint8_t *dest,uint16_t count,uint8_t reg)
{
    uint8_t u8i=0,flag[10]={0},idx=0,u8State;
	uint32_t u32KeyTimer = rt_tick_get()+200;
	I2C_ClearFunc(BS8116A_IIC,I2cStart_En);
	I2C_ClearFunc(BS8116A_IIC,I2cAck_En);
	I2C_ClearFunc(BS8116A_IIC,I2cStop_En);
	I2C_SetFunc(BS8116A_IIC,I2cModule_En);
    I2C_SetFunc(BS8116A_IIC,I2cStart_En);    
    while(u32KeyTimer > rt_tick_get())
    {
        while(0 == I2C_GetIrq(BS8116A_IIC) && u32KeyTimer > rt_tick_get()){;}
        u8State = I2C_GetState(BS8116A_IIC);
        switch(u8State)
        {
            case 0x08:                                    //已发送起始条件,将发送SLA+R
				flag[0]++;
                I2C_ClearFunc(BS8116A_IIC,I2cStart_En);
                I2C_WriteByte(BS8116A_IIC,(I2C_DEVADDR));//发送SLA+W
                break;
            case 0x18:                                    //已发送SLA+W,并接收到ACK
				flag[1]++;
				while(!IIC_READ_SDA){}
                I2C_WriteByte(BS8116A_IIC,reg);              //发送内存地址
			case 0x20:
				flag[2]++;
                I2C_WriteByte(BS8116A_IIC,reg);              //发送内存地址
                break;
			case 0x28:										//已发送 I2Cx_DATA 中的数据,已接收 ACK
				flag[3]++;
				I2C_WriteByte(BS8116A_IIC,dest[u8i++]);              //发送内存地址
				if(u8i>count){
					I2C_SetFunc(BS8116A_IIC,I2cStop_En);            //其他错误状态,重新发送起始条件
					goto FINISH;
				}
				break;
            default:                                      //其他错误状态,重新发送起始条件
				flag[9]++;
                I2C_SetFunc(BS8116A_IIC,I2cStop_En);            //其他错误状态,重新发送起始条件
				goto FINISH;
        }
        I2C_ClearIrq(BS8116A_IIC);                               //清除中断状态标志位
		idx++;
    }
	FINISH:
	I2C_ClearIrq(BS8116A_IIC);                               //清除中断状态标志位
    return 0;
}

//获取按键码
int TK_I2c_ReadReg(uint8_t *dest,uint16_t count,uint8_t reg)
{
	en_result_t enRet = Error;
    uint8_t u8i=0,flag[10]={0},idx=0,u8State,pu8Data[32]={0};
	uint32_t u32KeyTimer = rt_tick_get()+200;
    I2C_ClearFunc(BS8116A_IIC,I2cStart_En);
	I2C_ClearFunc(BS8116A_IIC,I2cAck_En);
	I2C_ClearFunc(BS8116A_IIC,I2cStop_En);
	I2C_SetFunc(BS8116A_IIC,I2cModule_En);
    I2C_SetFunc(BS8116A_IIC,I2cStart_En);    
    while(u32KeyTimer > rt_tick_get())
    {
        while(0 == I2C_GetIrq(BS8116A_IIC) && u32KeyTimer > rt_tick_get()){;}
        u8State = I2C_GetState(BS8116A_IIC);
        switch(u8State)
        {
            case 0x08:                                    //已发送起始条件,将发送SLA+R
				flag[0]++;
                I2C_ClearFunc(BS8116A_IIC,I2cStart_En);
                I2C_WriteByte(BS8116A_IIC,(I2C_DEVADDR));//发送SLA+W
                break;
            case 0x18:                                    //已发送SLA+W,并接收到ACK
				flag[1]++;
				while(!IIC_READ_SDA){}
                I2C_WriteByte(BS8116A_IIC,reg);              //发送内存地址
                break;
            case 0x28:                                    //已发送数据,接收到ACK
				flag[2]++;
                I2C_SetFunc(BS8116A_IIC,I2cStart_En);
                break;
            case 0x10:                                    //已发送重复起始条件
				flag[3]++;
                I2C_ClearFunc(BS8116A_IIC,I2cStart_En);
                I2C_WriteByte(BS8116A_IIC,(I2C_DEVADDR)|0x01);//读命令发送
                break;
            case 0x40:                                    //已发送SLA+R,并接收到ACK
				flag[4]++;
				if(count>1){
					I2C_SetFunc(BS8116A_IIC,I2cAck_En);
				}
                break;
            case 0x50:                                    //已接收数据字节,并已返回ACK信号
				flag[5]++;
                pu8Data[u8i++] = I2C_ReadByte(BS8116A_IIC);
                if(u8i>=count)
                {
                    I2C_ClearFunc(BS8116A_IIC,I2cAck_En);        //读数据时,倒数第二个字节ACK关闭
                }else{
					I2C_SetFunc(BS8116A_IIC,I2cAck_En);
				}
                break;
            case 0x58:                                    //已接收到最后一个数据,NACK已返回
            case 0x38:                                    //在发送地址或数据时,仲裁丢失
            case 0x48:                                    //发送SLA+R后,收到一个NACK
            default:                                      //其他错误状态,重新发送起始条件
				flag[9]++;
                I2C_SetFunc(BS8116A_IIC,I2cStop_En);            //其他错误状态,重新发送起始条件
				goto FINISH;
        }
        I2C_ClearIrq(BS8116A_IIC);                               //清除中断状态标志位
		idx++;
    }
	FINISH:
	I2C_ClearIrq(BS8116A_IIC);                               //清除中断状态标志位
	rt_memcpy(dest,pu8Data,count);
    return 0;
}

void TK_ReadReg(key_setting_t * setting)
{
	uint8_t * pset = (uint8_t *)setting,i=0;
	TK_I2c_ReadReg(pset,REG_CFG_CNT,REG_CFG_ADDR);
}

void TK_WriteReg(key_setting_t * setting)
{
	uint8_t * pset = (uint8_t *)setting,i=0;
	uint16_t checksum = 0;
	TK_I2c_WriteReg(pset,REG_CFG_CNT+1,REG_CFG_ADDR);
}

uint16_t TK_GetKey(void)
{
	uint8_t pu8Data[2]={0};
	uint16_t key_status = 0;
	TK_I2c_ReadReg(pu8Data,2,KEY_ADDR1_8);
	key_status = pu8Data[1];
	key_status = key_status<<8 | pu8Data[0];
    return key_status;
}

结束。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值