第一步,初始化AT24C02
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStructure;//IIC初始化
GPIO_InitTypeDef GPIO_InitStructure; //GPIO初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);//使能IIC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);//使能GPIOB和复用IO时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;//硬件IIC1:PB6->SCL,PB7->SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//频率50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//复用开漏模式
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);//清楚IIC1原来配置
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//设置为IIC模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//占空比:low/high=2:1
I2C_InitStructure.I2C_OwnAddress1 = 0x00;//主机地址:0x00
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//IIC应答使能
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//7位地址应答
I2C_InitStructure.I2C_ClockSpeed = 100000;//时钟频率100KHZ
I2C_Cmd(I2C1, ENABLE);//IIC使能
I2C_Init(I2C1, &I2C_InitStructure);
I2C_AcknowledgeConfig(I2C1, ENABLE);//IIC应答使能
}
第二步,IIC写数据
参考主机发送时序图
uint8_t I2C_WriteOneByte(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t value)
{
I2C_GenerateSTART(I2Cx, ENABLE);//产生起始位
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));//等待EV5
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);//发送7位从机地址(I2C_Addr:0xA0),主机发送模式
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//等待EV6
I2C_SendData(I2Cx, addr);//发送写入数据地址
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//等待EV8_2
I2C_SendData(I2Cx, value);//发送数据
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//等待EV8_2
I2C_GenerateSTOP(I2Cx, ENABLE);//产生停止位
I2C_AcknowledgePolling(I2Cx,I2C_Addr);//等待从机应答
I2C_delay(1000);
return 0;
}
uint8_t I2C_Write(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num)
{
uint8_t err=0;
while(num--)//循环一字节一字节写入数据
{
if(I2C_WriteOneByte(I2Cx, I2C_Addr,addr++,*buf++))
{
err++;
}
}
if(err)
return 1;
else
return 0;
}
第三步,IIC读数据
参考主机接收时序图
uint8_t I2C_Read(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num)
{
if(num==0)
return 1;
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));//总线上无数据通信,则继续执行
I2C_AcknowledgeConfig(I2Cx, ENABLE);//使能I2C应答
I2C_GenerateSTART(I2Cx, ENABLE);//使能I2C开始
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));//等待EV5
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);//发送设备7位地址,主发送模式
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//等待 EV6
I2C_SendData(I2Cx, addr);//发送I2C数据地址
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//等待EV8_2
I2C_GenerateSTART(I2Cx, ENABLE);//使能I2C开始
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));//等待EV5
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Receiver);//发送设备7位地址,主接收模式
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//等待 EV6
while (num)
{
if(num==1)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);//失能应答
I2C_GenerateSTOP(I2Cx, ENABLE);//产生停止位
}
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); //等待EV7
*buf = I2C_ReceiveData(I2Cx);//接收一字节数据
buf++;//buf指针后移
num--;//剩余数据-1
}
I2C_AcknowledgeConfig(I2Cx, ENABLE);//使能应答
return 0;
}
第四步,等待从机应答
static void I2C_AcknowledgePolling(I2C_TypeDef *I2Cx,uint8_t I2C_Addr)
{
do
{
I2C_GenerateSTART(I2Cx, ENABLE);//使能I2Cx开始
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);//7位地址,主发送模式
}while(!(I2C_ReadRegister(I2Cx, I2C_Register_SR1) & 0x0002));//未发送完成,则继续循环执行
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);//清除应答标志位(SR1)
I2C_GenerateSTOP(I2Cx, ENABLE);//产生停止位
}
参考实验
#include "stm32f10x.h"
#include "24C02.h"
#include <string.h>
#include <stdio.h>
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
void USART_Configuration(void);
void Delay (uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
int main(void)
{
uint16_t Addr;
uint8_t WriteBuffer[256],ReadBuffer[256];
USART_Configuration();
I2C_Configuration();
for(Addr=0; Addr<256; Addr++)
WriteBuffer[Addr]=Addr; /* 填充WriteBuffer */
/* 开始向AT24C02写入数据 */
printf("\r\n EEPROM 24C02 Write Test \r\n");
I2C_Write(I2C1,ADDR_24LC02,0,WriteBuffer,sizeof(WriteBuffer) );
printf("\r\n EEPROM 24C02 Write Test OK \r\n");
/* 开始读取AT24C02的数据 */
printf("\r\n EEPROM 24C02 Read Test \r\n");
I2C_Read(I2C1,ADDR_24LC02,0,ReadBuffer,sizeof(WriteBuffer) );
if( memcmp(WriteBuffer,ReadBuffer,sizeof(WriteBuffer)) == 0 ) /* 匹配数据 */
{
printf("\r\n EEPROM 24C02 Read Test OK\r\n");
for(int i=0;i<256;i++){
printf("%d\n",ReadBuffer[i]);
Delay(500000);
}
printf("\r\n EEPROM 24C02 Read Test END\r\n");
}
else
printf("\r\n EEPROM 24C02 Read Test False\r\n");
}
实验现象