#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