总线一:IIC( 三 )


清零 , 因为写入寄存器的字节被立即移入内部移位寄存器 。一旦移位寄存器非
空 ,  I2C就开始发送数据到总线 。
【总线一:IIC】6. 在第一个字节的发送过程中 , 软件可以写第二个字节到 , 此时TBE会被清零 。
7. 任何时候TBE被置1 , 软件都可以向寄存器写入一个字节 , 只要还有数据待发送 。
8. 在倒数第二个字节发送过程中 , 软件写入最后一个字节数据到来清除TBE标志
位 , 此后就不用关心TBE位的状态 。TBE位会在倒数第二个字节发送完成后被置起 , 直到
发送STOP结束位时被清零 。
9. 最后一个字节发送结束后 ,  I2C主机将BTC位置起 , 因为移位寄存器和寄存器此
时都为空 。软件此时应该配置STOP来发送一个STOP结束位 , 此后TBE和BTC状态位都
将被清0 。
主机接收模式如下图所示:
附上下面调的程序 , 调了好几个型号 , 大差不差 , 下面是的代码
.h
#ifndef __I2C_EE_H#define __I2C_EE_H#include "stm32f10x.h"/**************************I2C参数定义 , I2C1或I2C2********************************/#defineEEPROM_I2CxI2C1#defineEEPROM_I2C_APBxClock_FUNRCC_APB1PeriphClockCmd#defineEEPROM_I2C_CLKRCC_APB1Periph_I2C1#defineEEPROM_I2C_GPIO_APBxClock_FUNRCC_APB2PeriphClockCmd#defineEEPROM_I2C_GPIO_CLKRCC_APB2Periph_GPIOB#defineEEPROM_I2C_SCL_PORTGPIOB#defineEEPROM_I2C_SCL_PINGPIO_Pin_6#defineEEPROM_I2C_SDA_PORTGPIOB #defineEEPROM_I2C_SDA_PINGPIO_Pin_7/* STM32 I2C 快速模式 */#define I2C_Speed400000//*/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */#define I2Cx_OWN_ADDRESS70X0A/* AT24C01/02每页有8个字节 */#define I2C_PageSize8/* AT24C04/08A/16A每页有16个字节 *///#define I2C_PageSize16 /*等待超时时间*/#define I2CT_FLAG_TIMEOUT((uint32_t)0x1000)#define I2CT_LONG_TIMEOUT((uint32_t)(10 * I2CT_FLAG_TIMEOUT))/*信息输出*/#define EEPROM_DEBUG_ON0#define EEPROM_INFO(fmt,arg...)printf("<<-EEPROM-INFO->> "fmt"\n",##arg)#define EEPROM_ERROR(fmt,arg...)printf("<<-EEPROM-ERROR->> "fmt"\n",##arg)#define EEPROM_DEBUG(fmt,arg...)do{\if(EEPROM_DEBUG_ON)\printf("<<-EEPROM-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\}while(0)/* * AT24C02 2kb = 2048bit = 2048/8 B = 256 B* 32 pages of 8 bytes each** Device Address* 1 0 1 0 A2 A1 A0 R/W* 1 0 1 0 0000 = 0XA0* 1 0 1 0 0001 = 0XA1 *//* EEPROM Addresses defines */#define EEPROM_Block0_ADDRESS 0xA0/* E2 = 0 *///#define EEPROM_Block1_ADDRESS 0xA2 /* E2 = 0 *///#define EEPROM_Block2_ADDRESS 0xA4 /* E2 = 0 *///#define EEPROM_Block3_ADDRESS 0xA6 /* E2 = 0 */void I2C_EE_Init(void);void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite);uint32_t I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr);uint32_t I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite);uint32_t I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead);void I2C_EE_WaitEepromStandbyState(void);#endif /* __I2C_EE_H */
.c
/********************************************************************************* @filebsp_i2c_ee.c* @authorSTMicroelectronics* @version V1.0* @briefi2c EEPROM(AT24C02)应用函数bsp*******************************************************************************/ #include "./i2c/bsp_i2c_ee.h"#include "./usart/bsp_usart.h"uint16_t EEPROM_ADDRESS;static __IO uint32_tI2CTimeout = I2CT_LONG_TIMEOUT;static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode);/*** @briefI2C I/O配置* @param无* @retval 无*/static void I2C_GPIO_Config(void){GPIO_InitTypeDefGPIO_InitStructure; /* 使能与 I2C 有关的时钟 */EEPROM_I2C_APBxClock_FUN ( EEPROM_I2C_CLK, ENABLE );EEPROM_I2C_GPIO_APBxClock_FUN ( EEPROM_I2C_GPIO_CLK, ENABLE );/* I2C_SCL、I2C_SDA*/GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;// 开漏输出GPIO_Init(EEPROM_I2C_SCL_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;// 开漏输出GPIO_Init(EEPROM_I2C_SDA_PORT, &GPIO_InitStructure); }/*** @briefI2C 工作模式配置* @param无* @retval 无*/static void I2C_Mode_Configu(void){I2C_InitTypeDefI2C_InitStructure; /* I2C 配置 */I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;/* 高电平数据稳定 , 低电平数据变化 SCL 时钟线的占空比 */I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 =I2Cx_OWN_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;/* I2C的寻址模式 */I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;/* 通信速率 */I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;/* I2C 初始化 */I2C_Init(EEPROM_I2Cx, &I2C_InitStructure);/* 使能 I2C */I2C_Cmd(EEPROM_I2Cx, ENABLE);}/*** @briefI2C 外设(EEPROM)初始化* @param无* @retval 无*/void I2C_EE_Init(void){I2C_GPIO_Config(); I2C_Mode_Configu();/* 根据头文件i2c_ee.h中的定义来选择EEPROM的设备地址 */#ifdef EEPROM_Block0_ADDRESS/* 选择 EEPROM Block0 来写入 */EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;#endif#ifdef EEPROM_Block1_ADDRESS/* 选择 EEPROM Block1 来写入 */EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;#endif#ifdef EEPROM_Block2_ADDRESS/* 选择 EEPROM Block2 来写入 */EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;#endif#ifdef EEPROM_Block3_ADDRESS/* 选择 EEPROM Block3 来写入 */EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;#endif}/*** @brief将缓冲区中的数据写到I2C EEPROM中* @param*@arg pBuffer:缓冲区指针*@arg WriteAddr:写地址*@arg NumByteToWrite:写的字节数* @retval无*/void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite){u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;Addr = WriteAddr % I2C_PageSize;count = I2C_PageSize - Addr;NumOfPage =NumByteToWrite / I2C_PageSize;NumOfSingle = NumByteToWrite % I2C_PageSize;/* If WriteAddr is I2C_PageSize aligned*/if(Addr == 0) {/* If NumByteToWrite