xld0932 发表于 2024-3-14 17:34

【国民技术车规MCU N32A455开发板】05、通过硬件I2C熟悉板载EEPROM的操作和应用

<div class='showpostmsg'><p><strong>1.概述</strong></p>

<p>国民技术N32A455系列MCU搭载了多达4个独立的I2C总线接口,它提供多主机功能,控制所有I2C总线特定的时序、协议、仲裁和定时。支持多种通信速率模式(最高支持1MHz),支持DMA操作,同时与SMBus 2.0兼容。 I2C模块有多种用途,包括CRC码的生成和校验、 SMBus(系统管理总线&mdash;System Management Bus)和PMBus(电源管理总线&mdash;PowerManagement Bus)。<br />
&nbsp;</p>

<p><strong>2.N32A455开发板EEPROM原理图</strong></p>

<p>开发板选用EEROM芯片(CAT24C08YI-GT3),分别连接到硬件I2C1的PB8和PB9这两个引脚上,EEPROM的A0~A2地址选择引脚都连接了GND,如下所示:</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

<p><strong>3.I2C示例程序</strong></p>

<p>通过I2C模块与外部EEPRON的通信,对EEPROM进行读取操作,熟悉I2C的编程和应用方法:</p>

<pre>
<code class="language-cpp">int main(void)
{
    uint16_t i = 0;

    log_init();
    log_info("this is a I2C EEPROM demo\r\n");
    /* Initialize the I2C EEPROM driver ----------------------------------------*/
    I2C_EE_Init();

    /* Fill the buffer to send */
    for (i = 0; i &lt; TEST_EEPROM_SIZE; i++)
    {
      tx_buf = i;
    }
    log_info("\r\nWrite to I2C EEPROM...");
    /* First write in the memory followed by a read of the written data --------*/
    /* Write to I2C EEPROM from TEST_EEPROM_ADDR */
    I2C_EE_WriteBuffer(tx_buf, TEST_EEPROM_ADDR, TEST_EEPROM_SIZE);

    log_info("\r\nRead from I2C EEPROM :");
    /* Read from I2C EEPROM from sEE_READ_ADDRESS1 */
    I2C_EE_ReadBuffer(rx_buf, TEST_EEPROM_ADDR, TEST_EEPROM_SIZE);

    for (i = 0; i &lt; TEST_EEPROM_SIZE; i++)
    {
      if ((i % 16) == 0)
      {
            printf("\r\n");
      }

      printf("0x%02X ", rx_buf);
    }

    printf("\r\n");

    /* Check if the data written to the memory is read correctly */
    test_status = Buffercmp(tx_buf, rx_buf, TEST_EEPROM_SIZE);

    if (test_status == PASSED)
    {
      log_info("\r\nthe write and read data are the same,I2C EEPROM test pass\r\n");
    }
    else
    {
      log_info("\r\nthe write and read data are different,I2C EEPROM test fail\r\n");
    }

    while (1)
    {
    }
}</code></pre>

<p>&nbsp;</p>

<p>EEPROM写PAGE操作:</p>

<p>写PAGE操作实现了查访和DMA两种方式,操作流程都相同,都是先产生START信号、发送器件地址、发送写入地址、写入数据、最后发送STOP停止位;每一个步骤都对应一个事件检测,判断是否操作完成:</p>

<pre>
<code class="language-cpp">void I2C_EE_PageWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
#if PROCESS_MODE == 0 /* polling */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send START condition */
    I2C_GenerateStart(I2Cx, ENABLE);
    /** Test on EV5 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send EEPROM address for write */
    I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send the EEPROM's internal address to write to */
    I2C_SendData(I2Cx, WriteAddr);
    /** Test on EV8 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** While there is data to be written */
    while (NumByteToWrite--)
    {
      /** Send the current byte */
      I2C_SendData(I2Cx, *pBuffer);
      /** Point to the next byte to be written */
      pBuffer++;
      /** Test on EV8 and clear it */
      sEETimeout = sEE_LONG_TIMEOUT;
      while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED))
      {
            if ((sEETimeout--) == 0)
                sEE_TIMEOUT_UserCallback();
      }
    }
    /** Send STOP condition */
    I2C_GenerateStop(I2Cx, ENABLE);
    I2C_EE_WaitEepromStandbyState();
    I2C_EE_WriteOnePageCompleted();

#elif PROCESS_MODE == 1 /* interrupt */
    /** initialize static parameter */
    MasterDirection = Transmitter;
    i2c_comm_state= COMM_PRE;
    /** initialize static parameter according to input parameter */
    SlaveADDR    = EEPROM_ADDRESS; /// this byte shoule be send by F/W (in loop or INTSTS way)
    DeviceOffset = WriteAddr;      /// this byte can be send by both F/W and DMA
    OffsetDone   = FALSE;
    memcpy(SendBuf, pBuffer, NumByteToWrite);
    BufCount         = 0;
    Int_NumByteToWrite = NumByteToWrite;
    I2C_ConfigAck(I2C1, ENABLE);
    I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, ENABLE);

    /** Send START condition */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    I2C_GenerateStart(I2C1, ENABLE);
    I2C_EE_WaitOperationIsCompleted();
    I2C_EE_WriteOnePageCompleted();

#elif PROCESS_MODE == 2 /* DMA */
    DMA_InitType DMA_InitStructure;
    /** DMA initialization */
    DMA_DeInit(DMA1_CH6);
    DMA_InitStructure.PeriphAddr   = (u32)&amp;I2Cx-&gt;DAT;            /// (u32)I2C1_DR_Address;
    DMA_InitStructure.MemAddr      = (u32)pBuffer;            /// from function input parameter
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;   /// fixed for send function
    DMA_InitStructure.BufSize      = NumByteToWrite;            /// from function input parameter
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE; // fixed
    DMA_InitStructure.DMA_MemoryInc= DMA_MEM_INC_ENABLE;      /// fixed
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;/// fixed
    DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_Byte;/// fixed
    DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;         /// fixed
    DMA_InitStructure.Priority       = DMA_PRIORITY_VERY_HIGH;   /// up to user
    DMA_InitStructure.Mem2Mem      = DMA_M2M_DISABLE;      /// fixed
    DMA_Init(DMA1_CH6, &amp;DMA_InitStructure);

    sEETimeout   = sEE_LONG_TIMEOUT;
    while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send START condition */
    I2C_GenerateStart(I2Cx, ENABLE);
    /** Test on EV5 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send EEPROM address for write */
    I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send the EEPROM's internal address to write to */
    I2C_SendData(I2Cx, WriteAddr);
    /** Test on EV8 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDING))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
   
    DMA_EnableChannel(DMA1_CH6, ENABLE);
    I2C_EnableDMA(I2C1, ENABLE);
    sEETimeout = sEE_LONG_TIMEOUT;
    while(I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send STOP condition */
    I2C_GenerateStop(I2Cx, ENABLE);
    I2C_EnableDMA(I2Cx, DISABLE);
    DMA_EnableChannel(DMA1_CH6, DISABLE);
    I2C_EE_WaitEepromStandbyState();
    I2C_EE_WriteOnePageCompleted();
#endif
}</code></pre>

<p>&nbsp;</p>

<p>EEPROM读取数据:</p>

<p>EEPROM数据读取的函数,依然使用了查询和DMA两种实现方式,EEPROM的读取大小没有写入PAGE字节数的限制了;具体的操作流程:产生START信号、发送器件地址、发送读取地址、产生RESTART信号、发送读取命令、读取数据:</p>

<pre>
<code class="language-cpp">void I2C_EE_ReadBuffer(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead)
{
#if PROCESS_MODE == 0 /* polling */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    I2C_ConfigNackLocation(I2Cx, I2C_NACK_POS_CURRENT);// clear ACKPOS
    I2C_ConfigAck(I2Cx, ENABLE);
    /** Send START condition */
    I2C_GenerateStart(I2Cx, ENABLE);

    /** Test on EV5 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send EEPROM address for write */
    I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Clear EV6 by setting again the PE bit */
    I2C_Enable(I2Cx, ENABLE);
    /** Send the EEPROM's internal address to write to */
    I2C_SendData(I2Cx, ReadAddr);
    /** Test on EV8 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send STRAT condition a second time */
    I2C_GenerateStart(I2Cx, ENABLE);
    /** Test on EV5 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send EEPROM address for read */
    I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_RECV);
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_GetFlag(I2Cx, I2C_FLAG_ADDRF))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }

    /** While there is data to be read */
    if (NumByteToRead == 1)
    {
      /** Disable Acknowledgement */
      I2C_ConfigAck(I2Cx, DISABLE);
      (void)(I2Cx-&gt;STS1); /// clear ADDR
      (void)(I2Cx-&gt;STS2);
      I2C_GenerateStop(I2Cx, ENABLE);
    }
    else if (NumByteToRead == 2)
    {
      I2C_ConfigNackLocation(I2Cx, I2C_NACK_POS_NEXT);// set ACKPOS
      (void)(I2Cx-&gt;STS1);
      (void)(I2Cx-&gt;STS2);
      I2C_ConfigAck(I2Cx, DISABLE);
    }
    else
    {
      I2C_ConfigAck(I2Cx, ENABLE);
      (void)(I2Cx-&gt;STS1);
      (void)(I2Cx-&gt;STS2);
    }
    while (NumByteToRead)
    {
      if (NumByteToRead &lt;= 3)
      {
            /** One byte */
            if (NumByteToRead == 1)
            {
                /** Wait until RXNE flag is set */
                sEETimeout = sEE_LONG_TIMEOUT;
                while (!I2C_GetFlag(I2Cx, I2C_FLAG_RXDATNE))
                {
                  if ((sEETimeout--) == 0)
                        sEE_TIMEOUT_UserCallback();
                }
                /** Read data from DAT */
                /** Read a byte from the EEPROM */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;
            }
            /** Two bytes */
            else if (NumByteToRead == 2)
            {
                /** Wait until BTF flag is set */
                sEETimeout = sEE_LONG_TIMEOUT;
                while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
                {
                  if ((sEETimeout--) == 0)
                        sEE_TIMEOUT_UserCallback();
                }
                /** Send STOP Condition */
                I2C_GenerateStop(I2Cx, ENABLE);

                /** Read data from DAT */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;
                /** Read data from DAT */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;
            }
            /** 3 Last bytes */
            else
            {
                sEETimeout = sEE_LONG_TIMEOUT;
                while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
                {
                  if ((sEETimeout--) == 0)
                        sEE_TIMEOUT_UserCallback();
                }
                /** Disable Acknowledgement */
                I2C_ConfigAck(I2Cx, DISABLE);
                /** Read data from DAT */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;

                /** Wait until BTF flag is set */
                sEETimeout = sEE_LONG_TIMEOUT;
                while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
                {
                  if ((sEETimeout--) == 0)
                        sEE_TIMEOUT_UserCallback();
                }
                /** Send STOP Condition */
                I2C_GenerateStop(I2Cx, ENABLE);

                /** Read data from DAT */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;

                /** Read data from DAT */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;
            }
      }
      else
      {
            /** Test on EV7 and clear it */
            sEETimeout = sEE_LONG_TIMEOUT;
            while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_RECVD_FLAG))
            {
                if ((sEETimeout--) == 0)
                  sEE_TIMEOUT_UserCallback();
            }
            /** Read a byte from the EEPROM */
            *pBuffer = I2C_RecvData(I2Cx);
            /** Point to the next location where the byte read will be saved */
            pBuffer++;
            /** Decrement the read bytes counter */
            NumByteToRead--;
            if (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
            {
                /** Read a byte from the EEPROM */
                *pBuffer = I2C_RecvData(I2Cx);
                /** Point to the next location where the byte read will be saved */
                pBuffer++;
                /** Decrement the read bytes counter */
                NumByteToRead--;
            }
      }
    }

#elif PROCESS_MODE == 1 /* interrupt */
    I2C_pBuffer   = pBuffer;
    MasterDirection = Receiver;

    /** initialize static parameter according to input parameter*/
    SlaveADDR      = EEPROM_ADDRESS;
    DeviceOffset   = ReadAddr;
    OffsetDone   = FALSE;
    i2c_comm_state = COMM_PRE;
    I2C_ConfigNackLocation(I2Cx, I2C_NACK_POS_CURRENT);// clear ACKPOS
    I2C_ConfigAck(I2C1, ENABLE);
    I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, ENABLE);
    Int_NumByteToRead = NumByteToRead;

    sEETimeout = sEE_LONG_TIMEOUT;
    while (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    I2C_GenerateStart(I2C1, ENABLE);
    I2C_EE_WaitOperationIsCompleted();

#elif PROCESS_MODE == 2 /* DMA */
    /** DMA initialization */
    if(NumByteToRead &gt; 1)
    {
      DMA_InitType DMA_InitStructure;
      /** DMA initialization */
      DMA_DeInit(DMA1_CH7);
      DMA_InitStructure.PeriphAddr   = (u32)&amp;I2Cx-&gt;DAT;            /// (u32)I2C1_DR_Address;
      DMA_InitStructure.MemAddr      = (u32)pBuffer;               /// from function input parameter
      DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;         /// fixed for read function
      DMA_InitStructure.BufSize      = NumByteToRead;            /// from function input parameter
      DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;   /// fixed
      DMA_InitStructure.DMA_MemoryInc= DMA_MEM_INC_ENABLE;         /// fixed
      DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;/// fixed
      DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_Byte;    /// fixed
      DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;            /// fixed
      DMA_InitStructure.Priority       = DMA_PRIORITY_VERY_HIGH;   /// up to user
      DMA_InitStructure.Mem2Mem      = DMA_M2M_DISABLE;            /// fixed
      DMA_Init(DMA1_CH7, &amp;DMA_InitStructure);
    }
    while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY))
    {
      if ((sEETimeout--) == 0)
      {
            sEE_TIMEOUT_UserCallback();
      }
    }
    /** Send START condition */
    I2C_GenerateStart(I2Cx, ENABLE);
    /** Test on EV5 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send EEPROM address for write */
    I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Clear EV6 by setting again the PE bit */
    I2C_Enable(I2Cx, ENABLE);
    /** Send the EEPROM's internal address to write to */
    I2C_SendData(I2Cx, ReadAddr);
    /** Test on EV8 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send STRAT condition a second time */
    I2C_GenerateStart(I2Cx, ENABLE);
    /** Test on EV5 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG))
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** Send EEPROM address for read */
    I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_RECV);
    /* Test on EV6 and clear it */
    sEETimeout = sEE_LONG_TIMEOUT;
    while (!I2C_GetFlag(I2Cx, I2C_FLAG_ADDRF))    //EV6
    {
      if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
    }
    /** While there is data to be read */
    if (NumByteToRead == 1)
    {
      /** Disable Acknowledgement */
      I2C_ConfigAck(I2Cx, DISABLE);
      (void)(I2Cx-&gt;STS1); /// clear ADDR
      (void)(I2Cx-&gt;STS2);
      I2C_GenerateStop(I2Cx, ENABLE);
      /** Wait until RXNE flag is set */
      sEETimeout = sEE_LONG_TIMEOUT;
      while (!I2C_GetFlag(I2Cx, I2C_FLAG_RXDATNE))
      {
            if ((sEETimeout--) == 0)
                sEE_TIMEOUT_UserCallback();
      }
      /** Read data from DAT */
      /** Read a byte from the EEPROM */
      *pBuffer = I2C_RecvData(I2Cx);
    }
    else
    {
      I2C_ConfigAck(I2Cx, ENABLE);
      (void)(I2Cx-&gt;STS1);
      (void)(I2Cx-&gt;STS2);
      I2C_EnableDmaLastSend(I2Cx, ENABLE);
      DMA_EnableChannel(DMA1_CH7, ENABLE);
      I2C_EnableDMA(I2Cx, ENABLE);
      sEETimeout = sEE_LONG_TIMEOUT;
      while(!(DMA_GetFlagStatus(DMA1_FLAG_TC7,DMA1)))
      {
          if ((sEETimeout--) == 0)
            sEE_TIMEOUT_UserCallback();
      }
      I2C_EnableDMA(I2Cx, DISABLE);
      DMA_EnableChannel(DMA1_CH7, DISABLE);
      I2C_EnableDmaLastSend(I2Cx, DISABLE);
      I2C_GenerateStop(I2Cx, ENABLE);
    }
    I2C_EE_WaitOperationIsCompleted();
#endif
}</code></pre>

<p>&nbsp;</p>

<p><strong>4.运行结果</strong></p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

<p><strong>5.工程源码</strong></p>

<div></div>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

Jacktang 发表于 2024-3-15 07:25

<p>国民技术N32A455系列MCU还是很强悍的</p>

xld0932 发表于 2024-3-15 12:39

Jacktang 发表于 2024-3-15 07:25
国民技术N32A455系列MCU还是很强悍的

<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan88.gif" width="59" /></p>

lugl4313820 发表于 2024-3-16 06:59

<p>DMA的方式比普通的读取在快好多倍呀?</p>

xld0932 发表于 2024-3-16 20:45

lugl4313820 发表于 2024-3-16 06:59
DMA的方式比普通的读取在快好多倍呀?

<p>读写的速度是一样的呀,只是DMA可以释放MCU资源去做其它事情&hellip;&hellip;</p>

天若有情天亦老 发表于 2024-7-15 15:53

<p>为什么没有用到中断来发送接收</p>
页: [1]
查看完整版本: 【国民技术车规MCU N32A455开发板】05、通过硬件I2C熟悉板载EEPROM的操作和应用