是AT24C02
我的代码如下:
bsp_i2c.c文件
#include "bsp_i2c.h"
void I2C_EE_CONFIG(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
//打开I2C的GPIO的Clock
EEPROM_I2C_GPIO_APBxClkCmd(EEPROM_SCL_GPIO_CLK |EEPROM_SDA_GPIO_CLK ,ENABLE);//等同于 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//打开I2C的外设的Clock
EEPROM_I2C_APBxClkCmd(RCC_APB1Periph_I2C1,ENABLE);//等同于 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
//配置I2C的GPIO的SCL引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);//配置到寄存器中
//配置I2C的GPIO的SDA引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB,&GPIO_InitStructure);//配置到寄存器中
//配置I2C的工作模式
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;//使能应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;//指定地址的长度
I2C_InitStructure.I2C_ClockSpeed = EEPROM_I2C_BAUDRATE; //配置时钟频率 单位是波特率
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ;//配置时钟占空比
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1 = STM32_I2C_OWN_ADDR; //为7位地址 要和总线上的设备地址都不一样 这是STM32的IIC自身设备地址 总线上唯一即可
I2C_Init(EEPROM_I2C,&I2C_InitStructure);//配置到寄存器中
//使能I2C
I2C_Cmd(EEPROM_I2C,ENABLE);
}
void EEPROM_Byte_Write(uint8_t addr,uint8_t data){//EEPROM的设备地址已经在里面默认了
//发送起始信号
I2C_GenerateSTART(I2C1,ENABLE);
//检测EV5
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);//I2C_GetFlagStatus(I2C1,I2C_FLAG_SB);
//发送设备地址
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
// EV8事件很普遍 所以只用EV6检测就可以
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR);//I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR);
//发送要操作的EEPROM的存储单元地址
I2C_SendData(I2C1,addr);
//检测EV8事件
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR)//I2C_GetFlagStatus(I2C1,I2C_FLAG_TXE);
//EV8事件被检测到 发送要存储的数据
I2C_SendData(I2C1,data);
//检测EV8_2事件 以便结束
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);
//数据传输完成
I2C_GenerateSTOP(I2C1,ENABLE);
//
}
//等待EEPROM的处理好内部时序时用GET FLAG 真正的读取数据时还是要用事件Event
void EEPROM_WaitForWriteEnd(void)
{
do{
I2C_GenerateSTART(I2C1,ENABLE);
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_SB ) == RESET);
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
}while(I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR) == RESET);
I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
}
//从EEPROM读取数据
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead)
{
//产生起始信号
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
//EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);
//EV6事件被检测到,发送要操作的存储单元地址
I2C_SendData (EEPROM_I2C,addr);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);
//第二次起始信号
//产生起始信号
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
//EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Receiver);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR);
while(numByteToRead)
{
//EV7事件被检测到
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR);
//EV7事件被检测到,即数据寄存器有新的有效数据
*data = I2C_ReceiveData(EEPROM_I2C);
if(numByteToRead == 1)
{
//如果为最后一个字节
I2C_AcknowledgeConfig (EEPROM_I2C,DISABLE);
}
data++;
numByteToRead--;
}
//数据传输完成
I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
//重新配置ACK使能,以便下次通讯
I2C_AcknowledgeConfig (EEPROM_I2C,ENABLE);
}
//向EEPROM写入多个字节(页写入),每次写入不得超过8个字节
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite){
I2C_GenerateSTART(I2C1,ENABLE);
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR);
I2C_SendData(I2C1,addr);
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR);
while(numByteToWrite){
I2C_SendData(I2C1,*data);
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR);
data++;
numByteToWrite--;
}
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR );
I2C_GenerateSTOP(I2C1,ENABLE);
}
bsp_i2c.h文件
#ifndef __BSP_I2C_H
#define __BSP_I2C_H
#include "stm32f10x.h"
#include <stdio.h>
//EEPROM设备地址
#define EEPROM_ADDR 0xA0
//I2C地址
#define STM32_I2C_OWN_ADDR 0X5F//要和EEPROM设备地址不一样
//I2C EEPROM的引脚定义
#define EEPROM_I2C I2C1
#define EEPROM_I2C_CLK RCC_APB1Periph_I2C1
#define EEPROM_I2C_APBxClkCmd RCC_APB1PeriphClockCmd
#define EEPROM_I2C_BAUDRATE 400000
//IIC GPIO 引脚宏定义
#define EEPROM_SCL_GPIO_CLK (RCC_APB2Periph_GPIOB)
#define EEPROM_SDA_GPIO_CLK (RCC_APB2Periph_GPIOB)
#define EEPROM_I2C_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define EEPROM_I2C_SCL_GPIO_PORT GPIOB
#define EEPROM_I2C_SCL_GPIO_PIN GPIO_Pin_6
#define EEPROM_I2C_SDA_GPIO_PORT GPIOB
#define EEPROM_I2C_SDA_GPIO_PIN GPIO_Pin_7
void I2C_EE_CONFIG(void);
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead);
void EEPROM_Byte_Write(uint8_t addr,uint8_t data);
void EEPROM_WaitForWriteEnd(void);
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite);
#endif /* __BSP_I2C_H */
main.c文件
#include &quot;stm32f10x.h&quot;
#include &quot;bsp_led.h&quot;
#include &quot;bsp_usart.h&quot;
#include &quot;./i2c/bsp_i2c.h&quot;
//1.初始化I2C相关的GPIO
//2.配置I2C外设的工作模式
//3.编写I2C写入EEPROM的ByteWrite函数
//4.编写I2C读取EEPROM的RandomRead函数
//5.使用read函数及write函数进行读写校验
//6.编写pagewrite及seqread函数并使用 校验
/**
* @brief 主函数
* @param 无
* @retval 无
*/
uint8_t readData[10] = {0};
int main(void)
{
USART_Config();
printf( &quot;这是一个IIC通讯实验\n&quot; );
I2C_EE_CONFIG();
EEPROM_Byte_Write(8,17);
//这里必须加一个等待EEPROM处理自身内部时序的函数 由于STM32速度很快 外设速度慢 在写入字节过后 直接就读取的话会导致EEPROM由于正在处理自身内部时序而接受不到信号
//所以要加一个循环重发信号的等待函数
EEPROM_WaitForWriteEnd();
EEPROM_Read(8,readData,1);
printf(&quot;接受到的数据为0x%x&quot;,readData[0]);
while (1)
{
}
} |
|