/*******************************************************************************
Copyright: 2022
File name: bsp_driver_i2c .c
Description: IIC EEPROM 配置,工作参数配置
Author: Kerlly
Version: v1.0
Date: 20220614
History: 20220614:v1.0:初版
*******************************************************************************/
#include "./i2c/bsp_driver_i2c.h"
#include "./usart/bsp_usart.h"
static __IO uint32_t I2CTimeout;
/*******************************************************************************
Function:BSP_I2C_Init
Description: I2C初始化和工作模式配置
Input: 无
Output: 无
Return: 无
*******************************************************************************/
void BSP_I2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* 使能与 I2C 有关的时钟 */
EEPROM_I2C_APBxClock_FUN ( EEPROM_I2C_CLK, ENABLE );
EEPROM_I2C_GPIO_APBxClock_FUN ( EEPROM_I2C_GPIO_CLK, ENABLE );
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);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//时钟占空比
I2C_InitStructure.I2C_OwnAddress1 =I2Cx_OWN_ADDRESS7; //这是STM32 IIC自身设备地址,只要是总线上唯一即可
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//使用7位地址模式
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//时钟占空比
I2C_Init(EEPROM_I2Cx, &I2C_InitStructure);
I2C_Cmd(EEPROM_I2Cx, ENABLE);
}
/*******************************************************************************
Function:BSP_EEPROM_ByteWrite
Description:快速页写入的数据到 I2C EEPROM 中
Input: _EEPROM_addr:设备地址
_WriteAddr:写入地址
_Writedata:写入数据
_len:长度
Output: 无
Return: 无
*******************************************************************************/
//void BSP_I2C_BufferWrite(uint8_t WriteAddr, uint8_t* pBuffer, uint16_t 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 */
// if (Addr == 0)
// {
// /* If NumByteToWrite < I2C_PageSize */
// if (NumOfPage == 0)
// {
// BSP_EEPROM_PageWrite(WriteAddr, pBuffer, NumOfSingle);
// I2C_EE_WaitEepromStandbyState();
// }
// /* If NumByteToWrite > I2C_PageSize */
// else
// {
// while(NumOfPage--)
// {
// BSP_EEPROM_PageWrite(WriteAddr, pBuffer, I2C_PageSize);
// I2C_EE_WaitEepromStandbyState();
// WriteAddr += I2C_PageSize;
// pBuffer += I2C_PageSize;
// }
// if(NumOfSingle!=0)
// {
// BSP_EEPROM_PageWrite(WriteAddr,pBuffer , NumOfSingle);
// I2C_EE_WaitEepromStandbyState();
// }
// }
// }
// else
// {
// /* If NumByteToWrite < I2C_PageSize */
// if (NumOfPage== 0)
// {
// BSP_EEPROM_PageWrite(WriteAddr, pBuffer, NumOfSingle);
// I2C_EE_WaitEepromStandbyState();
// }
// /* If NumByteToWrite > I2C_PageSize */
// else
// {
// NumByteToWrite -= count;
// NumOfPage = NumByteToWrite / I2C_PageSize;
// NumOfSingle = NumByteToWrite % I2C_PageSize;
// if (count != 0)
// {
// BSP_EEPROM_PageWrite(WriteAddr, pBuffer, count);
// I2C_EE_WaitEepromStandbyState();
// WriteAddr += count;
// pBuffer += count;
// }
// while(NumOfPage--)
// {
// BSP_EEPROM_PageWrite(WriteAddr,pBuffer , I2C_PageSize);
// I2C_EE_WaitEepromStandbyState();
// WriteAddr += I2C_PageSize;
// pBuffer += I2C_PageSize;
// }
// if(NumOfSingle != 0)
// {
// BSP_EEPROM_PageWrite(WriteAddr,pBuffer , NumOfSingle);
// I2C_EE_WaitEepromStandbyState();
// }
// }
// }
//}
/*******************************************************************************
Function:BSP_EEPROM_ByteWrite
Description:快速页写入的数据到 I2C EEPROM 中
Input: _EEPROM_addr:设备地址
_WriteAddr:写入地址
_Writedata:写入数据
_len:长度
Output: 无
Return: 无
*******************************************************************************/
void BSP_I2C_BufferWrite(uint8_t WriteAddr, uint8_t* pBuffer, uint16_t NumByteToWrite)
{
u8 NumOfSingle = 0;
while (NumByteToWrite)
{
NumOfSingle = I2C_PageSize - WriteAddr % I2C_PageSize;
if (NumByteToWrite > NumOfSingle)
{
BSP_EEPROM_PageWrite(WriteAddr, pBuffer, NumOfSingle);
WriteAddr += NumOfSingle;
pBuffer += NumOfSingle;
NumByteToWrite -= NumOfSingle;
}
else
{
BSP_EEPROM_PageWrite(WriteAddr, pBuffer, NumByteToWrite);
NumByteToWrite = 0;
}
I2C_EE_WaitEepromStandbyState();
}
}
/*******************************************************************************
Function:BSP_EEPROM_ByteWrite
Description:单字节向写入EEPROM
Input: WriteAddr 写入地址
WriteData 写入数据
Output: 无
Return: 1=失败 0=成功
*******************************************************************************/
uint32_t BSP_EEPROM_ByteWrite(uint8_t WriteAddr, uint8_t* WriteData)
{
I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
//起始信号+EV5+设备地址+EV6+储存DATA+EV8+结束信号
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2CTimeout--) == 0)
{
return 1;
}
}
I2CTimeout = I2CT_FLAG_TIMEOUT;
I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_SendData(EEPROM_I2Cx, WriteAddr);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_SendData(EEPROM_I2Cx, *WriteData);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
return 0;
}
/*******************************************************************************
Function:BSP_EEPROM_PageWrite
Description:向EEPROM写入多个字节(页写入),
每次写入不能超过EEPROM页的大小,AT24C02每页有8个字节
Input: WriteAddr 写入地址
Writedata 写入数据
_len 数据字节长度
Output: 无
Return: 1=失败 0=成功
*******************************************************************************/
uint32_t BSP_EEPROM_PageWrite(uint8_t WriteAddr, uint8_t* Writedata , uint8_t _len)
{
I2CTimeout = I2CT_FLAG_TIMEOUT ;//设置超时等待
while (I2C_GetFlagStatus(EEPROM_I2Cx, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
I2CTimeout = I2CT_FLAG_TIMEOUT;
//EV5事件被检测到,发送设备地址
while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
I2CTimeout = I2CT_FLAG_TIMEOUT;
//EV6事件被检测到,发送要操作的存储单元地址
while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_SendData(EEPROM_I2Cx, WriteAddr);
I2CTimeout = I2CT_FLAG_TIMEOUT;
//EV8事件被检测到,发送要存储的数据
while(! I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
while ( _len--)
{
I2C_SendData(EEPROM_I2Cx, *Writedata);
Writedata++;
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
}
I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
return 0;
}
/*******************************************************************************
Function:BSP_EEPROM_Read
Description:读取EEPROM的数据
Input: _EEPROM_addr设备地址
ReadAddr 读取地址
ReadData 写入数据
_len 字节长度
Output: 无
Return: 1=失败 0=成功
*******************************************************************************/
uint32_t BSP_EEPROM_Read(uint8_t ReadAddr ,uint8_t* ReadData , uint16_t _len)
{
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (I2C_GetFlagStatus(EEPROM_I2Cx, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
I2CTimeout = I2CT_FLAG_TIMEOUT;
//EV6事件被检测到,发送要操作的存储单元地址
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_Cmd(EEPROM_I2Cx, ENABLE);
I2C_SendData(EEPROM_I2Cx, ReadAddr);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);//第二次起始信号
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2CTimeout--) == 0)
{
return 1;
}
}
I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Receiver);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if ((I2CTimeout--) == 0)
{
return 1;
}
}
while(_len)
{
if(_len == 1)
{
I2C_AcknowledgeConfig(EEPROM_I2Cx, DISABLE);//如果为最后一个字节
I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
}
I2CTimeout = I2CT_FLAG_TIMEOUT;
while(I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)
{
if((I2CTimeout--) == 0)
{
return 1;
}
}
{
*ReadData = I2C_ReceiveData(EEPROM_I2Cx);
ReadData++;
_len--;
}
}
//重新配置ACK使能,以便下次通讯
I2C_AcknowledgeConfig(EEPROM_I2Cx, ENABLE);
return 0;
}
/*******************************************************************************
Function:I2C_EE_WaitEepromStandbyState
Description:等待EEPROM内部时序完成,iic已经发数据过去,
iic空闲,但是EEPROM内部有时序写入,iic无法响应
Input: 无
Output: 无
Return: 无
*******************************************************************************/
void I2C_EE_WaitEepromStandbyState(void)
{
vu16 SR1_Tmp = 0;
do
{
/* Send START condition */
I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
/* Read I2C1 SR1 register */
SR1_Tmp = I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1);
/* Send EEPROM address for write */
I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
}
while(!(I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1) & 0x0002));
/* Clear AF flag */
I2C_ClearFlag(EEPROM_I2Cx, I2C_FLAG_AF);
/* STOP condition */
I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
}
/*********************************************END OF FILE**********************/
/*******************************************************************************
Copyright:
File name: bsp_driver_i2c .h
Description: IIC EEPROM 配置,工作参数配置
Author: Kerlly
Version: v1.0
Date: 20220614
History: 20220614:v1.0:初版
*******************************************************************************/
#ifndef _BSP_DRIVER_I2C_H
#define _BSP_DRIVER_I2C_H
#include "stm32f10x.h"
/**************************I2C参数定义,I2C1或I2C2********************************/
#define EEPROM_I2Cx I2C1
#define EEPROM_I2C_APBxClock_FUN RCC_APB1PeriphClockCmd
#define EEPROM_I2C_CLK RCC_APB1Periph_I2C1
#define EEPROM_I2C_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define EEPROM_I2C_GPIO_CLK RCC_APB2Periph_GPIOB
#define EEPROM_I2C_SCL_PORT GPIOB
#define EEPROM_I2C_SCL_PIN GPIO_Pin_6
#define EEPROM_I2C_SDA_PORT GPIOB
#define EEPROM_I2C_SDA_PIN GPIO_Pin_7
/* STM32 I2C 快速模式 */
#define I2C_Speed 400000 //*
/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */
#define I2Cx_OWN_ADDRESS7 0X0A
/* AT24C01/02每页有8个字节 */
#define I2C_PageSize 8
/*等待超时时间*/
#define I2CT_FLAG_TIMEOUT ((uint32_t)0x1000)
/*
* 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 0 0 0 0 = 0XA0
* 1 0 1 0 0 0 0 1 = 0XA1
*/
/* EEPROM Addresses defines */
#define EEPROM_ADDRESS 0xA0 /* E2 = 0 */
/*******************************************************************************
Function:BSP_I2C_Init
Description: I2C初始化和工作模式配置
Input: 无
Output: 无
Return: 无
*******************************************************************************/
void BSP_I2C_Init(void);
/*******************************************************************************
Function:BSP_EEPROM_ByteWrite
Description:快速页写入的数据到 I2C EEPROM 中
Input: _EEPROM_addr:设备地址
_WriteAddr:写入地址
_Writedata:写入数据
_len:长度
Output: 无
Return: 无
*******************************************************************************/
void BSP_I2C_BufferWrite(uint8_t WriteAddr, uint8_t* pBuffer, uint16_t NumByteToWrite);
/*******************************************************************************
Function:BSP_EEPROM_ByteWrite
Description:单字节向写入EEPROM
Input: WriteAddr 写入地址
WriteData 写入数据
Output: 无
Return: 1=失败 0=成功
*******************************************************************************/
uint32_t BSP_EEPROM_ByteWrite(uint8_t WriteAddr, uint8_t* WriteData);
/*******************************************************************************
Function:BSP_EEPROM_PageWrite
Description:向EEPROM写入多个字节(页写入),
每次写入不能超过EEPROM页的大小,AT24C02每页有8个字节
Input: WriteAddr 写入地址
Writedata 写入数据
_len 数据字节长度
Output: 无
Return: 1=失败 0=成功
*******************************************************************************/
uint32_t BSP_EEPROM_PageWrite(uint8_t WriteAddr, uint8_t* Writedata , uint8_t _len);
/*******************************************************************************
Function:BSP_EEPROM_Read
Description:读取EEPROM的数据
Input: _EEPROM_addr设备地址
ReadAddr 读取地址
ReadData 写入数据
_len 字节长度
Output: 无
Return: 1=失败 0=成功
*******************************************************************************/
uint32_t BSP_EEPROM_Read(uint8_t ReadAddr ,uint8_t* ReadData , uint16_t _len);
/*******************************************************************************
Function:I2C_EE_WaitEepromStandbyState
Description:等待EEPROM内部时序完成,iic已经发数据过去,
iic空闲,但是EEPROM内部有时序写入,iic无法响应
Input: 无
Output: 无
Return: 无
*******************************************************************************/
void I2C_EE_WaitEepromStandbyState(void);
#endif /* BSP_DRIVER_I2C_H */
#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./usart/bsp_usart.h"
#include "./i2c/bsp_driver_i2c.h"
#include <string.h>
#define EEP_Firstpage 0x00
uint8_t I2c_Buf_Write[50];
uint8_t I2c_Buf_Read[50];
uint8_t I2C_Test(void);
uint8_t I2c_test_Buf[256];
uint8_t readbuff[8];
uint8_t writebuff[8];
uint8_t _ReadBuf[8];
uint8_t _WriteBuf[8] = {1,2,3,4,5,6,7,8};
int main(void)
{
int n=0;
uint16_t i;
LED_GPIO_Config();
USART_Config();
BSP_I2C_Init();
LED_BLUE;
/**************************** 单字节写入 *******************************/
printf("\r\n");
printf("单字节写入数据:0x55 \n");
writebuff[0]=0x55;
BSP_EEPROM_ByteWrite(0,writebuff);
I2C_EE_WaitEepromStandbyState();
BSP_EEPROM_Read(0,readbuff,1);
printf("接收数据为: 0x%x\r\n",readbuff[0]);
printf("\r\n");
/**************************** 多字节写入 *******************************/
printf("\r\n");
printf("多字节写入数据: \n");
printf("write addr:1\r\n");
printf("write data: ");
for(n=0;n<8;n++)
{
BSP_EEPROM_PageWrite(1,_WriteBuf,8);
I2C_EE_WaitEepromStandbyState();
printf("0x%x ",_WriteBuf[n]);
}
printf("\r\n");
printf("read addr:1\r\n");
printf("read data:");
for(n=0;n<8;n++)
{
BSP_EEPROM_Read(1,_ReadBuf,8);
printf("0x%x ",_ReadBuf[n]);
}
printf("\r\n");
/************************ 快速页写入 ************************************/
printf("\r\n");
printf("快速页写入:\n\r");
for ( i=0; i<49; i++ ) //填充缓冲
{
I2c_Buf_Write[i] = i;
printf("0x%02X ", I2c_Buf_Write[i]);
if(i%25== 1)
printf("\n\r");
}
memset(I2c_test_Buf,0,256);
BSP_I2C_BufferWrite(0,I2c_test_Buf , 256);
//将I2c_Buf_Write中顺序递增的数据写入EERPOM中
BSP_I2C_BufferWrite(EEP_Firstpage,I2c_Buf_Write , 49);
printf("\n\r读出的数据:\r");
//将EEPROM读出数据顺序保持到I2c_Buf_Read中
BSP_EEPROM_Read(EEP_Firstpage,I2c_Buf_Read , 49);
//将I2c_Buf_Read中的数据通过串口打印
for (i=0; i<30; i++)
{
if(I2c_Buf_Read[i] != I2c_Buf_Write[i])
{
printf(" 出错 ");
}
printf("0x%02X ", I2c_Buf_Read[i]);
if (i%25 == 1)
{
printf("\n\r");
}
}
BSP_EEPROM_Read(0,I2c_test_Buf , 256);
printf("\n\r");
printf("read data:");
for (i=0; i<30; i++)
{
printf("0x%x ", I2c_test_Buf[i]);
}
printf("\n\r");
while (1)
{
}
}
/*********************************************END OF FILE**********************/