IIC--V3.0--TOUCH的那个KEY传统风格抽象OK

#include "HALI2C.h"
#include "gunit.h"
#define BIT0           0X01
#define BIT7           0X80

/IO//
/*2个脚 
其中 时钟 一直都是 输出 
而   数据 你TX就是 输出 你RX时候就 浮空输入 等待采集信号 
并且一般是你设置为高电平在变成输入等待从机拉低*/

void SET_SDA_OUT(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = I2C1_SDA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(I2C1_GPIO, &GPIO_InitStruct);
}
void SET_SDA_IN(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = I2C1_SDA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(I2C1_GPIO, &GPIO_InitStruct);
}

void SET_SCL_OUT(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = I2C1_SCL_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(I2C1_GPIO, &GPIO_InitStruct);
}
void SET_SCL_IN(void)/*基本不会使用*/
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = I2C1_SCL_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(I2C1_GPIO, &GPIO_InitStruct);
}
/IO//





/HL//
void i2c1_set_scl(void)
{//拉高时钟
  HAL_GPIO_WritePin(I2C1_GPIO, I2C1_SCL_Pin, GPIO_PIN_SET);
}
void i2c1_clr_scl(void)
{//拉低时钟
  HAL_GPIO_WritePin(I2C1_GPIO, I2C1_SCL_Pin, GPIO_PIN_RESET);
}
void i2c1_set_sda(void)
{//拉高数据
 HAL_GPIO_WritePin(I2C1_GPIO, I2C1_SDA_Pin, GPIO_PIN_SET);
}
void i2c1_clr_sda(void)
{//拉低数据
 HAL_GPIO_WritePin(I2C1_GPIO, I2C1_SDA_Pin, GPIO_PIN_RESET);
}
/HL//





/US//

void i2c1_delay_bit(void)
{
  	TIM7_Delay(50);//刘洋老师说的是5US 这个器件不只是为啥需要50US 
}

/US//






/ 开始IIC //
/*I2C_Init--操作GPIO-需要的2个脚都是上拉的输出*/
void I2C_Init(void)
{	
	GPIO_InitTypeDef GPIO_InitStruct = {0};

	GPIO_InitStruct.Pin = I2C1_SDA_Pin|I2C1_SCL_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(I2C1_GPIO, &GPIO_InitStruct);

	i2c1_set_scl();
	i2c1_set_sda();
}



/*产生起始信号*/
void I2C_Start(void)
{
	SET_SDA_OUT();/*必须设置OUT模式 最后找问题就是这里!!*/

	i2c1_set_sda();
	i2c1_set_scl();

	i2c1_delay_bit();
	i2c1_clr_sda();
	i2c1_delay_bit();
	i2c1_clr_scl();
	i2c1_delay_bit();
}

/*产生停止信号 OK*/
void I2C_Stop(void)
{
	SET_SDA_OUT();

	i2c1_clr_scl();
	i2c1_delay_bit();
	i2c1_clr_sda();
	i2c1_delay_bit();
	i2c1_set_scl();
	i2c1_delay_bit();
	i2c1_set_sda();
	i2c1_delay_bit();

}

/*主机产生应答信号ACK 主要是后面还有交互 比如读一串的时候 你拿到一个还没完就ACK*/
void I2C_Ack(void)
{
    SET_SDA_OUT();
    i2c1_clr_scl();
    i2c1_delay_bit();

    i2c1_clr_sda();//唯一的区别
    i2c1_delay_bit();

    i2c1_set_scl();
    i2c1_delay_bit();
    i2c1_clr_scl();
    i2c1_delay_bit();
}

/*主机不产生应答信号NACK 结束的时候*/
void I2C_NAck(void)
{
    SET_SDA_OUT();
    i2c1_clr_scl();
    i2c1_delay_bit();

    i2c1_set_sda();//唯一的区别
    i2c1_delay_bit();

    i2c1_set_scl();
    i2c1_delay_bit();
    i2c1_clr_scl();
    i2c1_delay_bit();
}


uint8_t i2c2_get_sda(void)
{//获得数据电平
//一般是我拉高SDA以后开始转变为浮空输入 等待从机拉低也就是1->0
//所以去读的话返回0就是从机应答了
	uint8_t Ret;
	
    SET_SDA_IN();
	if (HAL_GPIO_ReadPin(I2C1_GPIO, I2C1_SDA_Pin)== GPIO_PIN_SET)
		Ret= 1;
	else
		Ret= 0;

	SET_SDA_OUT();
	return Ret;
}


//等待从机应答信号
//返回值:1 接收应答失败
//		  0 接收应答成功
uint8_t I2C_Wait_Ack(void)
{
    uint8_t ack=0;

	i2c1_set_sda();
	i2c1_delay_bit();
	i2c1_set_scl();
	i2c1_delay_bit();
	#if 1  
	SET_SDA_IN();
	ack = HAL_GPIO_ReadPin(I2C1_GPIO,I2C1_SDA_Pin);
	SET_SDA_OUT();
	#else
	ack = i2c2_get_sda();
	#endif
	i2c1_clr_scl();
	i2c1_delay_bit();
	return ack;
}
void I2C_Send_Byte(uint8_t val)
{
	volatile uint8_t mark = BIT7;
	uint8_t i=0;

	i2c1_clr_scl();//拉低时钟开始数据传输
    i2c1_delay_bit();
    while(mark)
	{
		if (val & mark)
		i2c1_set_sda();
		else
        i2c1_clr_sda();

	    i2c1_delay_bit();
		i2c1_set_scl();
		i2c1_delay_bit();
		i2c1_clr_scl();
		i2c1_delay_bit();
		mark >>= 1;
	}
}

#if 1
unsigned char I2C_Read_Byte(unsigned char ack)
{
   unsigned char i=0,receive=0;

   SET_SDA_IN();
   for(i=0;i<8;i++)
   {
   	    i2c1_clr_scl();
		i2c1_delay_bit();
		i2c1_set_scl();
		receive<<=1;
		if(HAL_GPIO_ReadPin(I2C1_GPIO,I2C1_SDA_Pin))
		   receive++;
		i2c1_delay_bit();	
   }

   	if(ack==0)
	   	I2C_NAck();
	else
		I2C_Ack();

	return receive;
}
//上面是刘洋的写法 下面是陈强的写法 都是可以的 时序前面不是很严格
#else

unsigned char I2C_Read_Byte(unsigned char ack)
{
	volatile uint8_t receive = 0;
	uint8_t mask = BIT7;
	while(mask)
	{
		i2c1_set_sda();
		i2c1_set_scl();
	    i2c1_delay_bit();
		//if(HAL_GPIO_ReadPin(I2C1_GPIO,I2C1_SDA_Pin))//都可以
        if(i2c2_get_sda())
		   receive |= mask;
		i2c1_clr_scl();
		i2c1_delay_bit();
		mask >>= 1;
   }

	if (ack== TRUE)
		 i2c1_clr_sda();
	else
         i2c1_set_sda();
	i2c1_delay_bit();
	i2c1_set_scl();
	i2c1_delay_bit();
	i2c1_clr_scl();
	i2c1_delay_bit();
	return receive;
}

#endif


uint8_t sw_i2c_access_start(uint8_t SlaveAdr, char W0R1)
{
	volatile uint8_t dummy=5;
	uint8_t ack =0;
    
	if (W0R1 == 1)
		SlaveAdr |= BIT0;
	else
		SlaveAdr &= ~BIT0;

	while (dummy--)
    {
		I2C_Start();
		I2C_Send_Byte(SlaveAdr);
		ack = I2C_Wait_Ack();printf("sw_i2c_access_start:ack=%d\r\n",ack);
		if(ack==0)break;
		i2c1_delay_bit();
		I2C_Stop();
	}
	return !ack;/*如果ack=0标识TXRX成功了 我就返回1吧 反之是失败*/
}
 /* I2C and EZI2C slave address defines */
#define I2C_I2C_SLAVE_ADDR_POS    (0x01u)    /* 7-bit address shift */
#define I2C_I2C_SLAVE_ADDR_MASK   (0xFEu)    /* 8-bit address mask */
/* Return 8-bit address. The input address should be 7-bits */
#define I2C_GET_I2C_8BIT_ADDRESS(addr) (((unsigned long) ((unsigned long) (addr) << I2C_I2C_SLAVE_ADDR_POS)) & I2C_I2C_SLAVE_ADDR_MASK)
uint8_t cy3116_write(uint8_t slaveAdr,uint16_t subAdr,uint8_t *buff,uint16_t bufLen)
{
    volatile uint8_t dummy = 20;
	uint8_t ack=0;
    uint8_t slaveAddress = I2C_GET_I2C_8BIT_ADDRESS(slaveAdr);
	while(dummy--)
    {
//1--access_start
		if (sw_i2c_access_start(slaveAddress, 0) == FALSE)
        {
			continue;
		}
//2--执行TXRX
		I2C_Send_Byte(subAdr);
		ack = I2C_Wait_Ack();
        if(ack!=0)continue;
//3--执行TX		
		for( uint16_t i =0; i < bufLen ;i++)
        {			
	       I2C_Send_Byte(buff[i]);
           ack = I2C_Wait_Ack();
           if(ack!=0)goto err;
		}
		break;
	}
    
    if( dummy == 0xFF)
    {
        printf("I2C Timer out\r\n");
    }
    
	I2C_Stop();	  
    
    return 1;
err:
    printf("I2C send err\r\n");

    return 0;
}


static uint8_t cy3116_read(uint8_t slaveAdr,uint16_t subAdr,uint8_t *buff,uint16_t bufLen)
{
    volatile uint8_t dummy = 20;
	uint8_t ack=0;
	while(dummy--)
	{
//1--access_start 写0
		if (sw_i2c_access_start(slaveAdr, 0) == FALSE)
        {
			continue;
		}

//2--执行TXRX
		I2C_Send_Byte(subAdr);
		ack = I2C_Wait_Ack();
        if(ack!=0)continue;


//3--access_start	读1	
		if (sw_i2c_access_start(slaveAdr, 1) == FALSE)
        {
			continue;
		}
//4--开始RX每次收到一个我就ACK一下最后一个就不ACK了		
		while(bufLen--)
        {
			*buff = I2C_Read_Byte((bufLen>0)?1:0);
			buff++;
		}
		break;
	}
	I2C_Stop();	   
    
    return 1;
}


unsigned char CY8CMBR3116_config[128] = {
    0xF8u, 0x7Fu, 0xF8u, 0x7Fu, 0x00u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x7Fu, 0x7Fu, 0x7Fu, 0x80u,
    0x80u, 0x80u, 0x80u, 0x80u, 0x80u, 0x80u, 0x80u, 0x80u,
    0x80u, 0x80u, 0x80u, 0x7Fu, 0x03u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
    0x05u, 0x00u, 0x00u, 0x02u, 0x00u, 0x02u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x21u, 0x01u, 0x01u,
    0x00u, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
    0xFFu, 0x00u, 0x00u, 0x00u, 0x24u, 0x03u, 0x01u, 0x59u,
    0x00u, 0x37u, 0x01u, 0x00u, 0x00u, 0x0Au, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
    0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0xD9u, 0x55u
};
uint8_t saveCmd = 0x02;
uint8_t resert = 0xFF;
char __HTK_I2C_Read_optimal_touch_keyval(unsigned char  *pKeyVal)
{
	#define DEVICE_ADDR    (0x37u)
    unsigned char send;
    uint8_t id;
    char ack=0;
#if 1

    cy3116_read((DEVICE_ADDR<<1),0x8F,&id,1);
	printf("id=[%d]\r\n",id);

#else
    sw_i2c_access_start((DEVICE_ADDR<<1),0);

	I2C_Send_Byte(0x8F);
	ack = I2C_Wait_Ack();printf("I2C_Wait_Ack ack=%d\r\n",ack);

    sw_i2c_access_start((DEVICE_ADDR<<1),1);

	printf("[%d]\r\n",I2C_Read_Byte(0));

	I2C_Stop();	

#endif

    cy3116_write( DEVICE_ADDR ,0x00,CY8CMBR3116_config,128);
    HAL_Delay(100);

    cy3116_write( DEVICE_ADDR ,0x86,&saveCmd,1);
    HAL_Delay(100);

    cy3116_write( DEVICE_ADDR ,0x86,&resert,1);
    HAL_Delay(100);
	return 1;

 }


/*整理流程是:
 I2C_Start--发送器件地址【也就是(DEVICE_ADDR<<1)我们是写就是直接发 因为BIT0此时100%是0】--等待ack = I2C_Wait_Ack()--
 此时ack1必须是0 也即是从机必须应答【我拉高的SDA必须从机拉低】如果失败就循环操作
 
 从机应答以后继续发送0X8F这个就是一个文档的命令 发出去 从机一般很久应答
 
 再去发送读芯片ID的命令也就是 I2C_Start--发送器件地址【也就是(DEVICE_ADDR<<1)这里我们是读 不是直接发 需要暴力BIT0为1】--
 等待从机回答啥 这个就是ID
 如果ID不对 就需要检测延时50US对不对
 */
 
/*
开始抽象函数 我发消息总是 I2C_Start--I2C_Send_Byte--I2C_Wait_Ack 可以总结一个新函数
OLD:
dummy=5;
while (dummy--)
{
	I2C_Start();
	send =  (DEVICE_ADDR<<1) | BIT0;
	I2C_Send_Byte(  send  ) ;// 发送器件地址 读
	ack = I2C_Wait_Ack();printf("ack=%d\r\n",ack);
	if(ack==0)break;
	i2c1_delay_bit();
	I2C_Stop();
}

NEW:
//参数是从机地址 后面0标识写 1标识读
uint8_t sw_i2c_access_start(uint8_t SlaveAdr, char W0R1)
{
	volatile uint8_t dummy=5;
	uint8_t ack =0;
    
	if (W0R1 == 1)
		SlaveAdr |= BIT0;
	else
		SlaveAdr &= ~BIT0;

	while (dummy--)
    {
		I2C_Start();
		I2C_Send_Byte(SlaveAdr);
		ack = I2C_Wait_Ack();printf("ack=%d\r\n",ack);
		if(ack==0)break;
		i2c1_delay_bit();
		I2C_Stop();
	}
	return ack;
}



*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值