首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >STM32F401C -发现板:带有DMA的I2C

STM32F401C -发现板:带有DMA的I2C
EN

Stack Overflow用户
提问于 2016-02-22 11:27:16
回答 2查看 1K关注 0票数 0

如何使用I2C从LSM303DLHC(磁强计)读取数据,并通过DMA将数据存储在内存中的缓冲区中?

我尝试修改"LSM303DLHC_Read()“函数以将其与DMA一起使用,但是SerialChart上的输出始终是0。

你能给我举一个I2C与DMA的例子吗?

代码语言:javascript
运行
复制
   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配置:

代码语言:javascript
运行
复制
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配置:

代码语言:javascript
运行
复制
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);
}
EN

回答 2

Stack Overflow用户

发布于 2016-03-07 21:33:39

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

票数 0
EN

Stack Overflow用户

发布于 2016-04-27 15:30:30

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

代码语言:javascript
运行
复制
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);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35552424

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档