0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32指針抽象出I2C的數(shù)據(jù)實例

STM32嵌入式開發(fā) ? 來源:STM32嵌入式開發(fā) ? 2023-10-26 15:53 ? 次閱讀

1.寫在前面

I2C總線是由PHILIPS公司開發(fā)的一種簡單、「雙向二線制同步串行總線」。

關(guān)于i2c的使用,并不陌生,STM32、C51、ARMMSP430等,都基本集成硬件i2c,或者不集成i2c的,可以根據(jù)總線時序圖使用普通IO口翻轉(zhuǎn)模擬一根i2c總線。

wKgaomU6G5yAH6zwAABnIAjUCo0855.png

對于流行的STM32飽受詬病的硬件I2C,相信很多人都是使用模擬I2C。

模擬i2c的源碼比較多,大多都是大同小異,對于各類例程,提供的模擬i2c似乎都不是太規(guī)范(個人見解),特別是一根i2c總線掛多個外設(shè)、模擬多根i2c總線、以及更換一個i2c外設(shè)時,都需要大幅度修改源碼、復(fù)制源碼、重新調(diào)試時序等重復(fù)的工作。

在閱讀過Linux設(shè)備驅(qū)動框架和RT-Thread的驅(qū)動框架,發(fā)現(xiàn)在總線分層上處理就特別好,完美解決了上述提及的問題。參考RT-Thread和Linux下的模擬i2c,整理修改在裸機(jī)上使用。

2.Linux、RT-Thread設(shè)備驅(qū)動模型

1)模型分為總線驅(qū)動和設(shè)備驅(qū)動;

2) 總線驅(qū)動與外設(shè)驅(qū)動分離,方便一根總線掛多個外設(shè),方便移植;

3) 底層(與硬件相關(guān))與上層分離,方便添加總線及移植到不同處理器,移植到其他處理器,只需重新實現(xiàn)硬件相關(guān)的“寄存器”層即可;

wKgaomU6G5yAcInpAAAqxaqySFY086.jpg

3.MCU下裸機(jī)形式i2c總線抽象

此部分實現(xiàn)源碼為:i2c_core.c i2c_core.h

1)i2c總線抽象對外接口(API

“i2c_bus_xfer”為i2c封裝對外的API,函數(shù)原型如下,提供一個函數(shù)模型,具體需要實例化函數(shù)指針。


int i2c_bus_xfer(struct i2c_dev_device *dev,struct i2c_dev_message msgs[],unsigned int num)
{
 int size;
 
 size = dev->xfer(dev,msgs,num); 
 return size;
}

a)此函數(shù)即作為驅(qū)動外設(shè)的對外接口,所有操作通過此函數(shù)接口,與底層總線實現(xiàn)分離,如EEPROM、RTC、溫度傳感器等;

b)一個對外函數(shù)已經(jīng)實現(xiàn)90%的情況使用,對應(yīng)一些特殊情況,后期再完善或增加API。

c)struct i2c_dev_device *i2c_dev

2)i2c總線抽象API參數(shù)

a)i2c_dev:i2c設(shè)備指針,類型為“struct i2c_dev_device”,驅(qū)動一個i2c外設(shè)時,首先要對此指針設(shè)備初始化;

b)msgs:i2c一幀數(shù)據(jù),發(fā)送數(shù)據(jù)及存放返回數(shù)據(jù)的緩存;

c)num:數(shù)據(jù)幀數(shù)量。

3)struct i2c_dev_device

該結(jié)構(gòu)體為關(guān)鍵,調(diào)用API驅(qū)動外設(shè)時,首先對此初始化(類似于Linux/RT-Thread注冊設(shè)備)。完整的設(shè)備包括兩部分,數(shù)據(jù)操作函數(shù)和i2c相關(guān)信息(如硬件i2c或者模擬i2c)。因此“struct i2c_dev_device”的原型為:


struct i2c_dev_device
{
    int (*xfer)(struct i2c_dev_device *dev,struct i2c_dev_message msgs[],unsigned int num);
    void *i2c_phy;
};

a)第一個參數(shù)是函數(shù)指針,數(shù)據(jù)收發(fā)通過此函數(shù)指針調(diào)用實體函數(shù)實現(xiàn);

b)第二個參數(shù)是一個void指針,初始化時指向我們使用的物理i2c(硬件/模擬),使用時可強(qiáng)制轉(zhuǎn)換為對應(yīng)的類型。

4)xfer

該函數(shù)與i2c總線設(shè)備對外接口函數(shù)“i2c_bus_xfer”具有相同的參數(shù),形參參數(shù)參考此項的第2點,初始化時實例化指向?qū)嶓w函數(shù)。

5)struct i2c_dev_message

“struct i2c_dev_message”為i2c總線訪問外設(shè)的一幀數(shù)據(jù)信息,包括發(fā)送數(shù)據(jù)、外設(shè)從地址、訪問標(biāo)識等。原型如下:


struct i2c_dev_message
{
 unsigned short  addr;
 unsigned short flags;
 unsigned short size;
 unsigned char *buff;
 unsigned char   retries;  
};
a)addr:i2c外設(shè)從機(jī)地址,常用為7位,10位較少用;
b)flags:標(biāo)識,發(fā)送、接收、應(yīng)答、地址位選擇等標(biāo)識;幾種標(biāo)識如下:

#define I2C_BUS_WR             0x0000
#define I2C_BUS_RD             (1u << 0)
#define I2C_BUS_ADDR_10BIT     (1u << 2)
#define I2C_BUS_NO_START      (1u << 4)
#define I2C_BUS_IGNORE_NACK    (1u << 5)
#define I2C_BUS_NO_READ_ACK    (1u << 6)

c)size:發(fā)送的數(shù)據(jù)大小,或者接收的緩存大?。?/p>

d)buff:緩存區(qū);

e)retries:i2c啟動失敗時,重啟的次數(shù)。

4.模擬i2c抽象

對于模擬i2c,在以往的實現(xiàn)方式中,基本是時序圖和外設(shè)代碼混合在一起,增加外設(shè)或者使用新的i2c外設(shè)時,需要對模擬i2c代碼進(jìn)行較大工作量的修改,或者以“復(fù)制”的方式實現(xiàn)一套新的i2c總線。

但同理,可以把模擬i2c時序部分代碼抽象出來,以“復(fù)用”代碼的形式實現(xiàn)。此部分實現(xiàn)源碼為:i2c_bitops.c i2c_bitops.h

1)模擬i2c抽象對外接口

根據(jù)上述封裝的對外API,使用時,首先需要實現(xiàn)入口參數(shù)“i2c_dev”實例化,用模擬i2c即是調(diào)用模擬i2c相關(guān)接口。


int i2c_bitops_bus_xfer(struct ops_i2c_dev *i2c_bus,struct i2c_dev_message msgs[],unsigned long num)
{
 struct i2c_dev_message *msg;
 unsigned long i;
 unsigned short ignore_nack;
 int ret;
 
 ignore_nack = msg->flags & I2C_BUS_IGNORE_NACK;
 i2c_bitops_start(i2c_bus);       
    for (i = 0; i < num; i++)
    {
        msg = &msgs[i];
        if (!(msg->flags & I2C_BUS_NO_START))
        {
            if (i)
            {
                i2c_bitops_restart(i2c_bus); 
            }
            ret = i2c_bitops_send_address(i2c_bus,msg);
            if ((ret != 0) && !ignore_nack)
                goto out;
        }
        if (msg->flags & I2C_BUS_RD)
        {//read
            ret = i2c_bitops_bus_read(i2c_bus,msg);
            if(ret < msg->size)
            {
                ret = -1;
                goto out;
            }
        }
        else
        {//write
            ret = i2c_bitops_bus_write(i2c_bus,msg);
            if(ret < msg->size)
            {
                ret = -1;
                goto out;
            }
        }
    }
 ret = i;
out:
 i2c_bitops_stop(i2c_bus);
  
 return ret;
}
int ops_i2c_bus_xfer(struct i2c_dev_device *i2c_dev,struct i2c_dev_message msgs[],unsigned int num)
{
 return (i2c_bitops_bus_xfer((struct ops_i2c_dev*)(i2c_dev->i2c_phy),msgs,num));
}

a)模擬一根i2c總線時,對外的操作函數(shù)都通過上訴函數(shù);i2c信息幀相關(guān)參數(shù)由上層調(diào)用傳遞進(jìn)入,此處主要增加“struct ops_i2c_dev”的封裝;

b)該函數(shù)使用到的函,其中入口參數(shù)為“struct ops_i2c_dev”類型的都是模擬i2c相關(guān);

d)模擬i2c封裝實現(xiàn)主要針對“struct ops_i2c_dev”原型的實例化。

2)struct ops_i2c_dev

“struct ops_i2c_dev”原型如下:


struct ops_i2c_dev
{
        void (*set_sda)(int8_t state);
        void (*set_scl)(int8_t state);
        int8_t (*get_sda)(void);
        int8_t (*get_scl)(void);
        void (*delayus)(uint32_t us);
};

a)set_sda:數(shù)據(jù)線輸出;

b)set_scl:時鐘線輸出;

c)get_sda:數(shù)據(jù)線輸入(捕獲);

d)get_scl:時鐘線輸入(捕獲);

e)delayus:延時函數(shù);

要實現(xiàn)一個模擬i2c,只需將上訴函數(shù)指針的實體實現(xiàn)即可,具體看后面描述。

3)模擬i2c時序

以產(chǎn)生i2c起始信號函數(shù)為例子,簡要分析:


static void i2c_bitops_start(struct ops_i2c_dev *i2c_bus)
{
    i2c_bus->set_sda(0);                                          
    i2c_bus->delayus(3);
    i2c_bus->set_scl(0);                                                       
}  
入口參數(shù)為struct ops_i2c_dev * i2c_bus,其實就是i2c_bitops_bus_xfer應(yīng)用層函數(shù)傳入的參數(shù),最終是在此調(diào)用,底層需要實現(xiàn)的就是io模擬的輸入/輸出狀態(tài)函數(shù)。
其他函數(shù),如


static void i2c_bitops_restart(struct ops_i2c_dev *i2c_bus)
static char i2c_bitops_wait_ack(struct ops_i2c_dev *i2c_bus)
staticinti2c_bitops_send_byte(structops_i2c_dev*i2c_bus,unsignedchardata)

等等,入口參數(shù)都是i2c_bus,時序?qū)崿F(xiàn)與常規(guī)裸機(jī)程序設(shè)計是一致的,不同的是函數(shù)指針的分離調(diào)用,具體看附件源碼。

4)標(biāo)識位

在以往的模擬i2c或者硬件i2c中,操作外設(shè)時都有各類情況,如讀和寫方向的切換、連續(xù)操作(不需啟動i2c總線,如寫EEPROM,先寫地址再寫數(shù)據(jù))等。對于這類情況,我們處理辦法是選擇相關(guān)的宏標(biāo)識即可,具體實現(xiàn)由“中間層”實現(xiàn),讓i2c外設(shè)驅(qū)動起來更簡單!以上述對外函數(shù)為例:

a)通過標(biāo)識位判斷是讀還是寫狀態(tài)


if (msg->flags & I2C_BUS_RD)
{//read
    ret = i2c_bitops_bus_read(i2c_bus,msg);
    if(ret < msg->size)
    {
        ret = -1;
        goto out;
    }
}
b)應(yīng)答狀態(tài)標(biāo)識

ignore_nack = msg->flags & I2C_BUS_IGNORE_NACK;

5)讀寫函數(shù)


讀寫函數(shù)最終是通過io口1bit的翻轉(zhuǎn)模擬出時序,從而獲得數(shù)據(jù),這部分與常規(guī)模擬i2c一致,通過函數(shù)指針方式操作。主要實現(xiàn)接口函數(shù):



static unsigned long i2c_bitops_bus_write(struct ops_i2c_dev *i2c_bus,struct i2c_dev_message *msg);
staticunsignedlongi2c_bitops_bus_read(structops_i2c_dev*i2c_bus,structi2c_dev_message*msg);


5.模擬i2c總線實現(xiàn)

此部分實現(xiàn)源碼為:i2c_hw.c i2c_hw.h

以stm32f1為硬件平臺,采用上述模擬i2c封裝,實現(xiàn)一根模擬i2c總線。

1)實現(xiàn)struct ops_i2c_dev函數(shù)實體


除了“delayus”函數(shù)外,其余為io翻轉(zhuǎn),以“set_sda”和“delayus”為例,實現(xiàn)如下:

static void gpio_set_sda(int8_t state)
{
    if (state)
     I2C1_SDA_PORT->BSRR = I2C1_SDA_PIN;
    else
     I2C1_SDA_PORT->BRR = I2C1_SDA_PIN;
}


static void gpio_delayus(uint32_t us)
{
#if 0  
    volatile int32_t i;


    for (; us > 0; us--)
    {
        i = 30;  //mini 17
        while(i--);
    }
#else
        Delayus(us);
#endif
}


a)為例提高速率,上訴代碼采用寄存器方式操作,可以用庫函數(shù)操作io口;

b)延時可以用硬件定時器延時,或者軟件延時,具體根據(jù)cpu時鐘計算;

c)其他源碼看附件中“i2c_hw.c”

2)初始化一根模擬i2c總線


void stm32f1xx_i2c_init(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;          
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
 
 GPIO_InitStructure.GPIO_Pin = I2C1_SDA_PIN | I2C1_SCL_PIN;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;      
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
 GPIO_Init(I2C1_SDA_PORT, &GPIO_InitStructure);               
 I2C1_SDA_PORT->BSRR = I2C1_SDA_PIN;            
 I2C1_SCL_PORT->BSRR = I2C1_SCL_PIN;
 
 //device init
 ops_i2c1_dev.set_sda = gpio_set_sda;
 ops_i2c1_dev.get_sda = gpio_get_sda;
 ops_i2c1_dev.set_scl = gpio_set_scl;
 ops_i2c1_dev.get_scl = gpio_get_scl;
 ops_i2c1_dev.delayus = gpio_delayus;
  
 i2c1_dev.i2c_phy   = &ops_i2c1_dev;
 i2c1_dev.xfer    = ops_i2c_bus_xfer; 
}
a)i2c io初始化;

b)i2c設(shè)備實例化,其中“ops_i2c1_dev”和“i2c1_dev”即是我們定義的總線設(shè)備,后面使用該總線時主要通過“i2c1_dev”實現(xiàn)對底層的調(diào)用。

6.驅(qū)動EEPROM(AT24C16)

此部分實現(xiàn)源碼為:24clxx.c 24clxx.h

上面總線完成后,驅(qū)動一個i2c外設(shè)可以說就是信手拈來的事情了,而且模擬i2c總線抽象出來后,不需在做重復(fù)調(diào)試時序的工作。

假設(shè)初始化的i2c設(shè)備為i2c1_dev。


1)寫EEPROM


寫一個字節(jié),頁寫算法詳細(xì)見源碼附件(24clxx.c):


char ee_24clxx_writebyte(u16 addr,u8 data)
{
     struct i2c_dev_message ee24_msg[1];
     u8 buf[3];
     u8  slave_addr;
     if(EEPROM_MODEL > 16)
     {       
         slave_addr =EE24CLXX_SLAVE_ADDR;
         buf[0] = (addr >>8)& 0xff;   
         buf[1] = addr & 0xff;
         buf[2] = data;
         ee24_msg[0].size  = 3;
     }
     else
     {
         slave_addr = EE24CLXX_SLAVE_ADDR | (addr>>8);
         buf[0] = addr & 0xff;
         buf[1] = data;
         ee24_msg[0].size = 2;
     }
     ee24_msg[0].addr = slave_addr;
     ee24_msg[0].flags = I2C_BUS_WR;
     ee24_msg[0].buff = buf;
     i2c_bus_xfer(&i2c1_dev,ee24_msg,1);
  
     return 0;
}

2)讀EEPROM


voidee_24clxx_readbytes(u16 read_ddr, char* pbuffer, u16 read_size)
{ 
     struct i2c_dev_message ee24_msg[2];
     u8     buf[2];
     u8     slave_addr;
     if(EEPROM_MODEL > 16)
     {
          slave_addr =EE24CLXX_SLAVE_ADDR;
          buf[0] = (read_ddr>>8)& 0xff;
          buf[1] = read_ddr& 0xff;
          ee24_msg[0].size  = 2;
     }
     else
     {
          slave_addr =EE24CLXX_SLAVE_ADDR | (read_ddr>>8);
          buf[0] = read_ddr & 0xff;
          ee24_msg[0].size  = 1;
     }
     ee24_msg[0].buff  = buf;
     ee24_msg[0].addr  = slave_addr;
     ee24_msg[0].flags = I2C_BUS_WR;
     ee24_msg[1].addr  = slave_addr;
     ee24_msg[1].flags = I2C_BUS_RD;
     ee24_msg[1].buff  = (u8*)pbuffer;
     ee24_msg[1].size  = read_size;
     i2c_bus_xfer(&i2c1_dev,ee24_msg,2);
}


3)注意事項

驅(qū)動一個外設(shè)相對容易了,注意的事項就是標(biāo)識位部分。

a)此處外設(shè)地址(addr),是實際地址,不含讀寫位(7bit),比如AT24C16外設(shè)地址為0x50,可能大家平常用的是0xA0,因為包括讀寫位;

b)寫數(shù)據(jù)時,如果以2幀i2c_dev_message消息發(fā)送,需要注意“I2C_BUS_NO_START”宏,此宏標(biāo)識意思是不需要再次啟動i2c了,一般看i2c外設(shè)手冊時序圖可知道。如寫EEPROM是先寫地址,然后寫數(shù)據(jù)這個過程是連續(xù)的,此時就需用到“I2C_BUS_NO_START”標(biāo)識。程序可改成這樣:


char ee_24clxx_writebyte(u16 addr,u8 data)
{
     struct i2c_dev_message ee24_msg[2];
     u8     buf[2];
     u8 slave_addr;
     if(EEPROM_MODEL > 16)
     {                                   
          slave_addr =EE24CLXX_SLAVE_ADDR;
          buf[0] = (addr>>8)& 0xff;  
          buf[1] = addr &0xff;
          ee24_msg[0].size  = 2;
     }
     else
     {
           slave_addr =EE24CLXX_SLAVE_ADDR | (addr>>8);
           buf[0] = addr &0xff;
           ee24_msg[0].size  = 1;
     }
     ee24_msg[0].addr = slave_addr;
     ee24_msg[0].flags = I2C_BUS_WR;
     ee24_msg[0].buff  = buf;
     ee24_msg[1].addr = slave_addr;
     ee24_msg[1].flags = I2C_BUS_WR |I2C_BUS_NO_START;
     ee24_msg[1].buff  = &data;
     ee24_msg[1].size  = 1;
     i2c_bus_xfer(&i2c1_dev,ee24_msg,2);
          
     return 0;
}


4)其他

理解之后,或者使用過Linux、RT-Thread的驅(qū)動框架的,再驅(qū)動其他i2c外設(shè),就是很容易的事情了,剩下的就是配置寄存器、應(yīng)用算法的問題了。

7.總結(jié)

1)整體思路比較易理解,本質(zhì)就是函數(shù)指針,將與硬件底層無關(guān)的部分抽象出來,相關(guān)聯(lián)的地方分層明確,通過函數(shù)指針的方式進(jìn)行調(diào)用。

2)事務(wù)分離,通用、重復(fù)的事情交給總線處理,特殊任務(wù)留給外設(shè)驅(qū)動。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    16667

    瀏覽量

    347780
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207912
  • STM32
    +關(guān)注

    關(guān)注

    2258

    文章

    10828

    瀏覽量

    352482
  • I2C
    I2C
    +關(guān)注

    關(guān)注

    28

    文章

    1452

    瀏覽量

    122250
  • 串行總線
    +關(guān)注

    關(guān)注

    1

    文章

    176

    瀏覽量

    30551

原文標(biāo)題:STM32指針抽象出I2C的數(shù)據(jù)實例,附代碼

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM32硬件I2C例程

    STM32硬件I2C例程,感興趣的小伙伴們可以看看。
    發(fā)表于 07-26 10:26 ?92次下載

    《振南電子STM32視頻教程》第八講:I2C總線

    [第8講] I2C總線(96分鐘),由何強(qiáng)主講.本課主要講解:(1).I2C總線中的概念講解;(2).I2C總線應(yīng)用實例;(3).
    發(fā)表于 10-09 15:57 ?1077次閱讀

    STM32F2—通信接口I2C

    STM32F2—通信接口I2C
    發(fā)表于 09-03 11:24 ?31次下載
    <b class='flag-5'>STM32F2</b>—通信接口<b class='flag-5'>I2C</b>

    I2C總線原理及應(yīng)用實例

    I2C總線原理及應(yīng)用實例
    發(fā)表于 09-22 11:41 ?17次下載
    <b class='flag-5'>I2C</b>總線原理及應(yīng)用<b class='flag-5'>實例</b>

    STM32 I2C硬件的結(jié)構(gòu)

    我們可以看見STM32的硬件I2C有兩個和數(shù)據(jù)有關(guān)的寄存器“數(shù)據(jù)寄存器(Data register)”(DR)和“數(shù)據(jù)移位寄存器(Data
    的頭像 發(fā)表于 04-30 15:00 ?7043次閱讀
    <b class='flag-5'>STM32</b> <b class='flag-5'>I2C</b>硬件的結(jié)構(gòu)

    一文知道32位指針內(nèi)部區(qū)域?qū)ぶ?/a>

    32位指針用于I、Q、M、L數(shù)據(jù)塊等存儲器中的位、字節(jié)、字、雙字的尋址,32指針尋址,指針需要使用一個雙字的存儲器空間進(jìn)行存儲。
    的頭像 發(fā)表于 11-20 17:33 ?3652次閱讀

    i2c總線用來做什么_i2c總線數(shù)據(jù)傳輸過程

    I2C總線控制器為微控制器或微處理器提供控制I2C總線的接口,它控制所有I2C總線的特殊序列、協(xié)議、仲裁、時序,這里MPC8250提供的I2C
    發(fā)表于 11-24 14:16 ?7093次閱讀

    STM32學(xué)習(xí)之I2C協(xié)議(讀寫EEPROM)

    關(guān)于STM32學(xué)習(xí)分享第七章 I2C協(xié)議(讀寫EEPROM)文章目錄關(guān)于STM32學(xué)習(xí)分享前言二、代碼1.i2c.c2.i2c.h3.main.c總結(jié)前言開始!開始!單片機(jī)的
    發(fā)表于 11-30 15:21 ?32次下載
    <b class='flag-5'>STM32</b>學(xué)習(xí)之<b class='flag-5'>I2C</b>協(xié)議(讀寫EEPROM)

    STM32的硬件I2C有BUG嗎?

    坊間一直流傳著一個傳說~STM32的硬件I2C設(shè)計有BUG,最好不要用,用軟件I2C比較靠譜。長久以來,為了不必要的麻煩,我也一直沒有用過硬件I2C,主要是軟件
    發(fā)表于 12-04 14:51 ?13次下載
    <b class='flag-5'>STM32</b>的硬件<b class='flag-5'>I2C</b>有BUG嗎?

    I2C接口配置ES7243錄音芯片,MCU(STM32)收不到I2C ACK的問題

    I2C接口配置ES7243錄音芯片,MCU(STM32)收不到I2C ACK的問題
    發(fā)表于 12-08 16:36 ?10次下載
    <b class='flag-5'>I2C</b>接口配置ES7243錄音芯片,MCU(<b class='flag-5'>STM32</b>)收不到<b class='flag-5'>I2C</b> ACK的問題

    STM32F103硬件I2C Slave

    MCU:STM32F103IDE:STM32CubeIDEHAL庫硬件I2C當(dāng)作Slave,模擬EEPROM行為測試工具:樹莓派為I2C主機(jī),使用I
    發(fā)表于 12-20 19:38 ?50次下載
    <b class='flag-5'>STM32</b>F103硬件<b class='flag-5'>I2C</b> Slave

    STM32 I2C存取實驗資料

    STM32 I2C存取實驗資料
    發(fā)表于 12-30 10:36 ?16次下載

    硬件I2C與模擬I2C

    硬件I2C對應(yīng)芯片上的I2C外設(shè),有相應(yīng)I2C驅(qū)動電路,其所使用的I2C管腳也是專用的,因而效率要遠(yuǎn)高于軟件模擬的I2C;一般也較為穩(wěn)定,但
    發(fā)表于 12-28 19:14 ?81次下載
    硬件<b class='flag-5'>I2C</b>與模擬<b class='flag-5'>I2C</b>

    STM32F 單片機(jī)硬件I2C Busy標(biāo)志導(dǎo)致的I2C卡死的處理辦法

    STM32F 單片機(jī)硬件I2C Busy標(biāo)志導(dǎo)致的I2C卡死的處理辦法在調(diào)試多用戶表的時候,發(fā)現(xiàn)如果人為短接I2C的SDA或SLK腳后,I2C
    發(fā)表于 12-28 19:24 ?24次下載
    <b class='flag-5'>STM32</b>F 單片機(jī)硬件<b class='flag-5'>I2C</b> Busy標(biāo)志導(dǎo)致的<b class='flag-5'>I2C</b>卡死的處理辦法

    I2C子系統(tǒng)SW Architecture

    適配器(控制器)驅(qū)動,這里用到兩個重要的數(shù)據(jù)結(jié)構(gòu):i2c_adapter 和 i2c_algorithm。其中,Linux 內(nèi)核將 SOC 的 I2C 適配器(控制器)
    的頭像 發(fā)表于 07-22 16:01 ?796次閱讀
    <b class='flag-5'>I2C</b>子系統(tǒng)SW Architecture