Alkaitu:STM32的IO模拟I2C

#include "user_i2c.h"
#include "stm32f10x.h"
#include "user_config.h"


/*移植需改动三处*/

/***************************************************************/
/*i2c的IO脚位宏定义,移植改动第一处,如增加按格式加即可*/
/***************************************************************/
#define SCL1_SET_1       GPIO_SetBits(GPIOB, GPIO_Pin_6)
#define SCL1_SET_0       GPIO_ResetBits(GPIOB, GPIO_Pin_6)

#define SDA1_SET_1       GPIO_SetBits(GPIOB, GPIO_Pin_7)
#define SDA1_SET_0       GPIO_ResetBits(GPIOB, GPIO_Pin_7)
#define SDA1_READ_BIT    GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)
/***************************************************************/


/***************************************************************/
/*i2c数量和延迟时间设置,移植改动第二处,可增加数量和调节时间*/
/***************************************************************/
#define I2C_DELAY_TIME 50
#define I2C_NUM_ALL 1
/***************************************************************/


/***************************************************************/
/*i2c的IO脚位初始化,移植改动第三处*/
/***************************************************************/
void user_i2c_init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);
}
/***************************************************************/


/**********************************************************************************************/
/*i2c的SCL引脚电平设置*/
/**********************************************************************************************/
void user_set_scl(unsigned char i2c_id,unsigned char bit_value)
{
	switch(i2c_id)                                                            //设定那一组模拟IO
	{
		case 1:if(bit_value != 0){SCL1_SET_1;user_delay_us(I2C_DELAY_TIME);}
			     else{SCL1_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		
		#if I2C_NUM_ALL > 1
		case 2:if(bit_value != 0){SCL2_SET_1;user_delay_us(I2C_DELAY_TIME);}
			     else{SCL2_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		#endif
		
		#if I2C_NUM_ALL > 2
		case 3:if(bit_value != 0){SCL3_SET_1;user_delay_us(I2C_DELAY_TIME);}
			     else{SCL3_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		#endif
		
		#if I2C_NUM_ALL > 3
		case 4:if(bit_value != 0){SCL4_SET_1;user_delay_us(I2C_DELAY_TIME);}
			     else{SCL4_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		#endif
		
		#if I2C_NUM_ALL > 4
		case 5:if(bit_value != 0){SCL5_SET_1;user_delay_us(I2C_DELAY_TIME);}
			     else{SCL5_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
    #endif					 
	}
}
/**********************************************************************************************/


/**********************************************************************************************/
/*i2c的SDA引脚电平设置*/
/**********************************************************************************************/
void user_set_sda(unsigned char i2c_id,unsigned char bit_value)
{
	switch(i2c_id)
	{
		case 1: if(bit_value != 0){SDA1_SET_1;user_delay_us(I2C_DELAY_TIME);}
			      else{SDA1_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		
		#if I2C_NUM_ALL > 1
		case 2: if(bit_value != 0){SDA2_SET_1;user_delay_us(I2C_DELAY_TIME);}
			      else{SDA2_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		#endif
		
		#if I2C_NUM_ALL > 2
		case 3: if(bit_value != 0){SDA3_SET_1;user_delay_us(I2C_DELAY_TIME);}
			      else{SDA3_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		#endif
		
		#if I2C_NUM_ALL > 3
		case 4: if(bit_value != 0){SDA4_SET_1;user_delay_us(I2C_DELAY_TIME);}
			      else{SDA4_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
		#endif
		
		#if I2C_NUM_ALL > 4
		case 5: if(bit_value != 0){SDA5_SET_1;user_delay_us(I2C_DELAY_TIME);}
			      else{SDA5_SET_0;user_delay_us(I2C_DELAY_TIME);};break;
    #endif					 
	}
}
/**********************************************************************************************/


/**********************************************************************************************/
/*i2c的读取SDA引脚电平*/
/**********************************************************************************************/
unsigned char user_read_sda(unsigned char i2c_id)
{
	unsigned char bit_value;
	switch(i2c_id)
	{
		case 1: bit_value = SDA1_READ_BIT;user_delay_us(I2C_DELAY_TIME);
		        break;
		
		#if I2C_NUM_ALL > 1
		case 2: bit_value = SDA2_READ_BIT;user_delay_us(I2C_DELAY_TIME);
		        break;
		#endif
		
		#if I2C_NUM_ALL > 2
		case 3: bit_value = SDA3_READ_BIT;user_delay_us(I2C_DELAY_TIME);
		        break;
		#endif
		
		#if I2C_NUM_ALL > 3
		case 4: bit_value = SDA4_READ_BIT;user_delay_us(I2C_DELAY_TIME);
		        break;
		#endif
		
		#if I2C_NUM_ALL > 4
		case 5: bit_value = SDA5_READ_BIT;user_delay_us(I2C_DELAY_TIME);
		        break;
    #endif					 
	}
	return bit_value;
}
/*********************************************************************************************/


/***************************************************************/
/*i2c起始信号*/
/***************************************************************/
void user_i2c_start(unsigned char i2c_id)
{
	user_set_sda(i2c_id,1);
	user_set_scl(i2c_id,1);
	user_set_sda(i2c_id,0);
	user_set_scl(i2c_id,0);
}
/***************************************************************/


/***************************************************************/
/*i2c停止信号*/
/***************************************************************/
void user_i2c_stop(unsigned char i2c_id)
{
	user_set_sda(i2c_id,0);
	user_set_scl(i2c_id,1);
	user_set_sda(i2c_id,1);
}
/***************************************************************/


/***************************************************************/
/*i2c发送一个字节*/
/***************************************************************/
void user_i2c_send_byte(unsigned char i2c_id,unsigned char byte)
{
	unsigned char i;
	for (i = 0; i < 8; i ++)
	{
		if((byte & (0x80 >> i)) != 0)     //高位先行
		{
		  user_set_sda(i2c_id,1);			
		}
		else
		{
		  user_set_sda(i2c_id,0); 
		}
	  user_set_scl(i2c_id,1);
		user_set_scl(i2c_id,0);
	}
}
/***************************************************************/


/***************************************************************/
/*i2c接收一个字节*/
/***************************************************************/
unsigned char user_i2c_receive_byte(unsigned char i2c_id)
{
	unsigned char i,byte = 0x00;
	user_set_sda(i2c_id,1);
	for(i = 0; i < 8; i ++)
	{
		user_set_scl(i2c_id,1);
		if(user_read_sda(i2c_id) != 0)
		{
		  byte |= (0x80 >> i);
		}
		else
		{
		  byte &= (~(0x80 >> i));
		}
		user_set_scl(i2c_id,0);
	}
	return byte;
}
/***************************************************************/


/********************************************************************/
/*i2c发送应答信号ack*/
/********************************************************************/
void user_i2c_send_ack(unsigned char i2c_id,unsigned char ack_bit)
{
	user_set_sda(i2c_id,ack_bit);
	user_set_scl(i2c_id,1);
	user_set_scl(i2c_id,0);
}
/********************************************************************/


/***************************************************************/
/*i2c接收应答信号ack*/
/***************************************************************/
unsigned char user_i2c_receive_ack(unsigned char i2c_id)
{
	unsigned char ackbit;
	user_set_sda(i2c_id,1);
	user_set_scl(i2c_id,1);
	ackbit = user_read_sda(i2c_id);
	user_set_scl(i2c_id,0);
	return ackbit;
}
/***************************************************************/


/***********************************************************************************************************************************/
/*指定地址读,七位寻址,最后一位:1 读数据, 0 写数据,  重要:发送一定要给应答,接收也要给应答*/
/***********************************************************************************************************************************/
unsigned char user_i2c_read_reg(unsigned char i2c_id,unsigned char device_address,unsigned char reg_address)
{
	unsigned char i2c_receive_byte_data;
	
	user_i2c_start(i2c_id);                               //发送起始信号
	
	user_i2c_send_byte(i2c_id,device_address);            //发送寻址从设备地址
	user_i2c_receive_ack(i2c_id);                         //接收应答信号
	
	user_i2c_send_byte(i2c_id,reg_address);               //发送寻址从设备的寄存器地址
	user_i2c_receive_ack(i2c_id);                         //接收应答信号
	
	user_i2c_start(i2c_id);                               //发起始信号,此时写操作改成读操作,在当前寄存器地址操作 
	
	user_i2c_send_byte(i2c_id,(device_address | 0x01));   //发送寻址从设备地址,从设备地址最后一位设置成1,设置成读数据
	user_i2c_receive_ack(i2c_id);                         //接收应答信号
	
	i2c_receive_byte_data = user_i2c_receive_byte(i2c_id);   //接收从设备发送的数据
	user_i2c_send_ack(i2c_id,1);                             //发送非应答信号,结束接收
	
	user_i2c_stop(i2c_id);                                   //发送停止信号
	
	return i2c_receive_byte_data;                            //返回接收一个字节数据
}
/***********************************************************************************************************************************/


/***********************************************************************************************************************************/
/*指定地址写,七位寻址,最后一位:1 读数据, 0 写数据*/
/***********************************************************************************************************************************/
void user_i2c_write_reg(unsigned char i2c_id,unsigned char device_address,unsigned char reg_address,unsigned char data)
{
  user_i2c_start(i2c_id);
	
	user_i2c_send_byte(i2c_id,device_address);
	user_i2c_receive_ack(i2c_id);
	
	user_i2c_send_byte(i2c_id,reg_address);
	user_i2c_receive_ack(i2c_id);
	
	/**/
	user_i2c_send_byte(i2c_id,data);                                 
	user_i2c_receive_ack(i2c_id);
	
	user_i2c_stop(i2c_id);
}
/************************************************************************************************************************/



/*******************************************************************************************/
/*测试从设备寻址响应*/
/*******************************************************************************************/
unsigned char user_i2c_test_ack(unsigned char i2c_id,unsigned char device_address)
{
	unsigned char i2c_receive_ack;
	
	user_i2c_start(i2c_id);
	
	user_i2c_send_byte(i2c_id,device_address);
	i2c_receive_ack = user_i2c_receive_ack(i2c_id);
	
	user_i2c_stop(i2c_id);
	
	return i2c_receive_ack;
}
/******************************************************************************************/










#ifndef _user_i2c_h_
#define _user_i2c_h_



/*头文件移植无需改动*/

/******************************************************************************************/
/*i2c引脚初始化函数,移植需在.C文件改动*/
/******************************************************************************************/

void user_i2c_init(void);

/******************************************************************************************/


/******************************************************************************************/
/*移植无需改动,函数实现I2C的脚位电平设置,无需改动*/
/******************************************************************************************/

void user_set_scl(unsigned char i2c_id,unsigned char bit_value); /*i2c的SCL引脚电平设置*/
void user_set_sda(unsigned char i2c_id,unsigned char bit_value); /*i2c的SDA引脚电平设置*/
unsigned char user_read_sda(unsigned char i2c_id);               /*i2c的读取SDA引脚电平*/

/*******************************************************************************************/



/*******************************************************************************************/
/*移植无需改动,函数实现I2C的时序,无需改动*/
/********************************************************************************************/

void user_i2c_start(unsigned char i2c_id);                             /*i2c起始信号*/
void user_i2c_stop(unsigned char i2c_id);                              /*i2c停止信号*/

void user_i2c_send_byte(unsigned char i2c_id,unsigned char byte);      /*i2c发送一个字节*/
unsigned char user_i2c_receive_ack(unsigned char i2c_id);              /*i2c接收应答信号ack*/

void user_i2c_send_ack(unsigned char i2c_id,unsigned char ack_bit);    /*i2c发送应答信号ack*/
unsigned char user_i2c_receive_byte(unsigned char i2c_id);             /*i2c接收一个字节*/

/*********************************************************************************************/



/***********************************************************************************************************************/
/*实际IO模拟主要引用这三个函数,无需改动*/
/************************************************************************************************************************/

/*指定地址读*/ 
unsigned char user_i2c_read_reg(unsigned char i2c_id,unsigned char device_address,unsigned char reg_address);          


/*指定地址写*/
void user_i2c_write_reg(unsigned char i2c_id,unsigned char device_address,unsigned char reg_address,unsigned char data); 


/*测试从设备寻址响应*/
unsigned char user_i2c_test_ack(unsigned char i2c_id,unsigned char device_address);                                     

/*************************************************************************************************************************/


#endif




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值