使用gpio模拟i2c时序代码,亲测可用

参考:https://blog.csdn.net/huoyu_/article/details/53373815

 

这些代码是框架层的代码,无需修改直接使用即可/

#define DELAY 1
typedef unsigned char u8;
typedef unsigned short u16;


/* 这些代码是框架,直接使用即可 */


// 定义一个延时xms毫秒的延时函数
void delay(unsigned int xms)  // xms代表需要延时的毫秒数
{
    unsigned int x,y;
    for(x = xms; x > 0; x--)
        for(y = 110; y > 0; y--);
}




/******************************start*****************************************/
static void i2c_start(void)
{
	gpio_direction_output(SDA_PIN, 1);
	gpio_direction_output(CLK_PIN, 1);
	delay(DELAY);
	gpio_set_value(SDA_PIN, 0);
	delay(DELAY);
	gpio_set_value(CLK_PIN, 0);
	delay(DELAY);
	
}





/**********************************************stop****************************************/
static void i2c_stop(void)
{
	gpio_set_value(CLK_PIN, 0);
	gpio_set_value(SDA_PIN, 0);
	delay(DELAY);

	gpio_set_value(CLK_PIN, 1);
	delay(DELAY);
	gpio_set_value(SDA_PIN, 1);
	delay(DELAY);

}




/********************************send_ack****************************************/
/* 参数ack为1时发送NACK,参数ack为0时表示发送ACK */
static void i2c_send_ack(u8 ack)
{
	if(ack)
		gpio_direction_output(SDA_PIN, 1);
	else
		gpio_direction_output(SDA_PIN, 0);
	delay(DELAY);

	gpio_set_value(CLK_PIN, 1);
	delay(DELAY);
	gpio_set_value(CLK_PIN, 0);
	delay(DELAY);
}





/********************************receive_ack*********************************/
/* 返回1表示无效ACK,返回0表示有效ACK */
static u8 i2c_receive_ack(void)
{
	u8 rc = 0;
	gpio_direction_input(SDA_PIN);
	gpio_set_value(CLK_PIN, 1);
	delay(DELAY);

	/* 获取ack信号,如果信号为低,则为有效ACK */
	if(gpio_get_value(SDA_PIN))
	{
		rc = 1;
	}
	gpio_set_value(CLK_PIN, 0);
	gpio_direction_output(SDA_PIN, 1);
	return rc;
}




/********************************send****************************************/
/* 返回值为0,表示接收到ACK信号,表示发送成功
 * 返回值为1,表示没有收到ACK信号,表示发送失败
 */
static u8 i2c_send_byte(u8 send_byte)
{
	u8 rc = 0;
	u8 out_mask = 0x80;
	u8 value;
	u8 count = 8;
	while(count > 0)
	{
		value = ((send_byte & out_mask) ? 1 : 0);
		if (value == 1) 
		{
			gpio_set_value(SDA_PIN, 1);
		}
		else 
		{
			gpio_set_value(SDA_PIN, 0);
		}
		delay(DELAY);

		gpio_set_value(CLK_PIN, 1);
		delay(DELAY);
		gpio_set_value(CLK_PIN, 0);
		delay(DELAY);
		out_mask >>= 1;
		count--;
	}

	gpio_set_value(SDA_PIN, 1);
	rc = i2c_receive_ack();
	return rc;
}





/**********************************************receive*************************************/
static void i2c_read_byte(u8 *buffer, u8 ack)
{
	u8 count = 0x08;
	u8 data = 0x00;
	u8 temp = 0;

	gpio_direction_input(SDA_PIN);
	while(count > 0) 
	{
		gpio_set_value(CLK_PIN, 1);
		delay(DELAY);
		temp = gpio_get_value(SDA_PIN);
		data <<= 1;
		if (temp)
		data |= 0x01;
		gpio_set_value(CLK_PIN, 0);
		delay(DELAY);
		count--;
	}
	i2c_send_ack(ack);//0 = ACK, 1 = NACK
	*buffer = data;
}






//向client的某个寄存器写入多个字节,len是要写入的数据的长度??? 
/***********************************************write_bytes********************************/
/* 返回值为0表示收到ACK信号,发送成功
 * 返回值为1表示没有收到ACK信号,发送失败
 */
static u8 i2c_write(u8 device_id, u8 reg_address, u8* data, u8 len)
{
	u8 rc = 0;
	u8 i;
	i2c_start();

	rc |= i2c_send_byte( (device_id << 1) | 0x00 );
	if ( 0 != rc )
	{
		printf("i2c_send_byte failed, no ack back\n");
		return rc;
	}
	delay(10);

	rc |= i2c_send_byte(reg_address);
	if ( 0 != rc )
	{
		printf("i2c_send_byte failed, no ack back\n");
		return rc;
	}
	delay(10);

	if(data==NULL ||0==len)
	{
		i2c_stop();
		return rc;
	}
	delay(10);

	for(i=0; i<len; i++) 
	{
		rc |= i2c_send_byte(*data);		
		delay(10);
		if ( 0 != rc )
		{
			printf("i2c_send_byte failed, no ack back\n");
			return rc;
		}
		
		data++;
	}

	i2c_stop();

	return rc;
}




//从某个register中读取len个字节放在长度为len的缓冲区buffer中??? 
/***********************************************read_bytes********************************/
/* 返回值为0表示收到ACK信号,发送成功
 * 返回值为1表示没有收到ACK信号,发送失败
 */
static u8 i2c_read(u8 device_id, u8 reg_address, u8 *buffer, u16 len)
{
	u8 rc = 0;
	u16 i;
	i2c_start();
	rc |= i2c_send_byte( (device_id << 1) | 0x00 );
	if ( 0 != rc )
	{
		printf("i2c_send_byte failed, no ack back\n");
		return rc;
	}
	delay(10);
	rc |= i2c_send_byte(reg_address);
	if ( 0 != rc )
	{
		printf("i2c_send_byte failed, no ack back\n");
		return rc;
	}
	
	delay(10);
	i2c_start();//restart I2C
	rc |= i2c_send_byte( (device_id << 1) | 0x01 );
	if ( 0 != rc )
	{
		printf("i2c_send_byte failed, no ack back\n");
		return rc;
	}
	
	delay(10);
	for(i=0;i<len;i++) 
	{
		i2c_read_byte(buffer++, !(len-i-1));// !(len-i-1)? 这个用来保证在读到每个字节后发送一个ACK并能在最后一个字节读完后发送一个NACK
		delay(10);

	}

	i2c_stop();
	return rc;
}



 

以下代码需要根据自己的平台实现gpio的拉高拉低///



/* 设置gpio为输出功能,并且设置输出值为value */
static void gpio_direction_output(unsigned int gpio, int value)
{

    //实现具体平台的代码
}


/* 设置gpio为输入功能 */
static void gpio_direction_input(unsigned int gpio)
{

    //实现具体平台的代码
}



/* 设置gpo的值为value */
static void gpio_set_value(unsigned int gpio, int value)
{
    //实现具体平台的代码
	
}


//返回gpio的值
static unsigned int gpio_get_value(unsigned int gpio)
{
    //实现具体平台的代码

}

 

 

 

 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值