精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

I2C驅動學習看這一篇就夠了

嵌入式悅翔園 ? 來源:嵌入式悅翔園 ? 2023-06-16 11:46 ? 次閱讀

一、前言

I2C協議是在開發中使用非常頻繁的一種協議,相信大家在學習單片機的時候經常會用到支持I2C協議的模塊,I2C 總線僅僅使用 SCL、SDA 這兩根信號線就實現了設備之間的數據交互,極大地簡化了對硬件資源和 PCB 板布線空間的占用。因此,I2C 總線被非常廣泛地應用在 EEPROM、實時鐘、小型 LCD 等設備與 CPU接口中。

但是與裸機開發不同的是在 Linux 系統中,I2C 驅動由 3 部分組成,即 I2C 核心、I2C 總線驅動和 I2C 設備驅動。今天就從這三個部分來給大家講解一下Linux中的I2C驅動,以及我們應該如何為我們的開發板添加一個I2C設備。

二、Linux 的 I2C 體系結構

由上面分析可知,Linux驅動分為三部分:I2C 核心、I2C 總線驅動和 I2C 設備驅動

26b6b8b2-0bf8-11ee-962d-dac502259ad0.png

2.1 Linux I2C 核心

I2C 核心提供了 I2C 總線驅動和設備驅動的注冊、注銷方法,這部分主要是一些與硬件無關的的接口函數,這部分的代碼一般不用我們普通開發者進行開發和修改,但是理解這部分的代碼邏輯和接口還是非常必要的。

I2C 核心中的主要函數如下:

注冊/注銷適配器(adapter)
inti2c_add_adapter(structi2c_adapter*adap);
inti2c_del_adapter(structi2c_adapter*adap);

注冊/注銷I2C設備驅動程序
inti2c_register_driver(structmodule*owner,structi2c_driver*driver);
inti2c_del_driver(structi2c_driver*driver);
inlineinti2c_add_driver(structi2c_driver*driver);

創建并注冊一個新的I2C設備
structi2c_client*i2c_new_device(structi2c_adapter*adap,structi2c_board_infoconst*info);

I2C傳輸、發送和接收
inti2c_transfer(structi2c_adapter*adap,structi2c_msg*msgs,intnum);
inti2c_master_send(structi2c_client*client,constchar*buf,intcount);
inti2c_master_recv(structi2c_client*client,char*buf,intcount);

上邊三個函數用于實現與I2C設備之間的數據交換。i2c_transfer函數可以進行復雜的多消息傳輸,而i2c_master_send和i2c_master_recv函數用于單個數據消息的發送和接收。

這些函數提供了對于I2C總線讀寫操作的基本支持,簡化了I2C設備驅動的開發,有了這些接口我們就不用關注I2C協議方面的代碼了,只需要調用該接口即可完成數據的傳輸。

注意: i2c_transfer函數本身不具備驅動適配器物理硬件完成消息交互的能力,它只是尋找到 i2c_adapter 對應的 i2c_algorithm,并使用 i2c_algorithm 的 master_xfer函數真正驅動硬件流程。

2.2 Linux I2C 適配器驅動

通過上面的介紹我們知道了I2C驅動主要分為三個部分,上面我們已經介紹了I2C核心這一部分,現在我們來介紹一下I2C 適配器驅動,我們知道I2C驅動和其他的那些字符設備驅動有所不同,I2C驅動中維持著一套自己的總線。

I2C 適配器驅動是Linux內核中的一個核心模塊,總線層負責管理所有注冊到系統的I2C總線適配器和設備,并提供與設備通信的API函數。它提供了一些基本的操作函數,如啟動總線、停止總線、發送起始信號、發送停止信號等。但是這部分是由Linux內核完成的,并不需要我們開發者進行修改或添加,所以了解即可。

下面我們用一張圖來看一下上面描述的這個過程:

26f4966e-0bf8-11ee-962d-dac502259ad0.png

2.3 Linux I2C 設備驅動

I2C 設備驅動要使用 i2c_driver 和 i2c_client 數據結構并填充其中的成員函數。 i2c_client 一般被包含在設備的私有信息結構體 yyy_data 中,而 i2c_driver 則適合被定義為全局變量并初始化。

看到I2C設備驅動的這兩個結構體大家是不是很熟悉了,I2C設備驅動是針對特定類型的I2C設備編寫的驅動程序。它包含了對具體設備的操作和控制邏輯,通過調用I2C總線核心驅動提供的API函數與設備進行通信。設備驅動的主要任務包括初始化設備、讀寫數據、配置設備參數等。

因為這部分是針對特定類型的I2C設備編寫的驅動程序,所以這部分才是要我們開發人員來完成編寫的,我們如果需要在自己的開發板上添加一個新的I2C模塊,我們就要首先編寫I2C設備驅動這部分,這部分的編寫需要調用上面我們介紹的I2C核心和I2C總線中接口函數來完成模塊的初始化。

關于I2C設備驅動我們這里先做一個了解即可,后面會詳細介紹這部分的內容,也是我們學習I2C驅動的重點內容。

2.4 Linux I2C驅動總結

I2C總線核心驅動(I2C Core Driver):【系統廠編寫】I2C總線核心驅動是Linux內核中的一個核心模塊,負責管理所有注冊到系統的I2C總線適配器和設備,并提供與設備通信的API函數。它提供了一些基本的操作函數,如啟動總線、停止總線、發送起始信號、發送停止信號等。

I2C適配器驅動(I2C Adapter Driver):【芯片廠提供】I2C適配器驅動負責與硬件的I2C控制器進行交互,完成硬件層面的初始化、配置和操作。它將底層硬件的特定接口與I2C總線核心驅動進行連接,使得核心驅動能夠通過適配器驅動來訪問硬件。

I2C設備驅動(I2C Device Driver):【開發者編寫】I2C設備驅動是針對特定類型的I2C設備編寫的驅動程序。它包含了對具體設備的操作和控制邏輯,通過調用I2C總線核心驅動提供的API函數與設備進行通信。設備驅動的主要任務包括初始化設備、讀寫數據、配置設備參數等。

三部分之間的關系如下:

I2C核心層驅動作為頂層驅動,管理整個I2C子系統,并提供了基本的I2C操作接口。

I2C適配器驅動負責與底層硬件的I2C控制器進行交互,通過適配器驅動,I2C總線核心驅動能夠與硬件進行通信。

I2C設備驅動則針對具體的I2C設備編寫,實現了對設備的初始化、讀寫數據等操作。

27044c62-0bf8-11ee-962d-dac502259ad0.png

三、具體設備驅動分析

由于作為開發者我們需要關注并且需要我們親自編寫的部分就只有設備驅動了,所以我們今天就詳細介紹一下設備驅動這部分。

當我們需要編寫具體的I2C設備驅動程序時,我們需要編寫以下內容:**probe函數、remove函數、操作函數以及數據傳輸與處理**,下面將對每部分進行詳細介紹。

3.1 Probe函數

具體設備中的probe函數是I2C設備驅動中最重要的函數之一,用于在I2C設備與驅動匹配成功后進行初始化和注冊設備。在probe函數中,可以執行以下任務:

進行設備的特定初始化操作,例如配置設備寄存器、申請內存資源等。

注冊字符設備、輸入設備或其他設備類別,使系統能夠識別和使用該設備。

存儲設備私有數據,通常使用i2c_set_clientdata函數將私有數據與i2c_client相關聯,方便后續的操作函數訪問。

我們在學習其他設備驅動的時候就知道了probe函數是設備與驅動匹配成功后被調用執行的。它的原型通常如下所示:

staticinti2c_device_probe(structi2c_client*client,conststructi2c_device_id*id);

下面我們就找一個設備驅動來分析一下我們應該如何編寫:

這里以rk3x_i2c_probe為例給大家進行分析:
staticintrk3x_i2c_probe(structplatform_device*pdev)
{
structdevice_node*np=pdev->dev.of_node;
conststructof_device_id*match;
structrk3x_i2c*i2c;
structresource*mem;
intret=0;
intbus_nr;
u32value;
intirq;
unsignedlongclk_rate;

i2c=devm_kzalloc(&pdev->dev,sizeof(structrk3x_i2c),GFP_KERNEL);
if(!i2c)
return-ENOMEM;

match=of_match_node(rk3x_i2c_match,np);
i2c->soc_data=(structrk3x_i2c_soc_data*)match->data;

/*usecommoninterfacetogetI2Ctimingproperties*/
i2c_parse_fw_timings(&pdev->dev,&i2c->t,true);

strlcpy(i2c->adap.name,"rk3x-i2c",sizeof(i2c->adap.name));
i2c->adap.owner=THIS_MODULE;
i2c->adap.algo=&rk3x_i2c_algorithm;
i2c->adap.retries=3;
i2c->adap.dev.of_node=np;
i2c->adap.algo_data=i2c;
i2c->adap.dev.parent=&pdev->dev;

i2c->dev=&pdev->dev;

spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait);

i2c->i2c_restart_nb.notifier_call=rk3x_i2c_restart_notify;
i2c->i2c_restart_nb.priority=128;
ret=register_i2c_restart_handler(&i2c->i2c_restart_nb);
if(ret){
dev_err(&pdev->dev,"failedtosetupi2crestarthandler.
");
returnret;
}

mem=platform_get_resource(pdev,IORESOURCE_MEM,0);
i2c->regs=devm_ioremap_resource(&pdev->dev,mem);
if(IS_ERR(i2c->regs))
returnPTR_ERR(i2c->regs);

/*TrytosettheI2Cadapternumberfromdt*/
bus_nr=of_alias_get_id(np,"i2c");

/*
*SwitchtonewinterfaceiftheSoCalsoofferstheoldone.
*ThecontrolbitislocatedintheGRFregisterspace.
*/
if(i2c->soc_data->grf_offset>=0){
structregmap*grf;

grf=syscon_regmap_lookup_by_phandle(np,"rockchip,grf");
if(IS_ERR(grf)){
dev_err(&pdev->dev,
"rk3x-i2cneeds'rockchip,grf'property
");
returnPTR_ERR(grf);
}

if(bus_nrdev,"rk3x-i2cneedsi2cXalias");
return-EINVAL;
}

/*27+i:writemask,11+i:value*/
value=BIT(27+bus_nr)|BIT(11+bus_nr);

ret=regmap_write(grf,i2c->soc_data->grf_offset,value);
if(ret!=0){
dev_err(i2c->dev,"CouldnotwritetoGRF:%d
",ret);
returnret;
}
}

/*IRQsetup*/
irq=platform_get_irq(pdev,0);
if(irqdev,"cannotfindrk3xIRQ
");
returnirq;
}

ret=devm_request_irq(&pdev->dev,irq,rk3x_i2c_irq,
0,dev_name(&pdev->dev),i2c);
if(retdev,"cannotrequestIRQ
");
returnret;
}

platform_set_drvdata(pdev,i2c);

if(i2c->soc_data->calc_timings==rk3x_i2c_v0_calc_timings){
/*Onlyoneclocktouseforbusclockandperipheralclock*/
i2c->clk=devm_clk_get(&pdev->dev,NULL);
i2c->pclk=i2c->clk;
}else{
i2c->clk=devm_clk_get(&pdev->dev,"i2c");
i2c->pclk=devm_clk_get(&pdev->dev,"pclk");
}

if(IS_ERR(i2c->clk)){
ret=PTR_ERR(i2c->clk);
if(ret!=-EPROBE_DEFER)
dev_err(&pdev->dev,"Can'tgetbusclk:%d
",ret);
returnret;
}
if(IS_ERR(i2c->pclk)){
ret=PTR_ERR(i2c->pclk);
if(ret!=-EPROBE_DEFER)
dev_err(&pdev->dev,"Can'tgetperiphclk:%d
",ret);
returnret;
}

ret=clk_prepare(i2c->clk);
if(retdev,"Can'tpreparebusclk:%d
",ret);
returnret;
}
ret=clk_prepare(i2c->pclk);
if(retdev,"Can'tprepareperiphclock:%d
",ret);
gotoerr_clk;
}

i2c->clk_rate_nb.notifier_call=rk3x_i2c_clk_notifier_cb;
ret=clk_notifier_register(i2c->clk,&i2c->clk_rate_nb);
if(ret!=0){
dev_err(&pdev->dev,"Unabletoregisterclocknotifier
");
gotoerr_pclk;
}

clk_rate=clk_get_rate(i2c->clk);
rk3x_i2c_adapt_div(i2c,clk_rate);

ret=i2c_add_adapter(&i2c->adap);
if(retdev,"Couldnotregisteradapter
");
gotoerr_clk_notifier;
}

dev_info(&pdev->dev,"InitializedRK3xxxI2Cbusat%p
",i2c->regs);

return0;

err_clk_notifier:
clk_notifier_unregister(i2c->clk,&i2c->clk_rate_nb);
err_pclk:
clk_unprepare(i2c->pclk);
err_clk:
clk_unprepare(i2c->clk);
returnret;
}

從上面的代碼我們可以發現rk3x_i2c_probe主要做了以下幾件事情:

1、通過devm_kzalloc函數為rk3x_i2c結構體分配內存空間;
2、從設備樹中獲取I2C設備信息并填充rk3x_i2c結構體;
3、使用devm_platform_ioremap_resource函數來映射設備的寄存器資源到內存中;
4、獲取并配置中斷;
5、使用i2c_add_adapter注冊設備

基本上這個驅動就是一個比較完整的I2C設備初始化流程了,我們如果想要編寫其他設備的驅動可以參考該驅動初始化來進行編寫。

3.2 讀寫函數

由于rk3x_i2c中的讀寫函數和該設備關聯性較大,不具備通用性,這里以sx1_i2c_write_byte和sx1_i2c_read_byte來給大家進行分析,該函數更具有通用性。

/*WritetoI2Cdevice*/
intsx1_i2c_write_byte(u8devaddr,u8regoffset,u8value)
{
structi2c_adapter*adap;
interr;
structi2c_msgmsg[1];
unsignedchardata[2];

adap=i2c_get_adapter(0);
if(!adap)
return-ENODEV;
msg->addr=devaddr;/*I2Caddressofchip*/
msg->flags=0;
msg->len=2;
msg->buf=data;
data[0]=regoffset;/*registernum*/
data[1]=value;/*registerdata*/
err=i2c_transfer(adap,msg,1);
i2c_put_adapter(adap);
if(err>=0)
return0;
returnerr;
}

/*ReadfromI2Cdevice*/
intsx1_i2c_read_byte(u8devaddr,u8regoffset,u8*value)
{
structi2c_adapter*adap;
interr;
structi2c_msgmsg[1];
unsignedchardata[2];

adap=i2c_get_adapter(0);
if(!adap)
return-ENODEV;

msg->addr=devaddr;/*I2Caddressofchip*/
msg->flags=0;
msg->len=1;
msg->buf=data;
data[0]=regoffset;/*registernum*/
err=i2c_transfer(adap,msg,1);

msg->addr=devaddr;/*I2Caddress*/
msg->flags=I2C_M_RD;
msg->len=1;
msg->buf=data;
err=i2c_transfer(adap,msg,1);
*value=data[0];
i2c_put_adapter(adap);

if(err>=0)
return0;
returnerr;
}

從上面的代碼可以看出,sx1_i2c_write_byte主要完成了以下功能:

1、通過調用i2c_get_adapter(0)函數獲取指定索引的I2C適配器對象并賦值給adap變量。
2、初始化一個structi2c_msg類型的數組msg,該數組包含一個元素用于I2C消息的傳輸。
3、設置msg結構體中的字段:
addr:設備的I2C地址。
flags:傳輸標志位,此處為0表示寫操作。
len:要傳輸的字節數,此處設置為2,即寄存器地址和寄存器數據兩個字節。
buf:數據緩沖區的指針,用于存儲要發送的數據。
4、將要寫入的設備寄存器地址和數據分別存儲在data數組的第一個和第二個元素中,即data[0]=regoffset;和data[1]=value;。
5、調用i2c_transfer()函數進行I2C消息傳輸,將數據寫入設備寄存器。
6、使用i2c_put_adapter()函數釋放先前獲取的I2C適配器對象。

sx1_i2c_read_byte主要完成了以下功能:

1、通過調用i2c_get_adapter(0)函數獲取指定索引的I2C適配器對象并賦值給adap變量。
2、初始化一個structi2c_msg類型的數組msg,該數組包含一個元素用于I2C消息的傳輸。
3、設置msg結構體中的字段:
addr:設備的I2C地址。
flags:傳輸標志位,此處為0表示寫操作。
len:要傳輸或接收的字節數。
buf:數據緩沖區的指針,用于存儲要發送或接收的數據。
4、將要讀取的設備寄存器地址存儲在data數組的第一個元素中,即data[0]=regoffset;。
5、調用i2c_transfer()函數進行I2C消息傳輸,將數據寫入設備寄存器。
6、更改flags字段為I2C_M_RD,表示接收模式(讀操作)。
7、再次調用i2c_transfer()函數進行I2C消息傳輸,從設備中讀取數據。
8、將讀取到的數據存儲在data數組的第一個元素中,即*value=data[0];。
9、使用i2c_put_adapter()函數釋放先前獲取的I2C適配器對象。

對比I2C讀和寫的過程大家可能會發現I2C讀的過程為什么調用了兩次i2c_transfer函數呢?多調用了一次i2c_transfer函數是因為我們在調用i2c_transfer讀取數據時,需要先發送要讀取的寄存器地址給設備,然后再從設備讀取實際的數據。所以第一次使用i2c_transfer發送的信息為需要讀取的地址信息,第二次將標志位改為讀,然后使用i2c_transfer將從設備返回的信息存儲到i2c_adapter中。

四、I2C驅動中幾個重要的結構體

在I2C驅動中,有三個比較重要的結構體用于描述和管理I2C設備和傳輸操作。下面就這三個結構體的成員以及作用來給大家講解一下:

4.1 i2c_adapter 結構體

定義位置:i2c.h結構體原型:

structi2c_adapter{
structmodule*owner;
unsignedintclass;/*classestoallowprobingfor*/
conststructi2c_algorithm*algo;/*thealgorithmtoaccessthebus*/
void*algo_data;

/*datafieldsthatarevalidforalldevices*/
conststructi2c_lock_operations*lock_ops;
structrt_mutexbus_lock;
structrt_mutexmux_lock;

inttimeout;/*injiffies*/
intretries;
structdevicedev;/*theadapterdevice*/
unsignedlonglocked_flags;/*ownedbytheI2Ccore*/
#defineI2C_ALF_IS_SUSPENDED0
#defineI2C_ALF_SUSPEND_REPORTED1

intnr;
charname[48];
structcompletiondev_released;

structmutexuserspace_clients_lock;
structlist_headuserspace_clients;

structi2c_bus_recovery_info*bus_recovery_info;
conststructi2c_adapter_quirks*quirks;

structirq_domain*host_notify_domain;
structregulator*bus_regulator;
};

幾個重要的成員:

name:適配器的名稱。
nr:適配器的編號。
bus_lock和bus_unlock:用于保護對適配器的并發訪問的鎖機制。
algo:指向I2C算法結構體的指針,包含了適配器的通信算法,如標準模式、快速模式、高速模式等。

4.2 i2c_client 結構體

定義位置:i2c.h結構體原型:

structi2c_client{
unsignedshortflags;/*div.,seebelow*/
#defineI2C_CLIENT_PEC0x04/*UsePacketErrorChecking*/
#defineI2C_CLIENT_TEN0x10/*wehaveatenbitchipaddress*/
/*MustequalI2C_M_TENbelow*/
#defineI2C_CLIENT_SLAVE0x20/*wearetheslave*/
#defineI2C_CLIENT_HOST_NOTIFY0x40/*WewanttouseI2Chostnotify*/
#defineI2C_CLIENT_WAKE0x80/*forboard_info;trueiffcanwake*/
#defineI2C_CLIENT_SCCB0x9000/*UseOmnivisionSCCBprotocol*/
/*MustmatchI2C_M_STOP|IGNORE_NAK*/

unsignedshortaddr;/*chipaddress-NOTE:7bit*/
/*addressesarestoredinthe*/
/*_LOWER_7bits*/
charname[I2C_NAME_SIZE];
structi2c_adapter*adapter;/*theadapterwesiton*/
structdevicedev;/*thedevicestructure*/
intinit_irq;/*irqsetatinitialization*/
intirq;/*irqissuedbydevice*/
structlist_headdetected;
#ifIS_ENABLED(CONFIG_I2C_SLAVE)
i2c_slave_cb_tslave_cb;/*callbackforslavemode*/
#endif
void*devres_group_id;/*IDofprobedevresgroup*/
};

幾個重要的成員:

flags:標志位,用于指定設備的特性和行為。
addr:設備的I2C地址。
adapter:指向i2c_adapter的指針,表示所屬的I2C適配器。
driver:指向設備驅動程序的指針,表示設備所使用的驅動。

4.3 i2c_driver 結構體

定義位置:i2c.h結構體原型:

structi2c_driver{
unsignedintclass;

union{
/*Standarddrivermodelinterfaces*/
int(*probe)(structi2c_client*client);
/*
*Legacycallbackthatwaspartofaconversionof.probe().
*Todayithasthesamesemanticas.probe().Don'tusefornew
*code.
*/
int(*probe_new)(structi2c_client*client);
};
void(*remove)(structi2c_client*client);


/*drivermodelinterfacesthatdon'trelatetoenumeration*/
void(*shutdown)(structi2c_client*client);

/*Alertcallback,forexamplefortheSMBusalertprotocol.
*Theformatandmeaningofthedatavaluedependsontheprotocol.
*FortheSMBusalertprotocol,thereisasinglebitofdatapassed
*asthealertresponse'slowbit("eventflag").
*FortheSMBusHostNotifyprotocol,thedatacorrespondstothe
*16-bitpayloaddatareportedbytheslavedeviceactingasmaster.
*/
void(*alert)(structi2c_client*client,enumi2c_alert_protocolprotocol,
unsignedintdata);

/*aioctllikecommandthatcanbeusedtoperformspecificfunctions
*withthedevice.
*/
int(*command)(structi2c_client*client,unsignedintcmd,void*arg);

structdevice_driverdriver;
conststructi2c_device_id*id_table;

/*Devicedetectioncallbackforautomaticdevicecreation*/
int(*detect)(structi2c_client*client,structi2c_board_info*info);
constunsignedshort*address_list;
structlist_headclients;

u32flags;
};

幾個重要的成員:

driver:是一個structdevice_driver結構體,用于向Linux設備模型注冊驅動程序。
probe和remove:指向探測和移除設備的函數指針,通過這兩個函數,驅動程序可以在發現匹配的設備時執行初始化操作,并在設備被移除時執行清理操作。
id_table:用于指定驅動程序支持的I2C設備ID列表,以便匹配對應的設備。

這些結構體共同構成了Linux內核中的I2C驅動框架,提供了對I2C總線、適配器和設備的抽象和管理功能。開發者可以基于這些結構體來編寫自己的I2C驅動程序,并實現與I2C設備的通信和控制。所以我們的工作就是填充這些結構體然后調用對應的接口把我們填充好的結構體傳遞給I2C設備器驅動和核心驅動從而完成設備的初始化和讀寫操作。

五、總結

I2C驅動的學習有一個特點:弄懂比較難,會用比較簡單,這是因為有很多的有難度的內容以及和協議相關的內容都已經被Linux或者芯片廠封裝好了,我們需要做的就是使用他們提供的這些接口完成指定設備的讀寫操作,但是我們的學習不能止步于此,所以我們不但要會用,還要知其然知其所以然。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 驅動器
    +關注

    關注

    52

    文章

    8164

    瀏覽量

    146029
  • SDA
    SDA
    +關注

    關注

    0

    文章

    124

    瀏覽量

    28117
  • I2C協議
    +關注

    關注

    0

    文章

    26

    瀏覽量

    8460
  • Linux驅動
    +關注

    關注

    0

    文章

    43

    瀏覽量

    9951

原文標題:Linux驅動:I2C驅動學習看這一篇就夠了

文章出處:【微信號:嵌入式悅翔園,微信公眾號:嵌入式悅翔園】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    GPIO模擬I2C總線的驅動設計與實現

    I2C總線簡單方便,是我們經常使用的種總線。但有時候我們的MCU沒有足夠多的I2C控制器來實現我們的應用,所幸我可以使用普通的GPIO引腳來模擬低速的I2C總線通信。
    發表于 12-14 14:19 ?5335次閱讀
    GPIO模擬<b class='flag-5'>I2C</b>總線的<b class='flag-5'>驅動</b>設計與實現

    I2C總線驅動程序的實現

    I2C總線驅動程序的實現 I2C 驅動程序的簡介本驅動程序為標準的51 系列CPU 編寫,讓CPU 模擬成
    發表于 09-26 17:25 ?5721次閱讀
    <b class='flag-5'>I2C</b>總線<b class='flag-5'>驅動</b>程序的實現

    基于51的I2c總線

    I2c總線,基于51的I2c總線,程序學習。快來下載學習
    發表于 01-13 11:49 ?34次下載

    I2C LCD 器件通過驅動帶有 I2C 接口的 2 線式 16 字符 LCD

    I2C LCD 器件通過驅動帶有 I2C 接口的 2 線式 16 字符 LCD
    發表于 10-10 08:22 ?13次下載
    <b class='flag-5'>I2C</b> LCD 器件通過<b class='flag-5'>驅動</b>帶有 <b class='flag-5'>I2C</b> 接口的 <b class='flag-5'>2</b> 線式 16 字符 LCD

    Linux的I2C驅動架構

    控制器的差異,不考慮其實現細節地與硬件設備通訊。1.1 總線驅動在系統開機時,首先裝載的是I2C總線驅動個總線驅動用于支持
    發表于 04-02 14:38 ?666次閱讀

    I2C通信協議應該如何學習

    我最近剛做完I2C通信協議的編寫與調試,下面介紹下我從開始理解夏老師的程序,修改程序,直到下板調試整個的學習過程,希望對大家學習
    發表于 04-28 08:00 ?21次下載
    <b class='flag-5'>I2C</b>通信協議應該如何<b class='flag-5'>學習</b>

    I2C系列的合集,可以系統學習I2C協議

    這篇文章給大家帶來了I2C系列的合集,可以系統學習I2C協議。大家趕緊看看吧! 1、I2C總線:何時使用I2C緩沖器 本文討論了使用
    的頭像 發表于 09-23 15:28 ?3114次閱讀

    STM32學習I2C協議(讀寫EEPROM)

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

    Linux驅動I2C設備驅動(基于Freescale i.MX6ULL平臺了解I2C驅動框架,順便寫個簡陋的MPU6050驅動

    文章目錄1、簡介2、I2C總線、設備和驅動的結構體定義2.1 結構體定義--I2C總線2.2 結構體定義--I2C設備2.3 結構體定義--
    發表于 12-06 13:51 ?8次下載
    Linux<b class='flag-5'>驅動</b>:<b class='flag-5'>I2C</b>設備<b class='flag-5'>驅動</b>(基于Freescale <b class='flag-5'>i</b>.MX6ULL平臺了解<b class='flag-5'>I2C</b>的<b class='flag-5'>驅動</b>框架,順便寫個簡陋的MPU6050<b class='flag-5'>驅動</b>)

    嵌入式內核及驅動開發-09IIC子系統框架使用(I2C協議和時序,I2C驅動框架,I2C從設備驅動開發,MPU6050硬件連接

    文章目錄I2c協議和時序I2c介紹I2c硬件連接I2c總線的信號I2c總線寫時序I2c總線讀時序
    發表于 12-06 14:06 ?17次下載
    嵌入式內核及<b class='flag-5'>驅動</b>開發-09IIC子系統框架使用(<b class='flag-5'>I2C</b>協議和時序,<b class='flag-5'>I2C</b><b class='flag-5'>驅動</b>框架,<b class='flag-5'>I2C</b>從設備<b class='flag-5'>驅動</b>開發,MPU6050硬件連接

    硬件I2C與模擬I2C

    硬件I2C對應芯片上的I2C外設,有相應I2C驅動電路,其所使用的I2C管腳也是專用的,因而效率要遠高于軟件模擬的
    發表于 12-28 19:14 ?81次下載
    硬件<b class='flag-5'>I2C</b>與模擬<b class='flag-5'>I2C</b>

    ESP32 之 ESP-IDF 教學(六)——I2C數據總線(I2C

    ESP32 之 ESP-IDF 學習筆記(六)【I2C數據總線(I2C)】文章目錄ESP32 之 ESP-IDF 學習筆記(六)【
    發表于 12-28 19:25 ?22次下載
    ESP32 之 ESP-IDF 教學(六)——<b class='flag-5'>I2C</b>數據總線(<b class='flag-5'>I</b>2<b class='flag-5'>C</b>)

    Linux I2C驅動入門知識科普

    I2C 總線驅動, I2C總線驅動就是SOC的 I2C控制器驅動,也叫做
    的頭像 發表于 12-29 13:59 ?1651次閱讀

    I2C控制器驅動介紹

    (控制器)抽象成 i2c_adapter。 對于I2C 適配器,肯定要對外提供讀寫 API 函數,設備驅動程序可以使用這些 API 函數來完成讀寫操作。
    的頭像 發表于 07-22 15:38 ?1418次閱讀
    <b class='flag-5'>I2C</b>控制器<b class='flag-5'>驅動</b>介紹

    I2C子系統SW Architecture

    I2C SW Architecture 【driver 驅動層】由普通驅動工程師負責,【i2c 核心層】由 Linux 提供,【i2c 核心
    的頭像 發表于 07-22 16:01 ?911次閱讀
    <b class='flag-5'>I2C</b>子系統SW Architecture