EFM32 硬體I2C操作

來源:互聯網
上載者:User

標籤:

有關的常式,請參考如下:

#include "efm32.h"#include "em_chip.h"#include "em_cmu.h"#include "em_emu.h"#include "em_gpio.h"#include "em_i2c.h"#include "I2C_hw.h"unsigned long i2c_error = 0;void I2C_WaitForAck(void);void I2C_Buslock_Process(void);void I2C_IO_Initial(void){    i2c_error = 0;        /* Enabling clock to the I2C, GPIO*/    CMU_ClockEnable(cmuClock_GPIO, true);    CMU_ClockEnable(cmuClock_I2C0, true);        /* Using PC6 (SDA) and PC7 (SCL) */    GPIO_PinModeSet(gpioPortD, 6, gpioModeWiredAndPullUpFilter, 1);    GPIO_PinModeSet(gpioPortD, 7, gpioModeWiredAndPullUpFilter, 1);          /* Enable pins at location 2 */    I2C0->ROUTE = (I2C_ROUTE_SDAPEN |I2C_ROUTE_SCLPEN |I2C_ROUTE_LOCATION_LOC1);        I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX | I2C_CMD_ABORT;        I2C0->CTRL &= ~_I2C_CTRL_MASK;    /* Set the CLHR (clock low to high ratio). */    I2C0->CTRL |= i2cClockHLRStandard <<_I2C_CTRL_CLHR_SHIFT;    // Set SCK clock low timeout and bus idle timeout    I2C0->CTRL |= I2C_CTRL_CLTO_1024PPC | I2C_CTRL_GIBITO | I2C_CTRL_BITO_160PCC;    // Set auto STOP when NACK    I2C0->CTRL |= I2C_CTRL_AUTOSN;        /* Frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4), thus */    /* DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1 */    //Assume system clock = 1000000, i2c clock = 30kHz;    //div = (1000000 - (4 * 30000)) / (8 * 30000) = 3.67 = 4;    //CLKDIV = div - 1;    I2C0->CLKDIV = 16;        NVIC_ClearPendingIRQ(I2C0_IRQn);    I2C0->IFC = _I2C_IFC_MASK;        //I2C0->IEN = I2C_IEN_ARBLOST | I2C_IEN_CLTO | I2C_IEN_BITO | I2C_IEN_NACK | I2C_IEN_BUSERR;    //NVIC_EnableIRQ(I2C0_IRQn);        BITBAND_Peripheral(&(I2C0->CTRL),_I2C_CTRL_EN_SHIFT,true);}unsigned char I2C_SentData(unsigned char Address, unsigned short Offset, unsigned char Data){    //Perpare for a new transmit    I2C0->CMD = I2C_CMD_ABORT;    I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;        //Clear all the flags    I2C0->IFC = _I2C_IFC_MASK;        //Begin to transmit    I2C0->CMD = I2C_CMD_START;                   //Start    I2C0->TXDATA = Address | I2C_WRITE_COMMAND;  //I2C hardware address    I2C_WaitForAck();                                    I2C0->TXDATA  = Offset;                      //I2C internal address    I2C_WaitForAck();        I2C0->TXDATA = Data;                         //I2C data     I2C_WaitForAck();        I2C0->CMD = I2C_CMD_STOP;                    //Stop        unsigned char Result = i2c_error;    i2c_error = 0;    return Result;}unsigned char I2C_ReadData(unsigned char Address, unsigned short Offset, unsigned char *Rx){    //Perpare for a new transmit    I2C0->CMD = I2C_CMD_ABORT;    I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;      //Clear all the flags    I2C0->IFC = _I2C_IFC_MASK;        //Begin to transmit    I2C0->CMD = I2C_CMD_START;                   //S    I2C0->TXDATA = Address | I2C_WRITE_COMMAND;  //AD+W hardware address    I2C_WaitForAck();        I2C0->TXDATA  = Offset;                      //internal register address    I2C_WaitForAck();        I2C0->CMD = I2C_CMD_START;                   //S    I2C0->TXDATA = Address | I2C_READ_COMMAND;   //AD+R internal register address    I2C_WaitForAck();        while(!((I2C0->IF) & I2C_IF_RXDATAV));    *Rx = (unsigned char)(I2C0->RXDATA);    I2C0->CMD = I2C_CMD_NACK;                     //NACK    I2C0->CMD = I2C_CMD_STOP;                     //P        unsigned char Result = i2c_error;    i2c_error = 0;     return Result;}void I2C_WaitForAck(void){    while(!((I2C0->IF) & I2C_IF_ACK))    {        //STOP auto send        if(i2c_error)        {            break;        }    }    I2C0->IFC = _I2C_IFC_MASK;}void I2C0_IRQHandler(void){    static unsigned char Arblost = 0;    unsigned long Flag = I2C0->IF;    if(Flag & I2C_IF_NACK)    {        //auto STOP send        i2c_error = 1;    }    if(Flag & I2C_IF_BUSERR)    {        I2C0->CMD = I2C_CMD_ABORT;        I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;        i2c_error = 1;    }        if(Flag & I2C_IF_ARBLOST)    {        //arbitration losses, maybe SDA is stuck        if(Arblost++ > 5)        {            Arblost = 0;            I2C_Buslock_Process();        }        i2c_error = 1;    }    if((Flag & I2C_IF_CLTO) || (Flag & I2C_IF_BITO))    {        I2C_Buslock_Process();        i2c_error = 1;    }        I2C0->IFC = Flag;}void I2C_Buslock_Process(void){    unsigned long Delay = 1000;        //Disable I2C module, and clearing the route register    BITBAND_Peripheral(&(I2C0->CTRL),_I2C_CTRL_EN_SHIFT,false);    I2C0->ROUTE = 0;    //Set as pushpull mode    GPIO_PinModeSet(gpioPortD, 6, gpioModePushPull, 1);//SDA    GPIO_PinModeSet(gpioPortD, 7, gpioModePushPull, 1);//SCL        //send 9 clock of SCL    for(unsigned char i = 0; i < 9; i++)    {        Delay = 3000;        GPIO_PinOutClear(gpioPortD, 7);        while(Delay--);        Delay = 3000;        GPIO_PinOutSet(gpioPortD, 7);        while(Delay--);    }        /* Using PD6 (SDA) and PD7 (SCL) */    GPIO_PinModeSet(gpioPortD, 7, gpioModeWiredAndPullUpFilter, 1);    GPIO_PinModeSet(gpioPortD, 6, gpioModeWiredAndPullUpFilter, 1);          /* Enable pins at location 2 */    I2C0->ROUTE = (I2C_ROUTE_SDAPEN |I2C_ROUTE_SCLPEN |I2C_ROUTE_LOCATION_LOC1);    //enable again    BITBAND_Peripheral(&(I2C0->CTRL),_I2C_CTRL_EN_SHIFT,true);   }

在以上代碼中,並沒有使能硬體I2C的中斷,因此也不會調用I2C_Buslock_Process()函數。另外,針對該函數,目前也還沒有做過功能驗證,我只能通過短接SCL和SDA來測試。

I2C_Buslock_Process()原意是當I2C匯流排死結的時候,控制I2C中的SCL時鐘線產生9個時鐘脈衝(針對8位元據的情況),這樣I2C從裝置就可以完成被掛起的讀操作,從死結狀態中恢複過來。

在主函數中的調用方式如下:

I2C_SentData(SLAVE_ADDRESS, PWR_MGMT_1,   0x00);
I2C_ReadData(Address, RegAddress+1, &L);



EFM32 硬體I2C操作

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.