cancel
Showing results for 
Search instead for 
Did you mean: 

Connect with LM75 through I2C/DMA on ST32100B

ptumati
Associate II
Posted on July 16, 2012 at 11:28

Hi,

I am try to develop a simple I2C “receive data�? type of function; I took most of the code from the zip file that I was able to download from the st webpages.

The main function of interest getBytesI2C1DMA() sends a “0�? to the onboard LM75 and receives two bytes that contain the temperature information. I see the two temperature related bytes in the logic analyzer, but I don’t see the value getting copied into the LM75_BufferRX buffer. LM75_BufferRX[0] and LM75_BufferRX[1] are both reporting 0x0B and the final value that is stored in “tmp�? is wrong. It looks like the DMA copy is failing. I have spent hours trying to figure out whats going wrong here. Can you please point me to the flaw in this code?

Any suggestions/advice is highly appreciated.

typedef

enum

{

TX = 0,

RX = 1

} DMADirection_TypeDef;

uint16_t getBytesI2C1DMA(

int

address,

int

totalBytes) // <---- Problem FUNCTION

{

uint8_t LM75_BufferRX[10] ={1,1,0,0,0,0,0,0,0,0};

if

(totalBytes>10)

return

0;

sendByteI2C1(address, 0);

// Configure DMA Peripheral

DMA_Config(RX, (uint8_t*)LM75_BufferRX, totalBytes);

// Enable DMA NACK automatic generation

I2C_DMALastTransferCmd(I2C1, ENABLE);

// Send START condition a second time

I2C_GenerateSTART(I2C1, ENABLE);

/* Test on SB Flag */

I1C1_Timeout = FLAG_TIMEOUT;

while

(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB)) {

if

((I1C1_Timeout--) == 0)

return

0;

}

/* Send LM75 address for read */

I2C_Send7bitAddress(I2C1, address, I2C_Direction_Receiver);

/* Test on ADDR Flag */

I1C1_Timeout = FLAG_TIMEOUT;

while

(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {

if

((I1C1_Timeout--) == 0)

return

0;

}

// Enable I2C DMA request

I2C_DMACmd(I2C1,ENABLE);

// Enable DMA RX Channel

DMA_Cmd(DMA1_Channel7, ENABLE);

// Wait until DMA Transfer Complete

I1C1_Timeout = LONG_TIMEOUT;

while

(!DMA_GetFlagStatus(DMA1_FLAG_TC7)) {

if

((I1C1_Timeout--) == 0)

return

0;

}

// Send STOP Condition

I2C_GenerateSTOP(I2C1, ENABLE);

// Disable DMA RX Channel

DMA_Cmd(DMA1_Channel7, DISABLE);

// Disable I2C DMA request

I2C_DMACmd(I2C1, DISABLE);

// Clear DMA RX Transfer Complete Flag

DMA_ClearFlag(DMA1_FLAG_TC7);

//!< Store LM75_I2C received data

tmp = (uint16_t)(LM75_BufferRX[0] << 8); <------- LM75_BufferRX[0] & [1] contain 0x0B which is not the value I see in the logic analyzer

tmp |= LM75_BufferRX[1];

//!< Return Temperature value

tmp=(uint16_t)(tmp >> 7);

return

tmp; 

}  

static

void

DMA_Config(DMADirection_TypeDef Direction, uint8_t* buffer, uint8_t NumData)

{

DMA_InitTypeDef DMA_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* Initialize the DMA_PeripheralBaseAddr member */

DMA_InitStructure.DMA_PeripheralBaseAddr = I2C1_BASE;

/* Initialize the DMA_MemoryBaseAddr member */

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer;

/* 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_M2M member */

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

/* If using DMA for Reception */

if

(Direction == RX)

{

/* Initialize the DMA_DIR member */

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

/* Initialize the DMA_BufferSize member */

DMA_InitStructure.DMA_BufferSize = NumData;

DMA_DeInit(DMA1_Channel7);

DMA_Init(DMA1_Channel7, &DMA_InitStructure);

}

/* If using DMA for Transmission */

else

if

(Direction == TX)

{

/* Initialize the DMA_DIR member */

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

/* Initialize the DMA_BufferSize member */

DMA_InitStructure.DMA_BufferSize = NumData;

DMA_DeInit(DMA1_Channel6);

DMA_Init(DMA1_Channel6, &DMA_InitStructure);

}

}

int

sendByteI2C1(

int

address,

int

byte)

{

/* Test on BUSY Flag */

I1C1_Timeout = LONG_TIMEOUT;

while

(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY))

if

((I1C1_Timeout--) == 0)

return

0;

/* Enable the I2C peripheral */

I2C_GenerateSTART(I2C1, ENABLE);

// Test on SB Flag

I1C1_Timeout = FLAG_TIMEOUT;

while

(!I2C_GetFlagStatus(I2C1,I2C_FLAG_SB))

if

((I1C1_Timeout--) == 0)

return

0;

/* Send device address for write */

I2C_Send7bitAddress(I2C1, address, I2C_Direction_Transmitter);

/* Test on ADDR Flag */

I1C1_Timeout = FLAG_TIMEOUT;

while

(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

if

((I1C1_Timeout--) == 0)

return

0;

I2C_SendData(I2C1, byte);

/* Test on ADDR Flag */

I1C1_Timeout = FLAG_TIMEOUT;

while

(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))

// EV-8

if

((I1C1_Timeout--) == 0)

return

0;

return

1;

}

This is how I initialize the I2C interface

void

initI2C()

{

I2C_InitTypeDef I2C_InitStructure;

//---------------------------------------------------------

//-------------- Initialize GPIO

GPIO_InitTypeDef GPIO_InitStructure;

/*!< I2C1 Periph clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

/*!< LM75_I2C_SCL_GPIO_CLK, LM75_I2C_SDA_GPIO_CLK

and LM75_I2C_SMBUSALERT_GPIO_CLK Periph clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB, ENABLE);

/*!< Configure I2C1 pins: SCL */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

GPIO_Init(GPIOB, &GPIO_InitStructure);

/*!< Configure I2C1 pins: SDA */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

GPIO_Init(GPIOB, &GPIO_InitStructure);

/*!< Configure I2C1 pin: SMBUS ALERT */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

GPIO_Init(GPIOB, &GPIO_InitStructure);

//-----------------------------------------------------------

I2C_DeInit(I2C1);

/*!< I2C1 Init */

I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = 0x00;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_ClockSpeed = L2C_SPEED;

I2C_Init(I2C1, &I2C_InitStructure);

/*!< Enable SMBus Alert interrupt */

I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);

/*!< I2C1 Init */

I2C_Cmd(I2C1, ENABLE);

}

#i2c-lm75-dma #stm32-i2c-dma

1 REPLY 1
davedave9
Associate
Posted on July 29, 2012 at 23:34

I'd like to bump this post...

Having the same problem with this code. I've modified it to be used with a MCP23 This is an I2C 16 bit port expander, but the theory is the same and very little of the code needed changes. DMA functions are returning/sending the (byte wise) MSB and dropping the LSB. I've copied the WriteReg and ReadReg functions and subsituted the DMA calls with the extra I2C_Receive() and I2C_Send calls and the functions work fine. Has anyone looked at this as of recent? Update: 7/30/2012 I've got it to work... but I don't like the fix... This code:

/* Test on BUSY Flag */
MCP27XXX_Timeout = MCP27XXX_LONG_TIMEOUT;
while (I2C_GetFlagStatus(MCP27XXX_I2C,I2C_FLAG_BUSY)) 
{
if((MCP27XXX_Timeout--) == 0) return MCP27XXX_TIMEOUT_UserCallback();
}
/* Configure DMA Peripheral */
MCP27XXX_DMA_Config(MCP27XXX_DMA_TX, &MCP27XXX_BufferTX[0], 3);
/* Enable the I2C peripheral */
I2C_GenerateSTART(MCP27XXX_I2C, ENABLE);

gets the job done... this tells the DMA controller to send one more byte than the buffer length. I have verified that the code does wait for the TXE and BTF flags before calling GenerateSTOP() so it's not an issue of the DMA controller being cut off while transmitting the last byte. At least it doesn't seem that way. --Dave