程序大概已经写好了,但是在仿真时发现数据并没有存进存储器,有没有谁可以指点一下
```c
#include "stm32f10x.h"
#include "FM24C.h"
#include "main.h"
/* 由用户指定 ----------------------------------------------------*/
//#define I2C_REMAP
//#define SLAVE_10BIT_ADDRESS
/* Private define --------------------------------------------------------*/
#define ADDRESS_MAX (1024 * AT24Cxx / 8)
#if (AT24Cxx < 4) // AT24C02
#define I2C_PageSize 8
#elif (AT24Cxx <= 16) // AT24C04, AT24C08, AT24C16
#define I2C_PageSize 16
#elif (AT24Cxx <= 512) // AT24C32, AT24C64, AT24C512
#define I2C_PageSize 32
#define EE_ADDRESS_NUM 2
#else
#error "unsupport eeprom"
#endif
#define I2C1_DR_Address 0x40005410
#define I2C2_DR_Address 0x40005810
#define Transmitter 0x00
#define Receiver 0x01
/* 局部变量 -------------------------------------------------------*/
static vu8 MasterDirection = Transmitter;
static u16 SlaveADDR;
static u16 DeviceOffset = 0x0;
static bool check_begin = FALSE;
static bool OffsetDone = FALSE;
vu8 MasterReceptionComplete = 0;
vu8 MasterTransitionComplete = 0; // 指示主机的发送过程
vu8 WriteComplete = 0; // 指示目标的内部写进程
int I2C_NumByteToWrite = 0;
u8 I2C_NumByteWritingNow = 0;
u8 *I2C_pBuffer = 0;
u16 I2C_WriteAddr = 0;
u8 EE_Addr_Count = 0; //地址字节数
static vu8 PV_flag_1; //对I2C1的P-V运算
volatile I2C_STATE i2c_comm_state;
/*******************************************************************************
* 函数名 : I2C_EE_Init
* 类型 : 初始化I2C EEPROM驱动使用的外设。
* 输入 : None
* 输出 : None
* 返回 : None
*******************************************************************************/
void I2C_EE_Init(void)
{
/******* GPIO configuration and clock enable *********/
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
#ifdef I2C_REMAP
GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
#else
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
#endif
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*********** I2C periphral configuration **********/
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // 固定
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 固定
I2C_InitStructure.I2C_OwnAddress1 = I2C1_ADDRESS7; // user parameter
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // 固定
#ifdef SLAVE_10BIT_ADDRESS
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit; // user define
#else
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
#endif
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; // user parameter
I2C_Cmd(I2C1, ENABLE);
I2C_Init(I2C1, &I2C_InitStructure);
/************** I2C NVIC configuration *************************/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
/*******************************************************************************
* 函数名 : I2C_EE_BufferRead
* 类型 : 从EEPROM读取数据块。
* 输入 : - pBuffer : 指向缓冲区的指针,它接收从EEPROM读取的数据*。
* - ReadAddr : EEPROM要读取的内部地址。
* - NumByteToRead : 从EEPROM中读取的字节数。
* 输出 : None
* 返回 : None
*******************************************************************************/
void I2C_EE_ReadBuffer(u8 *pBuffer, u16 ReadAddr, u16 NumByteToRead)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* PV operation */
if (PV_flag_1 != 0)
return;
PV_flag_1 = 1;
/* DMA 初始化 */
DMA_DeInit(DMA1_Channel7);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)I2C1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pBuffer; // 从函数输入参数
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 固定接收功能
DMA_InitStructure.DMA_BufferSize = NumByteToRead; // 从函数输入参数
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 固定
DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte; //固定
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //固定
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 固定
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 固定
DMA_Init(DMA1_Channel7, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*固定接收功能*/
MasterDirection = Receiver;
MasterReceptionComplete = 0;
/*根据输入参数初始化静态参数*/
SlaveADDR = EEPROM_ADDRESS;
DeviceOffset = ReadAddr;
OffsetDone = FALSE;
/* 全局状态变量i2c_comm_state */
i2c_comm_state = COMM_PRE;
I2C_AcknowledgeConfig(I2C1, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_ERR, ENABLE); //只允许使用SB
/* 发送启动条件 */
if (I2C1->CR1 & 0x200)
I2C1->CR1 &= 0xFDFF;
I2C_GenerateSTART(I2C1, ENABLE);
}
/*******************************************************************************
* 函数名 : I2C_EE_PageWrite
* 类型 : 以单一的WRITE周期向EEPROM写入多个字节。字节数不能超过EEPROM页面大小
* 输入 : - pBuffer : 指向包含要写入EEPROM的数据的缓冲区的指针。
* - WriteAddr : EEPROM要写入(1-16)的内部地址。
* - NumByteToWrite : 写入EEPROM的字节数。
* 输出 : None
* 返回 : None
*******************************************************************************/
void I2C_EE_PageWrite(u8 *pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* DMA 初始化 */
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)I2C1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pBuffer; // 从函数输入参数
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 固定发送功能
DMA_InitStructure.DMA_BufferSize = NumByteToWrite; // 从函数输入参数
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 固定
DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte; //固定
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //固定
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 固定
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 固定
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*初始化静态参数*/
MasterDirection = Transmitter;
MasterTransitionComplete = 0;
/*根据输入参数初始化静态参数*/
SlaveADDR = EEPROM_ADDRESS; //这个字节应该由F/W发送(循环或ISR方式)
DeviceOffset = WriteAddr; // 这个字节可以通过F/W和DMA发送
OffsetDone = FALSE;
I2C_AcknowledgeConfig(I2C1, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
/* Send START condition */
if (I2C1->CR1 & 0x200)
I2C1->CR1 &= 0xFDFF;
I2C_GenerateSTART(I2C1, ENABLE);
}
void I2C_EE_WriteOnePage(u8 *pBuffer, u16 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;
I2C_NumByteWritingNow = 0;
/* 如果WriteAddr为I2C_PageSize对齐 */
if (Addr == 0)
{
/* 如果NumByteToWrite & lt;I2C_PageSize */
if (NumOfPage == 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_NumByteWritingNow = NumOfSingle;
}
/* If NumByteToWrite > I2C_PageSize */
else
{
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
I2C_NumByteWritingNow = I2C_PageSize;
}
}
/*如果WriteAddr不是I2C_PageSize对齐 */
else
{
/* If NumByteToWrite < I2C_PageSize */
if (NumOfPage == 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_NumByteWritingNow = NumOfSingle;
}
/* If NumByteToWrite > I2C_PageSize */
else
{
if (count != 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, count);
I2C_NumByteWritingNow = count;
}
else
{
printf("address error\r\n");
}
}
}
}
void I2C_EE_WriteOnePageCompleted(void)
{
I2C_pBuffer += I2C_NumByteWritingNow;
I2C_WriteAddr += I2C_NumByteWritingNow;
I2C_NumByteToWrite -= I2C_NumByteWritingNow;
}
/*******************************************************************************
* 函数名 : I2C_EE_BufferWrite
* 类型 : 将数据缓冲区写入I2C EEPROM。
* 输入 : - pBuffer : 指向包含要写入EEPROM的数据的缓冲区的指针。
* - WriteAddr : EEPROM要写入的内部地址。
* - NumByteToWrite : 写入EEPROM的字节数。
* 输出 : None
* 返回 : None
*******************************************************************************/
void I2C_EE_WriteBuffer(u8 *pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
/* PV 操作 */
if (PV_flag_1 != 0)
return;
PV_flag_1 = 1;
/* 全局状态变量i2c_comm_state */
i2c_comm_state = COMM_PRE;
I2C_pBuffer = pBuffer;
I2C_WriteAddr = WriteAddr;
I2C_NumByteToWrite = NumByteToWrite;
I2C_EE_WriteOnePage(I2C_pBuffer, I2C_WriteAddr, I2C_NumByteToWrite);
}
/*******************************************************************************
* 函数名 : I2C_EE_WaitOperationIsCompleted
* 类型 : 等待操作完成
* 输入 : None
* 输出 : None
* 返回 : None
*******************************************************************************/
void I2C_EE_WaitOperationIsCompleted(void)
{
while (i2c_comm_state != COMM_DONE)
;
}
/********************** 中断服务程序 **************************/
void i2c1_evt_isr()
{
uint32_t lastevent = I2C_GetLastEvent(I2C1);
switch (lastevent)
{
/************************** 主调用**************************************/
case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
// MSL SB BUSY 30001
if (!check_begin)
i2c_comm_state = COMM_IN_PROCESS;
if (MasterDirection == Receiver)
{
if (!OffsetDone)
#if (EE_ADDRESS_NUM > 1)
I2C_Send7bitAddress(I2C1, SlaveADDR, I2C_Direction_Transmitter);
#else
I2C_Send7bitAddress(I2C1, ((DeviceOffset & 0x0700) >> 7) | SlaveADDR,
I2C_Direction_Transmitter);
#endif
else
{
/* Send slave 读取地址 */
#if (EE_ADDRESS_NUM > 1)
I2C_Send7bitAddress(I2C1, SlaveADDR, I2C_Direction_Receiver);
#else
I2C_Send7bitAddress(I2C1, ((DeviceOffset & 0x0700) >> 7) | SlaveADDR, I2C_Direction_Receiver);
#endif
OffsetDone = FALSE;
}
}
else
{
/* 发送slave写地址 */
#if (EE_ADDRESS_NUM > 1)
I2C_Send7bitAddress(I2C1, SlaveADDR, I2C_Direction_Transmitter);
#else
I2C_Send7bitAddress(I2C1, ((DeviceOffset & 0x0700) >> 7) | SlaveADDR, I2C_Direction_Transmitter);
#endif
}
I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE); // also TxE int allowed
break;
/********************** 主接收事件 ********************************/
case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
// MSL BUSY ADDR 0x30002
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
//没有它,总线上没有NAK信号后最后数据
// I2C数据线将保持低电平
I2C_DMALastTransferCmd(I2C1, ENABLE);
I2C_DMACmd(I2C1, ENABLE);
DMA_Cmd(DMA1_Channel7, ENABLE);
break;
case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
// MSL BUSY RXNE 0x30040
break;
/************************* 主发射机事件 **************************/
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV8 just after EV6 */
// BUSY, MSL, ADDR, TXE and TRA 0x70082
if (check_begin)
{
check_begin = FALSE;
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
//!! write over
I2C_EE_WriteOnePageCompleted();
if (I2C_NumByteToWrite > 0)
{
I2C_EE_WriteOnePage(I2C_pBuffer, I2C_WriteAddr, I2C_NumByteToWrite);
}
else
{
WriteComplete = 1;
i2c_comm_state = COMM_DONE;
PV_flag_1 = 0;
}
break;
}
#if (EE_ADDRESS_NUM > 1)
EE_Addr_Count++;
if (EE_Addr_Count < (EE_ADDRESS_NUM))
{
I2C_SendData(I2C1, DeviceOffset >> 8);
}
// else
// {
// I2C_SendData(I2C1, DeviceOffset);
// }
#else
I2C_SendData(I2C1, DeviceOffset);
OffsetDone = TRUE;
#endif
break;
case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 I2C_EVENT_MASTER_BYTE_TRANSMITTING*/
#if (EE_ADDRESS_NUM > 1)
if (!OffsetDone)
{
if (EE_Addr_Count < (EE_ADDRESS_NUM))
{
// while ((I2C1->CR1 & 0x200) == 0x200);
// I2C_GenerateSTART(I2C1, ENABLE);
I2C_SendData(I2C1, DeviceOffset);
EE_Addr_Count++;
}
else
{
EE_Addr_Count = 0;
OffsetDone = TRUE;
}
break;
}
#endif
if (MasterDirection == Receiver)
{
I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE);
while ((I2C1->CR1 & 0x200) == 0x200)
;
I2C_GenerateSTART(I2C1, ENABLE);
break;
}
else
{
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
I2C_DMACmd(I2C1, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE);
break;
}
case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8-2 */
// TRA, BUSY, MSL, TXE and BTF 0x70084
break;
}
}
void i2c1_err_isr()
{
if (I2C_GetFlagStatus(I2C1, I2C_FLAG_AF))
{
if (check_begin)
I2C_GenerateSTART(I2C1, ENABLE);
else if (I2C1->SR2 & 0x01)
{
//!! receive over
I2C_GenerateSTOP(I2C1, ENABLE);
i2c_comm_state = COMM_EXIT;
PV_flag_1 = 0;
}
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
if (I2C_GetFlagStatus(I2C1, I2C_FLAG_BERR))
{
if (I2C1->SR2 & 0x01)
{
I2C_GenerateSTOP(I2C1, ENABLE);
i2c_comm_state = COMM_EXIT;
PV_flag_1 = 0;
}
I2C_ClearFlag(I2C1, I2C_FLAG_BERR);
}
}
void i2c1_send_dma_isr()
{
if (DMA_GetFlagStatus(DMA1_FLAG_TC6))
{
if (I2C1->SR2 & 0x01) // 主发送DMA完成,检查过程之后主控发送DMA完成,稍后检查进程
{
// DMA1-6 (I2C1 Tx DMA)transfer complete ISR
I2C_DMACmd(I2C1, DISABLE);
DMA_Cmd(DMA1_Channel6, DISABLE);
// wait until BTF
while (!(I2C1->SR1 & 0x04))
;
I2C_GenerateSTOP(I2C1, ENABLE);
// wait until BUSY clear
while (I2C1->SR2 & 0x02)
;
MasterTransitionComplete = 1;
i2c_comm_state = COMM_IN_PROCESS;
I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE); // 使用中断处理检查过程
check_begin = TRUE;
if (I2C1->CR1 & 0x200)
I2C1->CR1 &= 0xFDFF;
I2C_GenerateSTART(I2C1, ENABLE);
}
else // slave send DMA finish
{
}
DMA_ClearFlag(DMA1_FLAG_TC6);
}
if (DMA_GetFlagStatus(DMA1_FLAG_GL6))
{
DMA_ClearFlag(DMA1_FLAG_GL6);
}
if (DMA_GetFlagStatus(DMA1_FLAG_HT6))
{
DMA_ClearFlag(DMA1_FLAG_HT6);
}
}
void i2c1_receive_dma_isr()
{
if (DMA_GetFlagStatus(DMA1_FLAG_TC7))
{
if (I2C1->SR2 & 0x01) // 主接收DMA完成
{
I2C_DMACmd(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
i2c_comm_state = COMM_DONE;
MasterReceptionComplete = 1;
PV_flag_1 = 0;
}
else // 从属接收DMA完成
{
}
DMA_ClearFlag(DMA1_FLAG_TC7);
}
if (DMA_GetFlagStatus(DMA1_FLAG_GL7))
{
DMA_ClearFlag(DMA1_FLAG_GL7);
}
if (DMA_GetFlagStatus(DMA1_FLAG_HT7))
{
DMA_ClearFlag(DMA1_FLAG_HT7);
}
}
```c
#ifndef __I2C_EE_DMA_H
#define __I2C_EE_DMA_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
/* Private define ------------------------------------------------------------*/
#define I2C_Speed 200000
#define I2C1_ADDRESS7 0x01
#define EEPROM_ADDRESS 0xA0
/* eeprom 型号 */
#define AT24Cxx (16) //AT24C16
/* Exported types ------------------------------------------------------------*/
typedef enum i2c_result
{
NO_ERR = 0,
TIMEOUT = 1,
BUS_BUSY = 2,
SEND_START_ERR = 3,
ADDR_MATCH_ERR = 4,
ADDR_HEADER_MATCH_ERR = 5,
DATA_TIMEOUT = 6,
WAIT_COMM = 7,
STOP_TIMEOUT = 8
}I2C_Result;
typedef enum i2c_state
{
COMM_DONE = 0, // done successfully
COMM_PRE = 1,
COMM_IN_PROCESS = 2,
CHECK_IN_PROCESS = 3,
COMM_EXIT = 4 // exit since failure
}I2C_STATE;
extern volatile I2C_STATE i2c_comm_state;
void I2C_EE_Init(void);
void I2C_EE_WriteBuffer(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite);
void I2C_EE_ReadBuffer(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);
void I2C_EE_WaitOperationIsCompleted(void);
#endif
源码是别人开源的http://share.eepw.com.cn/share/download/id/59158#share_fb_down