新聞中心

        STM32 的I2C 硬使用

        作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
        /*

        操作對象為一24C02
        */

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

        #include "STM32Lib\stm32f10x.h"
        #include "hal.h"

        //#define AT24C01A//24C01A,I2C時序和往后的24C02一樣
        #define AT24C01//24C01,I2C的時序和普通的有點不同

        #define EEPROM_ADDR0xA0
        #define I2C_PAGESIZE4//24C01/01A頁緩沖是4個


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

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

        /* PB6,7 SCL and SDA */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        I2C_DeInit(I2C1);
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_OwnAddress1 = 0x30;
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_ClockSpeed = 100000;//100K速度

        I2C_Cmd(I2C1, ENABLE);
        I2C_Init(I2C1, &I2C_InitStructure);
        /*允許1字節(jié)1應(yīng)答模式*/
        I2C_AcknowledgeConfig(I2C1, ENABLE);

        }

        /***************************************************
        **函數(shù)名:I2C_ReadS
        **功能:讀取24C02多個字節(jié)
        **注意事項:24C02是256字節(jié),8位地址,A0-A2固定為0,從器件地址為EEPROM_ADDR
        ***************************************************/
        void I2C_ReadS_24C(u8 addr ,u8* pBuffer,u16 no)
        {
        if(no==0)
        return;

        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

        /*允許1字節(jié)1應(yīng)答模式*/
        I2C_AcknowledgeConfig(I2C1, ENABLE);


        /* 發(fā)送起始位 */
        I2C_GenerateSTART(I2C1, ENABLE);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

        #ifdef AT24C01A
        /*發(fā)送器件地址(寫)*/
        I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        /*發(fā)送地址*/
        I2C_SendData(I2C1, addr);
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));/*數(shù)據(jù)已發(fā)送*/

        /*起始位*/
        I2C_GenerateSTART(I2C1, ENABLE);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

        /*器件讀*/
        I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Receiver);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));


        #else
        /*發(fā)送器件地址(讀)24C01*/
        I2C_Send7bitAddress(I2C1, addr<<1, I2C_Direction_Receiver);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
        #endif

        while (no)
        {
        if(no==1)
        {
        I2C_AcknowledgeConfig(I2C1, DISABLE);//最后一位后要關(guān)閉應(yīng)答的
        I2C_GenerateSTOP(I2C1, ENABLE);//發(fā)送停止位
        }

        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */
        *pBuffer = I2C_ReceiveData(I2C1);
        pBuffer++;
        /* Decrement the read bytes counter */
        no--;
        }
        //再次允許應(yīng)答模式
        I2C_AcknowledgeConfig(I2C1, ENABLE);
        }

        /****************************************************
        **函數(shù)名:I2C_Standby_24C
        **功能:24C是否準(zhǔn)備好再寫入的判斷
        **注意事項:本函數(shù)可以理解為:判忙
        就是不停發(fā)地址 直到器件有應(yīng)答
        ****************************************************/
        void I2C_Standby_24C(void)
        {
        vu16 SR1_Tmp;
        do
        {
        /*起始位*/
        I2C_GenerateSTART(I2C1, ENABLE);
        /*讀SR1*/
        SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);
        /*器件地址(寫)*/
        #ifdef AT24C01A
        I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
        #else
        I2C_Send7bitAddress(I2C1, 0, I2C_Direction_Transmitter);
        #endif
        }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));

        /*清除應(yīng)答錯誤標(biāo)志*/
        I2C_ClearFlag(I2C1, I2C_FLAG_AF);
        /*停止位*/
        I2C_GenerateSTOP(I2C1, ENABLE);
        }

        /*************************************************
        **函數(shù)名:I2C_ByteWrite_24C
        **功能:寫一個字節(jié)
        **注意事項:字寫入同樣需要調(diào)用忙判斷
        *************************************************/
        void I2C_ByteWrite_24C(u8 addr,u8 dat)
        {
        /* 起始位 */
        I2C_GenerateSTART(I2C1, ENABLE);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

        #ifdef AT24C01A
        /* 發(fā)送器件地址(寫)*/
        I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        /*發(fā)送地址*/
        I2C_SendData(I2C1, addr);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        #else
        I2C_Send7bitAddress(I2C1, addr<<1, I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
        #endif

        /* 寫一個字節(jié)*/
        I2C_SendData(I2C1, dat);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        /* 停止位*/
        I2C_GenerateSTOP(I2C1, ENABLE);

        I2C_Standby_24C();
        }

        /*************************************************
        **函數(shù)名:I2C_PageWrite_24C
        **功能:寫入一頁(以內(nèi))
        **注意事項:此函數(shù)供群寫入調(diào)用
        *************************************************/
        void I2C_PageWrite_24C(u8 addr,u8* pBuffer, u8 no)
        {
        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

        /*起始位*/
        I2C_GenerateSTART(I2C1, ENABLE);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

        #ifdef AT24C01A
        /*器件地址(寫)*/
        I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        /*寫地址值*/
        I2C_SendData(I2C1, addr);
        while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        #else
        I2C_Send7bitAddress(I2C1, addr<<1, I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
        #endif
        while(no--)
        {
        I2C_SendData(I2C1, *pBuffer);
        pBuffer++;
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
        }

        /*停止位*/
        I2C_GenerateSTOP(I2C1, ENABLE);
        }

        /*************************************************
        **函數(shù)名:I2C_WriteS_24C
        **功能:頁寫入24C
        **注意事項:24C02最多允許一次寫入8個字節(jié)
        *************************************************/
        void I2C_WriteS_24C(u8 addr,u8* pBuffer, u16 no)
        {
        u8 temp;

        //1.先把頁不對齊的部分寫入
        temp=addr % I2C_PAGESIZE;
        if(temp)
        {
        temp=I2C_PAGESIZE-temp;
        I2C_PageWrite_24C(addr,pBuffer, temp);
        no-=temp;
        addr+=temp;
        pBuffer+=temp;
        I2C_Standby_24C();
        }
        //2.從頁對齊開始寫
        while(no)
        {
        if(no>=I2C_PAGESIZE)
        {
        I2C_PageWrite_24C(addr,pBuffer, I2C_PAGESIZE);
        no-=I2C_PAGESIZE;
        addr+=I2C_PAGESIZE;
        pBuffer+=I2C_PAGESIZE;
        I2C_Standby_24C();
        }
        else
        {
        I2C_PageWrite_24C(addr,pBuffer, no);
        no=0;
        I2C_Standby_24C();
        }
        }
        }


        //測試用
        void I2C_Test(void)
        {
        u8 i;
        u8 I2c_Buf[128];

        I2C_Standby_24C();

        //填充緩沖
        for(i=0;i<128;i++)
        I2c_Buf[i]=i;

        //寫
        I2C_WriteS_24C(1,I2c_Buf,120);

        //清緩沖
        for(i=0;i<128;i++)
        I2c_Buf[i]=0;

        //讀
        I2C_ReadS_24C(1,I2c_Buf,80);

        for(i=1;i<120;i++)
        {
        if(I2c_Buf[i]!=i)
        {
        while(1);
        }
        }

        }

        就看這里 確定是否正常~!

        其實 都是 while 這種 硬等待 導(dǎo)致屢次調(diào)不通 務(wù)必加入 超時判斷。

        簡單的像

        i=0;

        while((!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))&&i<12000);i++



        關(guān)鍵詞: STM32I2C硬使

        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 锡林浩特市| 新和县| 驻马店市| 台中县| 三原县| 浦北县| 昆山市| 威海市| 天全县| 印江| 昌图县| 连城县| 洛阳市| 应城市| 九龙县| 苍梧县| 宜君县| 衡南县| 武夷山市| 襄汾县| 乳源| 巨野县| 当阳市| 安新县| 温泉县| 漯河市| 白山市| 定西市| 禹州市| 化隆| 莱阳市| 开远市| 黄大仙区| 丹寨县| 土默特右旗| 洪泽县| 台前县| 南溪县| 弥渡县| 黔南| 康乐县|