新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32的I2C-EEPROM已調試成功

        STM32的I2C-EEPROM已調試成功

        作者: 時間:2016-11-17 來源:網絡 收藏

        萬利的I2C-EEPROM例程有些問題,經本人兩個晝夜的反復試驗,已修改完善。

        本文引用地址:http://www.104case.com/article/201611/315433.htm

        修改了兩個地方,在void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)寫操作函數和void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)讀操作函數體內的開頭先要執行一句I2C_EE_WaitEepromStandbyState();

        這樣在以后調用寫操作函數和讀操作函數時就不用執行I2C_EE_WaitEepromStandbyState()了。但上電復位后先要執行一次讀操作,以后就可以無限制的隨便調用這兩個函數了。

        詳細如下。

        /* Includes ------------------------------------------------------------------*/
        #include "stm32f10x_lib.h"
        #include "i2c_ee.h"
        #include"delay.h"

        /* Private typedef -----------------------------------------------------------*/
        /* Private define ------------------------------------------------------------*/
        #define I2C_Speed 10000
        #define I2C1_SLAVE_ADDRESS7 0xA0

        #define I2C_PageSize 4


        /* Private macro -------------------------------------------------------------*/
        /* Private variables ---------------------------------------------------------*/
        u16 EEPROM_ADDRESS;

        /* Private function prototypes -----------------------------------------------*/

        void I2C_Configuration(void);


        /*******************************************************************************
        * Function Name : I2C_Configuration
        * Description : I2C Configuration
        * Input : None
        * Output : None
        * Return : None
        *******************************************************************************/
        void I2C_Configuration(void)
        {
        GPIO_InitTypeDef GPIO_InitStructure;
        I2C_InitTypeDef I2C_InitStructure;

        /* Configure I2C1 pins: SCL and SDA */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//開漏輸出
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        /* I2C configuration */
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//設置 I2C為 I2C模式
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//I2C快速模式 Tlow / Thigh = 2

        I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;//設置第一個設備地址
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能應答
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//應答 7位地址
        I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//設置時鐘頻率
        /* I2C Peripheral Enable */
        I2C_Cmd(I2C1, ENABLE);//使能I2C外設
        /* Apply I2C configuration after enabling it */
        I2C_Init(I2C1, &I2C_InitStructure);
        }

        /*******************************************************************************
        * Function Name : I2C_EE_Init
        * Description : Initializes peripherals used by the I2C EEPROM driver.
        * Input : None
        * Output : None
        * Return : None
        *******************************************************************************/
        void I2C_EE_Init()
        {
        /* I2C configuration */
        I2C_Configuration();

        /* depending on the EEPROM Address selected in the i2c_ee.h file */
        #ifdef EEPROM_Block0_ADDRESS
        /* Select the EEPROM Block0 to write on */
        EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;
        #endif
        #ifdef EEPROM_Block1_ADDRESS
        /* Select the EEPROM Block1 to write on */
        EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;
        #endif
        #ifdef EEPROM_Block2_ADDRESS
        /* Select the EEPROM Block2 to write on */
        EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;
        #endif
        #ifdef EEPROM_Block3_ADDRESS
        /* Select the EEPROM Block3 to write on */
        EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;
        #endif
        }

        /*******************************************************************************
        * Function Name : I2C_EE_BufferWrite
        * Description : Writes buffer of data to the I2C EEPROM.
        * Input : - pBuffer : pointer to the buffer containing the data to be
        * written to the EEPROM.
        * - WriteAddr : EEPROMs internal address to write to.
        * - NumByteToWrite : number of bytes to write to the EEPROM.
        * Output : None
        * Return : None
        pBuffer:指向要寫入數據數組的指針
        WriteAddr:24c02中要寫入數據的首地址
        NumByteToWrite:寫入的字節數
        *******************************************************************************/
        void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)//將緩沖器的數據寫入EEPROM
        {
        u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

        Addr = WriteAddr % I2C_PageSize;//寫入地址是每頁的第幾位
        count = I2C_PageSize - Addr;//在開始的一頁要寫入的個數
        NumOfPage = NumByteToWrite / I2C_PageSize;//要寫入的頁數
        NumOfSingle = NumByteToWrite % I2C_PageSize;//不足一頁的個數
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        /* If WriteAddr is I2C_PageSize aligned */
        if(Addr == 0) //寫入地址是頁的開始
        {
        /* If NumByteToWrite < I2C_PageSize */
        if(NumOfPage == 0) //數據小于一頁
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//寫少于一頁的數據
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        }
        /* If NumByteToWrite > I2C_PageSize */
        else //數據大于等于一頁
        {
        while(NumOfPage--)//要寫入的頁數
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //寫一頁的數據
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        WriteAddr += I2C_PageSize;
        pBuffer += I2C_PageSize;
        }

        if(NumOfSingle!=0)//剩余數據小于一頁
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//寫少于一頁的數據
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        }
        }
        }
        /* If WriteAddr is not I2C_PageSize aligned */
        else //寫入地址不是頁的開始
        {
        /* If NumByteToWrite < I2C_PageSize */
        if(NumOfPage== 0) //數據小于一頁
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//寫少于一頁的數據
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        }
        /* If NumByteToWrite > I2C_PageSize */
        else//數據大于等于一頁
        {
        NumByteToWrite -= count;
        NumOfPage = NumByteToWrite / I2C_PageSize; //重新計算要寫入的頁數
        NumOfSingle = NumByteToWrite % I2C_PageSize;//重新計算不足一頁的個數

        if(count != 0)//在此處count一定不為0,此判斷條件好象有點多余
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, count);//將開始的空間寫滿一頁
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        WriteAddr += count;
        pBuffer += count;
        }

        while(NumOfPage--)//要寫入的頁數
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);//寫一頁的數據
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        WriteAddr += I2C_PageSize;
        pBuffer += I2C_PageSize;
        }
        if(NumOfSingle != 0)//剩余數據小于一頁
        {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); //寫少于一頁的數據
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        }
        }
        }
        }

        /*******************************************************************************
        * Function Name : I2C_EE_ByteWrite
        * Description : Writes one byte to the I2C EEPROM.
        * Input : - pBuffer : pointer to the buffer containing the data to be
        * written to the EEPROM.
        * - WriteAddr : EEPROMs internal address to write to.
        * Output : None
        * Return : None
        pBuffer:指向要寫入數據數組的指針
        WriteAddr:24c02中要寫入數據的首地址
        *******************************************************************************/
        void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)//寫一個字節到EEPROM
        {
        /* Send STRAT condition */
        I2C_GenerateSTART(I2C1, ENABLE);//產生 I2Cx傳輸 START條件

        /* Test on EV5 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //檢查最近一次 I2C事件是否是輸入的事件

        /* Send EEPROM address for write */
        I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的從 I2C設備傳送地址字,選擇發送方向
        /* Test on EV6 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//檢查最近一次 I2C事件是否是輸入的事件

        /* Send the EEPROMs internal address to write to */
        I2C_SendData(I2C1, WriteAddr);//通過外設 I2Cx發送地址
        /* Test on EV8 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//檢查最近一次 I2C事件是否是輸入的事件

        /* Send the byte to be written */
        I2C_SendData(I2C1, *pBuffer); //通過外設 I2Cx發送數據

        /* Test on EV8 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//檢查最近一次 I2C事件是否是輸入的事件
        /* Send STOP condition */
        I2C_GenerateSTOP(I2C1, ENABLE);//產生 I2Cx傳輸 STOP條件
        }

        /*******************************************************************************
        * Function Name : I2C_EE_PageWrite
        * Description : Writes more than one byte to the EEPROM with a single WRITE
        * cycle. The number of byte cant exceed the EEPROM page size.
        * Input : - pBuffer : pointer to the buffer containing the data to be
        * written to the EEPROM.
        * - WriteAddr : EEPROMs internal address to write to.
        * - NumByteToWrite : number of bytes to write to the EEPROM.
        * Output : None
        * Return : None
        pBuffer:指向要寫入數據數組的指針
        WriteAddr:24c02中要寫入數據的首地址
        NumByteToWrite:寫入的字節數
        *******************************************************************************/
        void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)//寫少于一頁的數據
        {
        /* Send START condition */
        I2C_GenerateSTART(I2C1, ENABLE);//產生 I2Cx傳輸 START條件
        /* Test on EV5 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //檢查最近一次 I2C事件是否是輸入的事件
        /* Send EEPROM address for write */
        I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的從 I2C設備傳送地址字,選擇發送方向

        /* Test on EV6 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //檢查最近一次 I2C事件是否是輸入的事件

        /* Send the EEPROMs internal address to write to */
        I2C_SendData(I2C1, WriteAddr); //通過外設 I2Cx發送地址

        /* Test on EV8 and clear it */
        while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //檢查最近一次 I2C事件是否是輸入的事件

        /* While there is data to be written */
        while(NumByteToWrite--)
        {
        /* Send the current byte */
        I2C_SendData(I2C1, *pBuffer); //通過外設 I2Cx發送數據

        /* Point to the next byte to be written */
        pBuffer++;
        /* Test on EV8 and clear it */
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//檢查最近一次 I2C事件是否是輸入的事件
        }

        /* Send STOP condition */
        I2C_GenerateSTOP(I2C1, ENABLE);//產生 I2Cx傳輸 STOP條件
        }

        /*******************************************************************************
        * Function Name : I2C_EE_BufferRead
        * Description : Reads a block of data from the EEPROM.
        * Input : - pBuffer : pointer to the buffer that receives the data read
        * from the EEPROM.
        * - ReadAddr : EEPROMs internal address to read from.
        * - NumByteToRead : number of bytes to read from the EEPROM.
        * Output : None
        * Return : None
        pBuffer:指向要保存讀出數據的數組的指針
        ReadAddr:24c02中要讀出數據的首地址
        NumByteToRead:讀出的字節數
        *******************************************************************************/
        void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//將EEPROM的數據讀入緩沖器
        {
        I2C_EE_WaitEepromStandbyState();//EEPROM設為待命狀態
        /* Send START condition */
        I2C_GenerateSTART(I2C1, ENABLE);//產生 I2Cx傳輸 START條件
        /* Test on EV5 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//檢查最近一次 I2C事件是否是輸入的事件
        /* In the case of a single data transfer disable ACK before reading the data */
        if(NumByteToRead==1)
        {
        I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的應答功能
        }
        /* Send EEPROM address for write */
        I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的從 I2C設備傳送地址字,選擇發送方向

        /* Test on EV6 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//檢查最近一次 I2C事件是否是輸入的事件
        /* Clear EV6 by setting again the PE bit */
        I2C_Cmd(I2C1, ENABLE);//使能或者失能 I2C外設

        /* Send the EEPROMs internal address to write to */
        I2C_SendData(I2C1, ReadAddr); //通過外設 I2Cx發送地址

        /* Test on EV8 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//檢查最近一次 I2C事件是否是輸入的事件
        /* Send STRAT condition a second time */
        I2C_GenerateSTART(I2C1, ENABLE);//產生 I2Cx傳輸 START條件
        /* Test on EV5 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//檢查最近一次 I2C事件是否是輸入的事件
        /* Send EEPROM address for read */
        I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//向指定的從 I2C設備傳送地址字,選擇接收方向
        /* Test on EV6 and clear it */
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//檢查最近一次 I2C事件是否是輸入的事件
        /* While there is data to be read */
        while(NumByteToRead)
        {
        /* Test on EV7 and clear it */
        if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //檢查最近一次 I2C事件是否是輸入的事件
        {
        if(NumByteToRead == 2)
        {
        /* Disable Acknowledgement */
        I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的應答功能
        }

        if(NumByteToRead == 1)
        {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2C1, ENABLE);//產生 I2Cx傳輸 STOP條件
        }

        /* Read a byte from the EEPROM */
        *pBuffer = I2C_ReceiveData(I2C1);//返回通過 I2Cx最近接收的數據

        /* Point to the next location where the byte read will be saved */
        pBuffer++;

        /* Decrement the read bytes counter */
        NumByteToRead--;
        }
        }

        /* Enable Acknowledgement to be ready for another reception */
        I2C_AcknowledgeConfig(I2C1, ENABLE);//使能或者失能指定 I2C的應答功能
        }

        /*******************************************************************************
        * Function Name : I2C_EE_WaitEepromStandbyState
        * Description : Wait for EEPROM Standby state
        * Input : None
        * Output : None
        * Return : None
        *******************************************************************************/
        void I2C_EE_WaitEepromStandbyState(void) //EEPROM設為待命狀態
        {
        vu16 SR1_Tmp = 0;

        do
        {
        /* Send START condition */
        I2C_GenerateSTART(I2C1, ENABLE);//產生 I2Cx傳輸 START條件
        /* Read I2C1 SR1 register */
        SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);//讀取指定的 I2C寄存器 I2C_SR1 并返回其值
        /* Send EEPROM address for write */
        I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的從 I2C設備傳送地址字 ,選擇發送方向
        }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//地址發送結束
        /* Clear AF flag */
        I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清除 I2Cx的應答錯誤標志位




        關鍵詞: STM32I2CEEPRO

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 宁海县| 大庆市| 集安市| 大埔区| 竹北市| 资兴市| 日喀则市| 霍邱县| 四川省| 赞皇县| 淮南市| 全椒县| 吉林省| 大新县| 隆子县| 通江县| 安阳市| 安远县| 霍林郭勒市| 岳池县| 枝江市| 乌审旗| 礼泉县| 德安县| 新河县| 宜良县| 克东县| 永平县| 呼和浩特市| 玉田县| 诸城市| 甘孜| 颍上县| 九寨沟县| 凤阳县| 新余市| 中方县| 武鸣县| 华宁县| 富平县| 鲁甸县|