2016-02-22 47 views
0

如何使用I2C从LSM303DLHC(磁力计)读取数据,并通过DMA将数据存储在内存中,缓冲区中?STM32F401C - 发现板:具有DMA的I2C

我试图修改“LSM303DLHC_Read()”函数与DMA但对SerialChart输出使用它始终为0

你能告诉我I2C与DMA的例子吗?

uint16_t LSM303DLHC_DMA_Read(uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToRead) 
{ 
    __IO uint32_t LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT; 
    __IO uint32_t temp; 

    I2C_Initialization(); 
    DMA_Config(); 
restart: 

    LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT; 
    /* Send START condition */ 
    I2C_GenerateSTART(LSM303DLHC_I2C, ENABLE); 
    /* Test on EV5 and clear it */ 
    while (!I2C_CheckEvent(LSM303DLHC_I2C, I2C_EVENT_MASTER_MODE_SELECT)) 
    { 
    if (LSM303DLHC_Timeout-- == 0) 
     return ERROR; 
    } 

    /* Active the needed channel Request */ 
    I2C_DMACmd(I2C1, ENABLE); 

    LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT; 
    /* Send slave address for read */ 
    I2C_Send7bitAddress(LSM303DLHC_I2C, DeviceAddr, I2C_Direction_Transmitter); 

    while (!I2C_CheckEvent(LSM303DLHC_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) 
    { 
    if (LSM303DLHC_Timeout-- == 0) 
    { 
     I2C_ClearFlag(LSM303DLHC_I2C,I2C_FLAG_BUSY|I2C_FLAG_AF); 
     goto restart; 
    } 
    } 
    /* Clear EV6 by setting again the PE bit */ 
    I2C_Cmd(LSM303DLHC_I2C, ENABLE); 

    I2C_SendData(LSM303DLHC_I2C, RegisterAddr); 

    /* Test on EV8 and clear it */ 
    LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT; 
    while (!I2C_CheckEvent(LSM303DLHC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) 
    { 
    if (LSM303DLHC_Timeout-- == 0) 
    return ERROR; 
    } 

    if (NumByteToRead == 0x01) 
    { 
    restart3: 
    /* Send START condition */ 
    I2C_GenerateSTART(LSM303DLHC_I2C, ENABLE); 
    while (!I2C_CheckEvent(LSM303DLHC_I2C, I2C_EVENT_MASTER_MODE_SELECT)); 
    /* Send Slave address for read */ 
    I2C_Send7bitAddress(LSM303DLHC_I2C, DeviceAddr, I2C_Direction_Receiver); 
    /* Wait until ADDR is set */ 
    LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT; 
    while (!I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_FLAG_ADDR)) 
    { 
     if (LSM303DLHC_Timeout-- == 0) 
     { 
     I2C_ClearFlag(LSM303DLHC_I2C,I2C_FLAG_BUSY|I2C_FLAG_AF); 
     goto restart3; 
     } 
    } 
    /* Clear ACK */ 
    I2C_AcknowledgeConfig(LSM303DLHC_I2C, DISABLE); 
    I2C_NACKPositionConfig(LSM303DLHC_I2C, I2C_NACKPosition_Current); 
    __disable_irq(); 
    /* Clear ADDR flag */ 
    temp = LSM303DLHC_I2C->SR2; 
    /* Program the STOP */ 
    I2C_GenerateSTOP(LSM303DLHC_I2C, ENABLE); 
    __enable_irq(); 
    while ((I2C_GetLastEvent(LSM303DLHC_I2C) & 0x0040) != 0x000040); /* Poll on RxNE */ 
    I2C_DMACmd(I2C1, DISABLE); 
    /* Read the data */ 
    //*pBuffer = I2C_ReceiveData(LSM303DLHC_I2C); 
    /* Make sure that the STOP bit is cleared by Hardware before CR1 write access */ 
    while ((LSM303DLHC_I2C->CR1&0x200) == 0x200); 
    /* Enable Acknowledgement to be ready for another reception */ 
    I2C_AcknowledgeConfig(LSM303DLHC_I2C, ENABLE); 

    return SUCCESS; 
    } 
} 

这是DMA配置:

void DMA_Config(void) 
{ 
    DMA_InitTypeDef DMA_InitStructure; 

    /* Enable DMA clock */ 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); 

    /* Reset DMA Stream registers (for debug purpose) */ 
    DMA_DeInit(DMA1_Stream0); 

    /* Check if the DMA Stream is disabled before enabling it. 
    Note that this step is useful when the same Stream is used multiple times: 
    enabled, then disabled then re-enabled... In this case, the DMA Stream disable 
    will be effective only at the end of the ongoing data transfer and it will 
    not be possible to re-configure it before making sure that the Enable bit 
    has been cleared by hardware. If the Stream is used only once, this step might 
    be bypassed. */ 
    while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE) {} 

    /* Configure DMA Stream */ 
    DMA_InitStructure.DMA_Channel = DMA_Channel_1; 
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C_Register_DR; 
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer_X; 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
    DMA_InitStructure.DMA_BufferSize = 1 ; 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_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_FIFOMode = DMA_FIFOMode_Disable; 
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; 
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
    DMA_Init(DMA1_Stream0, &DMA_InitStructure); 

    /* Enable DMA Stream Transfer Complete interrupt */ 
    DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE); 

    /* DMA Stream enable */ 
    DMA_Cmd(DMA1_Stream0, ENABLE); 

    /* Check if the DMA Stream has been effectively enabled. 
    The DMA Stream Enable bit is cleared immediately by hardware if there is an 
    error in the configuration parameters and the transfer is no started (ie. when 
    wrong FIFO threshold is configured ...) */ 
// while ((DMA_GetCmdStatus(DMA2_Stream0) != ENABLE)) 
// { } 

} 

这是I2C总线的配置:

void I2C_Initialization(void) 
{ 
GPIO_InitTypeDef GPIO_InitStructure; 
I2C_InitTypeDef I2C_InitStructure; 

/* Enable the I2C periph */ 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); 

/* Enable SCK and SDA GPIO clocks */ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); 

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); 
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); 

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

/* I2C SCK pin configuration */ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 

/* I2C SDA pin configuration */ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 

/* I2C configuration -------------------------------------------------------*/ 
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; 
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 = 100000; 

/* Apply LSM303DLHC_I2C configuration after enabling it */ 
I2C_Init(I2C1, &I2C_InitStructure); 

/* Active the needed channel Request */ 
//I2C_DMACmd(I2C1, ENABLE); 

/* LSM303DLHC_I2C Peripheral Enable */ 
I2C_Cmd(I2C1, ENABLE); 
} 

回答

0

我的第一个问题是,为什么你有DMA配置和I2C初始化函数在读取功能?

+0

我从STM32F4库复制此功能,在我的代码我有正确的这一点,并在代码中(主)的另一部分移动两个配置功能。 –

+0

我不知道DMA配置是否正确以及如何修改“LSM303DLHC_DMA_Read”函数以使用DMA与I2C。 –

0

我相信你错过了DMA1_Stream6的配置行。您需要更改DMA_InitStructure并初始化Tx流 - 现在您只是初始化Rx流。像下面这样的东西应该工作:

DMA_InitTypeDef DMA_InitStructure; 

DMA_DeInit(DMA1_Stream0); //reset DMA1 channe1 to default values; 

DMA_InitStructure.DMA_Channel = DMA_Channel_1; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_ADDRESS; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)I2C_RxBuffer; 
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; 
DMA_InitStructure.DMA_BufferSize = 1; 
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_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_FIFOMode = DMA_FIFOMode_Disable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; 
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_Init(DMA1_Stream0, &DMA_InitStructure); 

DMA_Cmd(DMA1_Stream0, ENABLE); 
while (DMA_GetCmdStatus(DMA1_Stream6) != ENABLE); 

DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_TCIF0 | DMA_FLAG_FEIF0 | DMA_FLAG_DMEIF0 | \ 
     DMA_FLAG_TEIF0 | DMA_FLAG_HTIF0); 


DMA_DeInit(DMA1_Stream6); 

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)I2C_TxBuffer; 
DMA_InitStructure.DMA_BufferSize = 1; 

DMA_Init(DMA1_Stream6, &DMA_InitStructure); 

DMA_Cmd(DMA1_Stream6, ENABLE); 
while (DMA_GetCmdStatus(DMA1_Stream6) != ENABLE); 

DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6 | DMA_FLAG_FEIF6 | DMA_FLAG_DMEIF6 | \ 
     DMA_FLAG_TEIF6 | DMA_FLAG_HTIF6);