#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