Hi,
I have developed the following code to implement the i2c combined format read where you first write to a register, do a repeat stop, and then read.
My code produces the correct results in the debugger. However, once I have read from the device, I cannot repeat the act. I have to reset the stm32 and reset the device in order to repeat.
I am totally stumped by this. Can anyone spot the issue?
Here is my code...Please help
#include "main.h"
/** @addtogroup STM32F2xx_StdPeriph_Examples
* @{
*/
/** @addtogroup I2C_DataExchangeDMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define countof(a) (sizeof(a) / sizeof(*(a)))
uint8_t SlaveAddrWriteBit =0x52; //0b1010010; 0x29;
uint8_t SlaveAddReadBit =0x53; //0b1010011;
uint8_t CommandCode =0xA3; // =0xB2; 0xA3 //0b10100011;
/* Private variables ---------------------------------------------------------*/
I2C_InitTypeDef I2C_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
uint8_t TxBuffer[] = "I2C DMA Example: Communication between two I2C using DMA";
uint8_t RxBuffer [256];
__IO uint32_t TimeOut = 0x0;
RCC_ClocksTypeDef RCC_Clocks;
volatile uint8_t tester = 0x00;
/* Private function prototypes -----------------------------------------------*/
static void I2C_Config(void);
static void SysTickConfig(void);
static void TimeOut_UserCallback(void);
static void Fill_Buffer(uint8_t *pBuffer, uint16_t BufferLength);
/* Private functions ---------------------------------------------------------*/
int main(void)
{
/* I2C configuration ---------------------------------------------------------*/
I2C_Config();
/* SysTick configuration -----------------------------------------------------*/
SysTickConfig();
/* Clear the RxBuffer */
Fill_Buffer(RxBuffer, RXBUFFERSIZE);
/*************************************Combined Write and Read*******/
/* I2C Struct Initialize */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE;
I2C_InitStructure.I2C_OwnAddress1 = 0xA0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
#ifndef I2C_10BITS_ADDRESS
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
#else
#endif /* I2C_10BITS_ADDRESS */
/* I2C Initialize */
I2C_Init(I2Cx, &I2C_InitStructure);
/* Master Transmitter --------------------------------------------------------*/
/* Generate the Start condition */
I2C_GenerateSTART(I2Cx, ENABLE);
/* Test on I2Cx EV5 and clear it or time out */
TimeOut = USER_TIMEOUT;
while ((!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
TimeOut_UserCallback();
}
/* Send I2Cx slave Address for write */
I2C_Send7bitAddress(I2Cx, SlaveAddrWriteBit, I2C_Direction_Transmitter);
/* Test on I2Cx EV6 and clear it or time out */
TimeOut = USER_TIMEOUT;
// while ((!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))&&(TimeOut != 0x00))
while ((!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
TimeOut_UserCallback();
}
//commandcode to be inserted here
I2C_SendData(I2Cx, CommandCode);
//repeatstart
/* Generate the Start condition */
/* Send I2Cx START condition */
I2C_GenerateSTART(I2Cx, ENABLE);
/* Test on I2Cx EV5 and clear it or time out*/
TimeOut = USER_TIMEOUT;
while ((!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
tester++;
// TimeOut_UserCallback();
}
/* Send I2Cx slave Address for write */ //was receiver
I2C_Send7bitAddress(I2Cx, SlaveAddReadBit, I2C_Direction_Receiver);
/* Test on I2Cx EV6 and clear it or time out */
TimeOut = USER_TIMEOUT; //was receiver***
while ((!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
// flag++;
TimeOut_UserCallback();
}
/* I2Cx DMA Enable */
I2C_DMACmd(I2Cx, ENABLE);
/* Enable DMA RX Channel */
DMA_Cmd(I2Cx_DMA_STREAM_RX, ENABLE);
/* Wait until I2Cx_DMA_STREAM_RX enabled or time out */
TimeOut = USER_TIMEOUT;
while ((DMA_GetCmdStatus(I2Cx_DMA_STREAM_RX)!= ENABLE)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
TimeOut_UserCallback();
}
/* Transfer complete or time out */
TimeOut = USER_TIMEOUT;
while ((DMA_GetFlagStatus(I2Cx_DMA_STREAM_RX,I2Cx_RX_DMA_TCFLAG)==RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
TimeOut_UserCallback();
}
/* Send I2Cx STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* Disable DMA RX Channel */
DMA_Cmd(I2Cx_DMA_STREAM_RX, DISABLE);
/* Wait until I2Cx_DMA_STREAM_RX disabled or time out */
TimeOut = USER_TIMEOUT;
while ((DMA_GetCmdStatus(I2Cx_DMA_STREAM_RX)!= DISABLE)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
TimeOut_UserCallback();
}
/* Disable I2C DMA request */
I2C_DMACmd(I2Cx,DISABLE);
/* Clear any pending flag on Rx Stream */
DMA_ClearFlag(I2Cx_DMA_STREAM_RX, I2Cx_RX_DMA_TCFLAG | I2Cx_RX_DMA_FEIFLAG | I2Cx_RX_DMA_DMEIFLAG | \
I2Cx_RX_DMA_TEIFLAG | I2Cx_RX_DMA_HTIFLAG);
while(1)
{}
}
/**
* @brief Enables the I2C Clock and configures the different GPIO ports.
* @param None
* @retval None
*/
static void I2C_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* RCC Configuration */
/*I2C Peripheral clock enable */
RCC_APB1PeriphClockCmd(I2Cx_CLK, ENABLE);
/*SDA GPIO clock enable */
RCC_AHB1PeriphClockCmd(I2Cx_SDA_GPIO_CLK, ENABLE);
/*SCL GPIO clock enable */
RCC_AHB1PeriphClockCmd(I2Cx_SCL_GPIO_CLK, ENABLE);
/* Reset I2Cx IP */
RCC_APB1PeriphResetCmd(I2Cx_CLK, ENABLE);
/* Release reset signal of I2Cx IP */
RCC_APB1PeriphResetCmd(I2Cx_CLK, DISABLE);
/* Enable the DMA clock */
RCC_AHB1PeriphClockCmd(DMAx_CLK, ENABLE);
/* GPIO Configuration */
/*Configure I2C SCL pin */
GPIO_InitStructure.GPIO_Pin = I2Cx_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStructure);
/*Configure I2C SDA pin */
GPIO_InitStructure.GPIO_Pin = I2Cx_SDA_PIN;
GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStructure);
/* Connect PXx to I2C_SCL */
GPIO_PinAFConfig(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_SOURCE, I2Cx_SCL_AF);
/* Connect PXx to I2C_SDA */
GPIO_PinAFConfig(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_SOURCE, I2Cx_SDA_AF);
/* DMA Configuration */
/* Clear any pending flag on Tx Stream */
DMA_ClearFlag(I2Cx_DMA_STREAM_TX, I2Cx_TX_DMA_TCFLAG | I2Cx_TX_DMA_FEIFLAG | I2Cx_TX_DMA_DMEIFLAG | \
I2Cx_TX_DMA_TEIFLAG | I2Cx_TX_DMA_HTIFLAG);
/* Clear any pending flag on Rx Stream */
DMA_ClearFlag(I2Cx_DMA_STREAM_RX, I2Cx_RX_DMA_TCFLAG | I2Cx_RX_DMA_FEIFLAG | I2Cx_RX_DMA_DMEIFLAG | \
I2Cx_RX_DMA_TEIFLAG | I2Cx_RX_DMA_HTIFLAG);
/* Disable the I2C Tx DMA stream */
DMA_Cmd(I2Cx_DMA_STREAM_TX, DISABLE);
/* Configure the DMA stream for the I2C peripheral TX direction */
DMA_DeInit(I2Cx_DMA_STREAM_TX);
/* Disable the I2C Rx DMA stream */
DMA_Cmd(I2Cx_DMA_STREAM_RX, DISABLE);
/* Configure the DMA stream for the I2C peripheral RX direction */
DMA_DeInit(I2Cx_DMA_STREAM_RX);
/* Initialize the DMA_Channel member */
DMA_InitStructure.DMA_Channel = I2Cx_DMA_CHANNEL;
/* Initialize the DMA_PeripheralBaseAddr member */
DMA_InitStructure.DMA_PeripheralBaseAddr = I2Cx_DR_ADDRESS;
/* Initialize the DMA_PeripheralInc member */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/* Initialize the DMA_MemoryInc member */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/* Initialize the DMA_PeripheralDataSize member */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
/* Initialize the DMA_MemoryDataSize member */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
/* Initialize the DMA_Mode member */
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
/* Initialize the DMA_Priority member */
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
/* Initialize the DMA_FIFOMode member */
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
/* Initialize the DMA_FIFOThreshold member */
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
/* Initialize the DMA_MemoryBurst member */
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
/* Initialize the DMA_PeripheralBurst member */
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
/* Init DMA for Reception */
/* Initialize the DMA_DIR member */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
/* Initialize the DMA_Memory0BaseAddr member */
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)RxBuffer;
/* Initialize the DMA_BufferSize member */
DMA_InitStructure.DMA_BufferSize = RXBUFFERSIZE;
DMA_DeInit(I2Cx_DMA_STREAM_RX);
DMA_Init(I2Cx_DMA_STREAM_RX, &DMA_InitStructure);
/* Init DMA for Transmission */
/* Initialize the DMA_DIR member */
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
/* Initialize the DMA_Memory0BaseAddr member */
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)TxBuffer;
/* Initialize the DMA_BufferSize member */
DMA_InitStructure.DMA_BufferSize = TXBUFFERSIZE;
DMA_DeInit(I2Cx_DMA_STREAM_TX);
DMA_Init(I2Cx_DMA_STREAM_TX, &DMA_InitStructure);
/* I2C ENABLE */
I2C_Cmd(I2Cx, ENABLE);
}
/**
* @brief Configure a SysTick Base time to 10 ms.
* @param None
* @retval None
*/
static void SysTickConfig(void)
{
/* SysTick end of count event each 10ms */
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
/* Configure the SysTick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x0);
}
/**
* @brief Compares two buffers.
* @param pBuffer1, pBuffer2: buffers to be compared.
* @param BufferLength: buffer's length
* @retval PASSED: pBuffer1 identical to pBuffer2
* FAILED: pBuffer1 differs from pBuffer2
*/
/**
* @brief Fills buffer.
* @param pBuffer: pointer on the Buffer to fill
* @param BufferLength: size of the buffer to fill
* @retval None
*/
static void Fill_Buffer(uint8_t *pBuffer, uint16_t BufferLength)
{
uint16_t index = 0;
/* Put in global buffer same values */
for (index = 0; index < BufferLength; index++ )
{
pBuffer[index] = 0x00;
}
}
/**
* @brief Basic management of the timeout situation.
* @param None.
* @retval None.
*/
static void TimeOut_UserCallback(void)
{
/* User can add his own implementation to manage TimeOut Communication failure */
/* Block communication and all processes */
while (1)
{
//flag++;
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{}
}
#endif
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/