您好,欢迎来到暴趣科技网。
搜索
您的当前位置:首页stm32 i2c dma

stm32 i2c dma

来源:暴趣科技网
stm32 i2c dma

#ifndef __AT24C256_H

#define __AT24C256_H

/* Includes ------------------------------------------------------------------*/

#include \"stm32f10x.h\"

#ifdef __cplusplus

extern \"C\" {

#endif

#define I2C_SPEED 300000

#define I2C_SLAVE_ADDRESS7 0xA0

#define sEE_PAGESIZE 32

/* Maximum number of trials for sEE_WaitEepromStandbyState() function */

#define sEE_MAX_TRIALS_NUMBER 150

/* Defintions for the state of the DMA transfer */

1 / 621 / 62

stm32 i2c dma

#define sEE_STATE_READY 0

#define sEE_STATE_BUSY 1

#define sEE_STATE_ERROR 2

#define sEE_OK 0

#define sEE_FAIL 1

#define sEE_FLAG_TIMEOUT ((uint32_t)0x1000)

#define sEE_LONG_TIMEOUT ((uint32_t)(10 * sEE_FLAG_TIMEOUT))

#define sEE_I2C I2C1

#define sEE_I2C_CLK RCC_APB1Periph_I2C1

#define sEE_I2C_SCL_PIN GPIO_Pin_6

#define sEE_I2C_SCL_GPIO_PORT GPIOB

#define sEE_I2C_SCL_GPIO_CLK RCC_APB2Periph_GPIOB

#define sEE_I2C_SDA_PIN GPIO_Pin_7

2 / 622 / 62

stm32 i2c dma

#define sEE_I2C_SDA_GPIO_PORT GPIOB

#define sEE_I2C_SDA_GPIO_CLK RCC_APB2Periph_GPIOB

#define sEE_M24C_32

#define sEE_I2C_DMA #define sEE_I2C_DMA_CHANNEL_TX #define sEE_I2C_DMA_CHANNEL_RX #define sEE_I2C_DMA_FLAG_TX_TC #define sEE_I2C_DMA_FLAG_TX_GL #define sEE_I2C_DMA_FLAG_RX_TC #define sEE_I2C_DMA_FLAG_RX_GL #define sEE_I2C_DMA_CLK #define sEE_I2C_DR_Address #define sEE_USE_DMA

3 / 623 / 62

DMA1

DMA1_Channel6

DMA1_Channel7

DMA1_IT_TC6

DMA1_IT_GL6

DMA1_IT_TC7

DMA1_IT_GL7

RCC_AHBPeriph_DMA1

((uint32_t)0x40005410)stm32 i2c dma

#define sEE_I2C_DMA_TX_IRQn DMA1_Channel6_IRQn

#define sEE_I2C_DMA_RX_IRQn DMA1_Channel7_IRQn

#define sEE_I2C_DMA_TX_IRQHandler DMA1_Channel6_IRQHandler

#define sEE_I2C_DMA_RX_IRQHandler DMA1_Channel7_IRQHandler

#define sEE_I2C_DMA_PREPRIO 0

#define sEE_I2C_DMA_SUBPRIO 0

#define sEE_DIRECTION_TX 0

#define sEE_DIRECTION_RX 1

/* Time constant for the delay caclulation allowing to have a millisecond

incrementing counter. This value should be equal to (System Clock / 1000).

ie. if system clock = 24MHz then sEE_TIME_CONST should be 24. */

#define sEE_TIME_CONST 48

void sEE_DeInit(void);

4 / 624 / 62

stm32 i2c dma

void sEE_Init(void);

uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead);

uint32_t sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite);

void sEE_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite);

uint32_t sEE_WaitEepromStandbyState(void);

/* USER Callbacks: These are functions for which prototypes only are declared in

EEPROM driver and that should be implemented into user applicaiton. */

/* sEE_TIMEOUT_UserCallback() function is called whenever a timeout condition

occure during communication (waiting on an event that doesn't occur, bus

errors, busy devices ...).

You can use the default timeout callback implementation by uncommenting

5 / 625 / 62

stm32 i2c dma

the

define USE_DEFAULT_TIMEOUT_CALLBACK in stm32_evel_i2c_ee.h file.

Typically the user implementation of this callback should reset I2C peripheral

and re-initialize communication or in worst case reset all the application. */

uint32_t sEE_TIMEOUT_UserCallback(void);

/* Start and End of critical section: these callbacks should be typically used

to disable interrupts when entering a critical section of I2C communication

You may use default callbacks provided into this driver by uncommenting the

define USE_DEFAULT_CRITICAL_CALLBACK in stm32_evel_i2c_ee.h file..

Or you can comment that line and implement these callbacks into your

application */

void sEE_EnterCriticalSection_UserCallback(void);

void sEE_ExitCriticalSection_UserCallback(void);

6 / 626 / 62

stm32 i2c dma

#ifdef __cplusplus

}

#endif

#endif

以下是C文件

#include \"at24c256.h\"

__IO uint16_t sEEAddress = 0xa0;

__IO uint32_t sEETimeout = sEE_LONG_TIMEOUT;

__IO uint16_t* sEEDataReadPointer;

__IO uint8_t* sEEDataWritePointer;

__IO uint8_t sEEDataNum;

DMA_InitTypeDef sEEDMA_InitStructure;

void sEE_LowLevel_DeInit(void)

7 / 627 / 62

stm32 i2c dma

{

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

/* sEE_I2C Peripheral Disable */

I2C_Cmd(sEE_I2C, DISABLE);

/* sEE_I2C DeInit */

I2C_DeInit(sEE_I2C);

/*!< sEE_I2C Periph clock disable */

RCC_APB1PeriphClockCmd(sEE_I2C_CLK, DISABLE);

/*!< GPIO configuration */

/*!< Configure sEE_I2C pins: SCL */

GPIO_InitStructure.GPIO_Pin = sEE_I2C_SCL_PIN;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

8 / 628 / 62

stm32 i2c dma

GPIO_Init(sEE_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

/*!< Configure sEE_I2C pins: SDA */

GPIO_InitStructure.GPIO_Pin = sEE_I2C_SDA_PIN;

GPIO_Init(sEE_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);

/* Configure and enable I2C DMA TX Channel interrupt */

NVIC_InitStructure.NVIC_IRQChannel = sEE_I2C_DMA_TX_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority sEE_I2C_DMA_PREPRIO;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = sEE_I2C_DMA_SUBPRIO;NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;

NVIC_Init(&NVIC_InitStructure);

/* Configure and enable I2C DMA RX Channel interrupt */

NVIC_InitStructure.NVIC_IRQChannel = sEE_I2C_DMA_RX_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority

9 / 629 / 62

=

=

stm32 i2c dma

sEE_I2C_DMA_PREPRIO;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = sEE_I2C_DMA_SUBPRIO;

NVIC_Init(&NVIC_InitStructure);

/* Disable and Deinitialize the DMA channels */

DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, DISABLE);

DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, DISABLE);

DMA_DeInit(sEE_I2C_DMA_CHANNEL_TX);

DMA_DeInit(sEE_I2C_DMA_CHANNEL_RX);

}

/**

* @brief Initializes peripherals used by the I2C EEPROM driver.

* @param None

* @retval None

10 / 6210 / 62

stm32 i2c dma

*/

void sEE_LowLevel_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

/*!< sEE_I2C_SCL_GPIO_CLK and sEE_I2C_SDA_GPIO_CLK Periph clock enable */

RCC_APB2PeriphClockCmd(sEE_I2C_SCL_GPIO_CLK | sEE_I2C_SDA_GPIO_CLK, ENABLE);

/*!< sEE_I2C Periph clock enable */

RCC_APB1PeriphClockCmd(sEE_I2C_CLK, ENABLE);

/*!< GPIO configuration */

/*!< Configure sEE_I2C pins: SCL */

GPIO_InitStructure.GPIO_Pin = sEE_I2C_SCL_PIN;

11 / 6211 / 62

stm32 i2c dma

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

GPIO_Init(sEE_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

/*!< Configure sEE_I2C pins: SDA */

GPIO_InitStructure.GPIO_Pin = sEE_I2C_SDA_PIN;

GPIO_Init(sEE_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);

/* Configure and enable I2C DMA TX Channel interrupt */

NVIC_InitStructure.NVIC_IRQChannel = sEE_I2C_DMA_TX_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority sEE_I2C_DMA_PREPRIO;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = sEE_I2C_DMA_SUBPRIO;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

/* Configure and enable I2C DMA RX Channel interrupt */

12 / 6212 / 62

=

stm32 i2c dma

NVIC_InitStructure.NVIC_IRQChannel = sEE_I2C_DMA_RX_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority sEE_I2C_DMA_PREPRIO;

=

NVIC_InitStructure.NVIC_IRQChannelSubPriority = sEE_I2C_DMA_SUBPRIO;

NVIC_Init(&NVIC_InitStructure);

/*!< I2C DMA TX and RX channels configuration */

/* Enable the DMA clock */

RCC_AHBPeriphClockCmd(sEE_I2C_DMA_CLK, ENABLE);

/* I2C TX DMA Channel configuration */

DMA_DeInit(sEE_I2C_DMA_CHANNEL_TX);

sEEDMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)sEE_I2C_DR_Address;

=

sEEDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)0; /* This parameter will be configured durig communication */

sEEDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; /* This

13 / 6213 / 62

stm32 i2c dma

parameter will be configured durig communication */

sEEDMA_InitStructure.DMA_BufferSize = 0xFFFF; /* This parameter will be configured durig communication */

sEEDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

sEEDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

sEEDMA_InitStructure.DMA_PeripheralDataSize DMA_MemoryDataSize_Byte;

=

sEEDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

sEEDMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

sEEDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

sEEDMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(sEE_I2C_DMA_CHANNEL_TX, &sEEDMA_InitStructure);

/* I2C RX DMA Channel configuration */

DMA_DeInit(sEE_I2C_DMA_CHANNEL_RX);

14 / 6214 / 62

stm32 i2c dma

DMA_Init(sEE_I2C_DMA_CHANNEL_RX, &sEEDMA_InitStructure);

/* Enable the DMA Channels Interrupts */

DMA_ITConfig(sEE_I2C_DMA_CHANNEL_TX, DMA_IT_TC, ENABLE);

DMA_ITConfig(sEE_I2C_DMA_CHANNEL_RX, DMA_IT_TC, ENABLE);

}

/**

* @brief Initializes DMA channel used by the I2C EEPROM driver.

* @param None

* @retval None

*/

void sEE_LowLevel_DMAConfig(uint32_t pBuffer, uint32_t BufferSize, uint32_t Direction)

{

/* Initialize the DMA with the new parameters */

15 / 6215 / 62

stm32 i2c dma

if (Direction == sEE_DIRECTION_TX)

{

/* Configure the DMA Tx Channel with the buffer address and the buffer size */

sEEDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;

sEEDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

sEEDMA_InitStructure.DMA_BufferSize = (uint32_t)BufferSize;

DMA_Init(sEE_I2C_DMA_CHANNEL_TX, &sEEDMA_InitStructure);

}

else

{

/* Configure the DMA Rx Channel with the buffer address and the buffer size */

sEEDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;

sEEDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

16 / 6216 / 62

stm32 i2c dma

sEEDMA_InitStructure.DMA_BufferSize = (uint32_t)BufferSize;

DMA_Init(sEE_I2C_DMA_CHANNEL_RX, &sEEDMA_InitStructure);

}

}

void sEE_DeInit(void)

{

sEE_LowLevel_DeInit();

}

/**

* @brief Initializes peripherals used by the I2C EEPROM driver.

* @param None

* @retval None

*/

17 / 6217 / 62

stm32 i2c dma

void sEE_Init(void)

{

I2C_InitTypeDef I2C_InitStructure;

sEE_LowLevel_Init();

/*!< I2C configuration */

/* sEE_I2C configuration */

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS7;I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;

/* sEE_I2C Peripheral Enable */

18 / 6218 / 62

=

stm32 i2c dma

I2C_Cmd(sEE_I2C, ENABLE);

/* Apply sEE_I2C configuration after enabling it */

I2C_Init(sEE_I2C, &I2C_InitStructure);

/* Enable the sEE_I2C peripheral DMA requests */

I2C_DMACmd(sEE_I2C, ENABLE);

}

/**

* @brief Reads a block of data from the EEPROM.

* @param pBuffer : pointer to the buffer that receives the data read from

* the EEPROM.

* @param ReadAddr : EEPROM's internal address to start reading from.

* @param NumByteToRead : pointer to the variable holding number of bytes to

* be read from the EEPROM.

19 / 6219 / 62

stm32 i2c dma

*

* @note The variable pointed by NumByteToRead is reset to 0 when all the

* data are read from the EEPROM. Application should monitor this

* variable in order know when the transfer is complete.

*

* @note When number of data to be read is higher than 1, this function just

* configures the communication and enable the DMA channel to transfer data.

* Meanwhile, the user application may perform other tasks.

* When number of data to be read is 1, then the DMA is not used. The byte

* is read in polling mode.

*

20 / 6220 / 62

stm32 i2c dma

* @retval sEE_OK (0) if operation is correctly performed, else return value

* different from sEE_OK (0) or the timeout user callback.

*/

uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)

{

/* Set the pointer to the Number of data to be read. This pointer will be used

by the DMA Transfer Completer interrupt Handler in order to reset the

variable to 0. User should check on this variable in order to know if the

DMA transfer has been complete or not. */

sEEDataReadPointer = NumByteToRead;

/*!< While the bus is busy */

sEETimeout = sEE_LONG_TIMEOUT;

while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))

21 / 6221 / 62

stm32 i2c dma

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send START condition */

I2C_GenerateSTART(sEE_I2C, ENABLE);

/*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send EEPROM address for write */

I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);

22 / 6222 / 62

stm32 i2c dma

/*!< Test on EV6 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C,

I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

#ifdef sEE_M24C08

/*!< Send the EEPROM's internal address to read from: Only one byte address */

I2C_SendData(sEE_I2C, ReadAddr);

#elif defined (sEE_M24C_32)

/*!< Send the EEPROM's internal address to read from: MSB of the address first */

I2C_SendData(sEE_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8)); //发送高位地址

23 / 6223 / 62

stm32 i2c dma

/*!< Test on EV8 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send the EEPROM's internal address to read from: LSB of the address */

I2C_SendData(sEE_I2C, (uint8_t)(ReadAddr & 0x00FF)); //发送低位地址

#endif /*!< sEE_M24C08 */

/*!< Test on EV8 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF) == RESET)

{

24 / 6224 / 62

stm32 i2c dma

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send STRAT condition a second time */

I2C_GenerateSTART(sEE_I2C, ENABLE);

/*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send EEPROM address for read */

I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Receiver);

/* If number of data to be read is 1, then DMA couldn't be used */

25 / 6225 / 62

stm32 i2c dma

/*

One

Byte

Master

Reception

procedure

(POLLING)

---------------------------*/

if ((uint16_t)(*NumByteToRead) < 2)

{

/* Wait on ADDR flag to be set (ADDR is still not cleared at this level */

sEETimeout = sEE_FLAG_TIMEOUT;

while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_ADDR) == RESET)

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Disable Acknowledgement */

I2C_AcknowledgeConfig(sEE_I2C, DISABLE);

/* Call User callback for critical section start (should typically disable interrupts) */

26 / 6226 / 62

stm32 i2c dma

sEE_EnterCriticalSection_UserCallback();

/* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */

(void)sEE_I2C->SR2;

/*!< Send STOP Condition */

I2C_GenerateSTOP(sEE_I2C, ENABLE);

/* Call User callback for critical section end (should typically re-enable interrupts) */

sEE_ExitCriticalSection_UserCallback();

/* Wait for the byte to be received */

sEETimeout = sEE_FLAG_TIMEOUT;

while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_RXNE) == RESET)

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

27 / 6227 / 62

stm32 i2c dma

}

/*!< Read the byte received from the EEPROM */

*pBuffer = I2C_ReceiveData(sEE_I2C);

/*!< Decrement the read bytes counter */

(uint16_t)(*NumByteToRead)--;

/* Wait to make sure that STOP control bit has been cleared */

sEETimeout = sEE_FLAG_TIMEOUT;

while(sEE_I2C->CR1 & I2C_CR1_STOP)

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Re-Enable Acknowledgement to be ready for another reception */

I2C_AcknowledgeConfig(sEE_I2C, ENABLE);

28 / 6228 / 62

stm32 i2c dma

}

else/* More than one Byte Master Reception procedure (DMA) -----------------*/

{

/*!< Test on EV6 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C,

I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/* Configure the DMA Rx Channel with the buffer address and the buffer size */

sEE_LowLevel_DMAConfig((uint32_t)pBuffer, sEE_DIRECTION_RX);

(uint16_t)(*NumByteToRead),

29 / 6229 / 62

stm32 i2c dma

/* Inform the DMA that the next End Of Transfer Signal will be the last one */

I2C_DMALastTransferCmd(sEE_I2C, ENABLE);

/* Enable the DMA Rx Channel */

DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, ENABLE);

}

/* If all operations OK, return sEE_OK (0) */

return sEE_OK;

}

/**

* @brief Writes more than one byte to the EEPROM with a single WRITE cycle.

*

* @note The number of bytes (combined to write start address) must not

* cross the EEPROM page boundary. This function can only write into

30 / 6230 / 62

stm32 i2c dma

* the boundaries of an EEPROM page.

* This function doesn't check on boundaries condition (in this driver

* the function sEE_WriteBuffer() which calls sEE_WritePage() is

* responsible of checking on Page boundaries).

*

* @param pBuffer : pointer to the buffer containing the data to be written to

* the EEPROM.

* @param WriteAddr : EEPROM's internal address to write to.

* @param NumByteToWrite : pointer to the variable holding number of bytes to

* be written into the EEPROM.

*

* @note The variable pointed by NumByteToWrite is reset to 0 when all the

31 / 6231 / 62

stm32 i2c dma

* data are written to the EEPROM. Application should monitor this

* variable in order know when the transfer is complete.

*

* @note This function just configure the communication and enable the DMA

* channel to transfer data. Meanwhile, the user application may perform

* other tasks in parallel.

*

* @retval sEE_OK (0) if operation is correctly performed, else return value

* different from sEE_OK (0) or the timeout user callback.

*/

uint32_t sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite)

{

32 / 6232 / 62

stm32 i2c dma

/* Set the pointer to the Number of data to be written. This pointer will be used

by the DMA Transfer Completer interrupt Handler in order to reset the

variable to 0. User should check on this variable in order to know if the

DMA transfer has been complete or not. */

sEEDataWritePointer = NumByteToWrite;

/*!< While the bus is busy */

sEETimeout = sEE_LONG_TIMEOUT;

while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send START condition */

I2C_GenerateSTART(sEE_I2C, ENABLE);//开始符号

33 / 6233 / 62

stm32 i2c dma

/*!< Test on EV5 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send EEPROM address for write */

sEETimeout = sEE_FLAG_TIMEOUT;

//写器件地址最后一位由方向控制

I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);//0xa0

/*!< Test on EV6 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C,

I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

34 / 6234 / 62

stm32 i2c dma

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

#ifdef sEE_M24C08

/*!< Send the EEPROM's internal address to write to : only one byte Address */

I2C_SendData(sEE_I2C, WriteAddr);

#elif defined(sEE_M24C_32)

/*!< Send the EEPROM's internal address to write to : MSB of the address first */

I2C_SendData(sEE_I2C, (uint8_t)((WriteAddr & 0xFF00) >> 8));

/*!< Test on EV8 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

{

35 / 6235 / 62

stm32 i2c dma

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send the EEPROM's internal address to write to : LSB of the address */

I2C_SendData(sEE_I2C, (uint8_t)(WriteAddr & 0x00FF));

#endif /*!< sEE_M24C08 */

/*!< Test on EV8 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/* Configure the DMA Tx Channel with the buffer address and the buffer size */

sEE_LowLevel_DMAConfig((uint32_t)pBuffer, sEE_DIRECTION_TX);

36 / 6236 / 62

(uint8_t)(*NumByteToWrite),

stm32 i2c dma

/* Enable the DMA Tx Channel */

DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, ENABLE);

/* If all operations OK, return sEE_OK (0) */

return sEE_OK;

}

/**

* @brief Writes buffer of data to the I2C EEPROM.

* @param pBuffer : pointer to the buffer containing the data to be written

* to the EEPROM.

* @param WriteAddr : EEPROM's internal address to write to.

* @param NumByteToWrite : number of bytes to write to the EEPROM.

* @retval None

*/

37 / 6237 / 62

stm32 i2c dma

void

sEE_WriteBuffer(uint8_t*

pBuffer,

uint16_t

WriteAddr,

uint16_t

NumByteToWrite)

{

uint8_t NumOfPage = 0, NumOfSingle = 0, count = 0;

uint16_t Addr = 0;

Addr = WriteAddr % sEE_PAGESIZE;

count = sEE_PAGESIZE - Addr;

NumOfPage = NumByteToWrite / sEE_PAGESIZE;

NumOfSingle = NumByteToWrite % sEE_PAGESIZE;

/*!< If WriteAddr is sEE_PAGESIZE aligned */

if(Addr == 0)

{

/*!< If NumByteToWrite < sEE_PAGESIZE */

if(NumOfPage == 0)

38 / 6238 / 62

stm32 i2c dma

{

/* Store the number of data to be written */

sEEDataNum = NumOfSingle;

/* Start writing data */

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

}

sEE_WaitEepromStandbyState();

}

39 / 6239 / 62

stm32 i2c dma

/*!< If NumByteToWrite > sEE_PAGESIZE */

else

{

while(NumOfPage--)

{

/* Store the number of data to be written */

sEEDataNum = sEE_PAGESIZE;

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

40 / 6240 / 62

stm32 i2c dma

}

sEE_WaitEepromStandbyState();

WriteAddr += sEE_PAGESIZE;

pBuffer += sEE_PAGESIZE;

}

if(NumOfSingle!=0)

{

/* Store the number of data to be written */

sEEDataNum = NumOfSingle;

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

41 / 6241 / 62

stm32 i2c dma

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

}

sEE_WaitEepromStandbyState();

}

}

}

/*!< If WriteAddr is not sEE_PAGESIZE aligned else

{

/*!< If NumByteToWrite < sEE_PAGESIZE */

if(NumOfPage== 0)

{

42 / 6242 / 62

*/

stm32 i2c dma

/*!< If the number of data to be written is more than the remaining space

in the current page: */

if (NumByteToWrite > count)

{

/* Store the number of data to be written */

sEEDataNum = count;

/*!< Write the data conained in same page */

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

43 / 6243 / 62

stm32 i2c dma

}

sEE_WaitEepromStandbyState();

/* Store the number of data to be written */

sEEDataNum = (NumByteToWrite - count);

/*!< Write the remaining data in the following page */

sEE_WritePage((uint8_t*)(pBuffer + count), (WriteAddr + (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; }

44 / 6244 / 62

count),

stm32 i2c dma

sEE_WaitEepromStandbyState();

}

else

{

/* Store the number of data to be written */

sEEDataNum = NumOfSingle;

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

}

45 / 6245 / 62

stm32 i2c dma

sEE_WaitEepromStandbyState();

}

}

/*!< If NumByteToWrite > sEE_PAGESIZE */

else

{

NumByteToWrite -= count;

NumOfPage = NumByteToWrite / sEE_PAGESIZE;

NumOfSingle = NumByteToWrite % sEE_PAGESIZE;

if(count != 0)

{

/* Store the number of data to be written */

46 / 6246 / 62

stm32 i2c dma

sEEDataNum = count;

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

}

sEE_WaitEepromStandbyState();

WriteAddr += count;

pBuffer += count;

}

47 / 6247 / 62

stm32 i2c dma

while(NumOfPage--)

{

/* Store the number of data to be written */

sEEDataNum = sEE_PAGESIZE;

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

}

sEE_WaitEepromStandbyState();

WriteAddr += sEE_PAGESIZE;

48 / 6248 / 62

stm32 i2c dma

pBuffer += sEE_PAGESIZE;

}

if(NumOfSingle != 0)

{

/* Store the number of data to be written */

sEEDataNum = NumOfSingle;

sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));

/* Wait transfer through DMA to be complete */

sEETimeout = sEE_LONG_TIMEOUT;

while (sEEDataNum > 0)

{

if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};

}

49 / 6249 / 62

stm32 i2c dma

sEE_WaitEepromStandbyState();

}

}

}

}

/**

* @brief Wait for EEPROM Standby state.

*

* @note This function allows to wait and check that EEPROM has finished the

* last Write operation. It is mostly used after Write operation: after

* receiving the buffer to be written, the EEPROM may need additional

* time to actually perform the write operation. During this time, it

* doesn't answer to I2C packets addressed to it. Once the write operation

50 / 6250 / 62

stm32 i2c dma

* is complete the EEPROM responds to its address.

*

* @note It is not necessary to call this function after sEE_WriteBuffer()

* function (sEE_WriteBuffer() already calls this function after each

* write page operation).

*

* @param None

* @retval sEE_OK (0) if operation is correctly performed, else return value

* different from sEE_OK (0) or the timeout user callback.

*/

uint32_t sEE_WaitEepromStandbyState(void)

{

__IO uint16_t tmpSR1 = 0;

51 / 6251 / 62

stm32 i2c dma

__IO uint32_t sEETrials = 0;

/*!< While the bus is busy */

sEETimeout = sEE_LONG_TIMEOUT;

while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/* Keep looping till the slave acknowledge his address or maximum number

of trials is reached (this number is defined by sEE_MAX_TRIALS_NUMBER define

in stm32_eval_i2c_ee.h file) */

while (1)

{

/*!< Send START condition */

52 / 6252 / 62

stm32 i2c dma

I2C_GenerateSTART(sEE_I2C, ENABLE);

/*!< Test on EV5 and clear it */

sEETimeout = sEE_FLAG_TIMEOUT;

while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))

{

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/*!< Send EEPROM address for write */

I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);

/* Wait for ADDR flag to be set (Slave acknowledged his address) */

sEETimeout = sEE_LONG_TIMEOUT;

do

{

53 / 6253 / 62

stm32 i2c dma

/* Get the current value of the SR1 register */

tmpSR1 = sEE_I2C->SR1;

/* Update the timeout value and exit if it reach 0 */

if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();

}

/* Keep looping till the Address is acknowledged or the AF flag is

set (address not acknowledged at time) */

while((tmpSR1 & (I2C_SR1_ADDR | I2C_SR1_AF)) == 0);

/* Check if the ADDR flag has been set */

if (tmpSR1 & I2C_SR1_ADDR)

{

54 / 6254 / 62

stm32 i2c dma

/* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already

been read) */

(void)sEE_I2C->SR2;

/*!< STOP condition */

I2C_GenerateSTOP(sEE_I2C, ENABLE);

/* Exit the function */

return sEE_OK;

}

else

{

/*!< Clear AF flag */

55 / 6255 / 62

stm32 i2c dma

I2C_ClearFlag(sEE_I2C, I2C_FLAG_AF);

}

/* Check if the maximum allowed numbe of trials has bee reached */

if (sEETrials++ == sEE_MAX_TRIALS_NUMBER)

{

/* If the maximum number of trials has been reached, exit the function */

return sEE_TIMEOUT_UserCallback();

}

}

}

/**

* @brief This function handles the DMA Tx Channel interrupt Handler.

* @param None

56 / 6256 / 62

stm32 i2c dma

* @retval None

*/

void sEE_I2C_DMA_TX_IRQHandler(void)

{

/* Check if the DMA transfer is complete */

if(DMA_GetFlagStatus(sEE_I2C_DMA_FLAG_TX_TC) != RESET)

{

/* Disable the DMA Tx Channel and Clear all its Flags */

DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, DISABLE);

DMA_ClearFlag(sEE_I2C_DMA_FLAG_TX_GL);

/*!< Wait till all data have been physically transferred on the bus */

sEETimeout = sEE_LONG_TIMEOUT;

while(!I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF))

57 / 6257 / 62

stm32 i2c dma

{

if((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback();

}

/*!< Send STOP condition */

I2C_GenerateSTOP(sEE_I2C, ENABLE);

/* Perform a read on SR1 and SR2 register to clear eventualaly pending flags */

(void)sEE_I2C->SR1;

(void)sEE_I2C->SR2;

/* Reset the variable holding the number of data to be written */

*sEEDataWritePointer = 0;

}

}

/**

58 / 6258 / 62

stm32 i2c dma

* @brief This function handles the DMA Rx Channel interrupt Handler.

* @param None

* @retval None

*/

void sEE_I2C_DMA_RX_IRQHandler(void)

{

/* Check if the DMA transfer is complete */

if(DMA_GetFlagStatus(sEE_I2C_DMA_FLAG_RX_TC) != RESET)

{

/*!< Send STOP Condition */

I2C_GenerateSTOP(sEE_I2C, ENABLE);

/* Disable the DMA Rx Channel and Clear all its Flags */

DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, DISABLE);

59 / 6259 / 62

stm32 i2c dma

DMA_ClearFlag(sEE_I2C_DMA_FLAG_RX_GL);

/* Reset the variable holding the number of data to be read */

*sEEDataReadPointer = 0;

}

}

uint32_t sEE_TIMEOUT_UserCallback(void)

{

/* Block communication and all processes */

while (1)

{

}

}

void sEE_EnterCriticalSection_UserCallback(void)

60 / 6260 / 62

stm32 i2c dma

{

__disable_irq();

}

/**

* @brief Start and End of critical section: these callbacks should be typically used

* to re-enable interrupts when exiting a critical section of I2C communication

* You may use default callbacks provided into this driver by uncommenting the

* define USE_DEFAULT_CRITICAL_CALLBACK.

* Or you can comment that line and implement these callbacks into your

* application.

* @param None.

61 / 6261 / 62

stm32 i2c dma

* @retval None.

*/

void sEE_ExitCriticalSection_UserCallback(void)

{

__enable_irq();

}

此文件是按照官方版修改的,经过测试,非常好用(*^__^*) 嘻嘻……

用的i2c1,只要将上面两个文件包含在工程文件里面,就可以直接调用。

特此来这晒一下!

62 / 6262 / 62

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- baoquwan.com 版权所有 湘ICP备2024080961号-7

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务