1. 程式人生 > >EFM32 硬體I2C操作

EFM32 硬體I2C操作

有關的例程,請參考如下:

#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操作

有關的例程,請參考如下: #include "efm32.h" #include "em_chip.h" #include "em_cmu.h" #include "em_emu.h" #include "em_gpio.h" #include "em_i2c.h" #in

STM32硬體I2C除錯

除錯情況1 現象:主I2C傳送資料而沒有收到應答,則下一次不能正常傳送資料 背景:主I2C每次應該都能正常傳送資料 硬體:野火STM32-MINI,1主0從,SCL和SDA直接上拉 軟體:按鍵觸發中斷,主I2C傳送一次資料,中斷優先順序,按鍵最低,I2C最高,且主I2C中有TIMEOUT計時

STM32微控制器硬體I2C驅動程式(查詢方式)

本文章原始地址:http://feotech.com/?p=69 本程式主要用於驅動STM32微控制器晶片的硬體I2C暫存器,實現通過使用晶片自帶的I2C暫存器進行資料的傳送與接收. 本例程中採用I2C暫存器查詢的方式來實現資料傳輸,當I2C對應暫存器指定狀態時方可執行下一步操作.

STM32微控制器硬體I2C驅動程式(軟體輪詢方式)---摘自:FeoTech

感謝原作者:FeoTech   原文網址:http://feotech.com/?p=69 本程式主要用於驅動STM32微控制器晶片的硬體I2C暫存器,實現通過使用晶片自帶的I2C暫存器進行資料的傳送與接收. 本例程中採用I2C暫存器查詢的方式來實現資料傳輸,當I2C對應

STM32CubeMX學習筆記——STM32H743_硬體I2C

STM32CubeMX學習筆記——STM32H743_硬體I2C Github STM32CubeMX配置 Pinout配置 GPIO Clock Configuration配置 程式碼部分 main.

C#對window 硬體操作,ManagementObjectSearcher

用ManagementObjectSearcher 竟然不能解析到標頭檔案,需要手動 Add Referance.. 在解決方案--引用--右鍵--新增引用---程式集---框架---勾選System.Management   前言:  我們在很多情況下想要獲得

STM32F1 硬體I2C驅動DAC(LTC2605)

#include "i2c_drive_mcp.h" #define I2C_Speed     100000 #define Master_Address 0x0A  //全部通道 static void I2C_GPIO_Config(void) { &

STM32CubeMX學習教程之十:硬體I2C讀寫AT24C02

完整原始碼下載:https://github.com/simonliu009/STM32CubeMX-hardware-I2C-AT24C02網上有流傳已久一種說法,就是STM的I2C有bug,不好用。確實很多人在實際應用中都遇到了各種問題,所以絕大部分人都是在用軟體模擬II

硬體I2C(TWI)讀寫PCF8563和24CXX程式

//ICC-AVR application builder : 2010-3-5 13:51:50 // Target : M88 // Crystal: 8.0000Mhz #include <iom88v.h> #include <macro

EFM32-筆記-IO操作

 GPIO->P[4].DOUT共有16位,因此需要使用一個0xFFFF來表示 2.向GPIO_Px_DOUTSET的對應位上寫1,就可以將該位設定為高電平。 3.向GPIO_Px_DOUTCLR的對應位上寫1,就可以將該位設定為低電平。 4.向GPIO_Px_DOUTTGL的對應位上寫1,就可以將該位

STM32硬體IIC操作 (轉)

轉自:http://blog.csdn.net/dengrengong/article/details/39831577  Stm32具有IIC介面,介面有以下主要特性 多主機功能:該模組既可做主裝置也可做從裝置 主裝置功能 C地址檢測 產生和檢測7位/10位地

STM32 硬體I2C 到底是不是個坑?

/** ****************************************************************************** * @author    Maoxiao Hu * @version   V1.0.0 * @date       May-2015

GPIO模擬I2C操作除錯注意事項

I2C作為板級序列資料匯流排,其規格相對簡單,但除錯過程中的一些細節問題容易被忽視,產生意想不到的時序錯誤。寫這邊文章為了記錄我在除錯I2C過程中遇到的問題,以便今後查閱並作為經驗與大家分享。 關於I2C匯流排的規格可以參考I2C的規格書,描述準確詳細,此不贅述。 使用M

基於 STM32 的硬體 I2C 讀取 MPU6050 資料

MPU6050其實就是一個 I2C 器件,裡面有很多暫存器(但是我們用到的只有幾個),我們通過讀寫暫存器來操作這個晶片。所以首要問題就是 STM32 和 MPU6050 的 I2C 通訊。1、配置 STM32 (用I2C1:PB6——SCL;PB7——SDA)      

STM32F10x_硬體I2C讀寫EEPROM(標準外設庫版本)

Ⅰ、寫在前面 上一篇文章是“STM32F10x_模擬I2C讀寫EEPROM”,講述使用IO口模擬I2C匯流排通訊,對EEPROM(AT24Xxx)進行讀寫操作的過程。 上一篇文章主要內容:I2C協議、模擬I2C底層驅動、EEPROM(AT24Xxx)單位元組讀寫操作。 本文

STM32 硬體IIC操作

就三個函式  簡單明瞭   初始化  讀   寫  int main(void){  u8 i;  SystemInit();  Iic1_Init();  LED_GPIO_Config();  I2C1_WriteByte(0xA0,1,0x89);  //寫EEPRO

STM32F103使用硬體i2c作為從機模式

一、簡單說明 本例子參考了ST官方歷程,官方歷程的連結如下 關於i2c的協議這裡就不做描述了 關於STM32 i2c的模式可以在中文資料手冊中檢視 手冊中已經描述,該模組預設工作在從模式,要想變為主模式,主要生產一個起始條件。(主模式的程式碼可以參考野火開發板的硬體i2

stm32硬體I2C測試例程,親測可用

        對於stm32的硬體I2C確實有不盡人意的地方。但是還是可以實現的,畢竟使用stm32的硬體I2C確實比使用IO口來模擬簡單的多。下面的程式程式碼是使用stm32F03ZET6的I2C1(PB6,PB7)和AT24C02的EEPROM來測試的。希望對於需要的朋

STM32F10x_硬體I2C主從通訊(輪詢傳送,中斷接收)

Ⅰ、寫在前面 關注我分享文章的朋友應該知道我在前面講述過(軟體、硬體)I2C主機控制從機EEPROM的例子。在I2C通訊主機控制程式是比較常見的一種,可以說在實際專案中,很多應用都會使用到I2C通訊。但在實際專案中作為I2C從機的應用相對要少的多,本文主要講述關於【STM3

STM32中FSMC與硬體I2C衝突

ST官網勘誤表中列到,FSMC與I2C不能同時開啟。解決的辦法可以有 1:將I2C對映到PB9,PB8. 2:使用模擬的I2C. I/O重對映步驟:(以串列埠為例) 1.開啟重對映時鐘和USART重對映後的I/O口引腳時鐘,  RCC_APB2PeriphClockCmd(