日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux下的I2c 和展锐8310下的I2c

發(fā)布時間:2024/3/26 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux下的I2c 和展锐8310下的I2c 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

I2C物理層

它是一個支持設(shè)備的總線。“總線”指多個設(shè)備共用的信號線。在一個I2C通訊總線中,可連接多個I2C通訊設(shè)備,支持多個通訊主機及多個通訊從機。

·一個I2C總線只使用兩條總線線路,一條雙向串行數(shù)據(jù)線(SDA),一條串行時鐘線(SCL)。數(shù)據(jù)線即用來表示數(shù)據(jù),時鐘線用于數(shù)據(jù)收發(fā)同步。

·每個連接到總線的設(shè)備都有一個獨立的地址,主機可以利用這個地址進行不同設(shè)備之間的訪問。

·總線通過上拉電阻接到電源。當I2C設(shè)備空閑時,會輸出高阻態(tài),而當所有設(shè)備都空閑,都輸出高阻態(tài)時,由上拉電阻把總線拉成高電平。

·多個主機同時使用總線時,為了防止數(shù)據(jù)沖突,會利用仲裁方式?jīng)Q定由哪個設(shè)備占用總線。

·具有三種傳輸模式:標準模式傳輸速率為100kbit/s,快速模式為400kbit/s,高速模下可達3.4Mbit/s,但目前大多I2C設(shè)備尚不支持高速模式。

I2C協(xié)議層

以主機向從機寫數(shù)據(jù)為例,其基本結(jié)構(gòu)如圖所示,依次為:
起始信號——從機地址——讀寫信號——數(shù)據(jù)位——應答位——… … ——停止位

?

起始信號(S):當 SCL 線是高電平時,SDA 線從高電平向低電平切換;停止信號(P):當 SCL 是高電平時,SDA 線由低電平向高電平切換。

?

?

應答信號

I2C最大的一個特點就是有完善的應答機制,從機接收到主機的數(shù)據(jù)時,會回復一個應答信號來通知主機表示“我收到了”。

應答信號出現(xiàn)在1個字節(jié)傳輸完成之后,即第9個SCL時鐘周期內(nèi),此時主機需要釋放SDA總線,把總線控制權(quán)交給從機,由于上拉電阻的作用,此時總線為高電平,如果從機正確的收到了主機發(fā)來的數(shù)據(jù),會把SDA拉低,表示應答響應。

非應答信號

當?shù)?個SCL時鐘周期時,SDA保持高電平,表示非應答信號。

幀地址:I2C總線上的每個設(shè)備都有自己的獨立地址,主機發(fā)起通訊時,通過SDA信號線發(fā)送設(shè)備地址(SLAVE_ADDRESS)來查找從機。I2C協(xié)議規(guī)定設(shè)備地址可以是7位或10位,實際中7位的地址應用比較廣泛。

I2C使用SDA信號線來傳輸數(shù)據(jù),使用SCL信號線進行數(shù)據(jù)同步。SDA數(shù)據(jù)線在SCL的每個時鐘周期傳輸一位數(shù)據(jù)。傳輸時,SCL為高電平的時候SDA表示的數(shù)據(jù)有效,即此時的SDA為高電平時表示數(shù)據(jù)“1”,為低電平時表示數(shù)據(jù)“0”。當SCL為低電平時,SDA的數(shù)據(jù)無效,一般在這個時候SDA進行電平切換,為下一次表示數(shù)據(jù)做好準備。

I2C的數(shù)據(jù)和地址傳輸都帶響應。響應包括“應答(ACK)”和“非應答(NACK)”兩種信號。

作為數(shù)據(jù)接收端時,當設(shè)備(無論主從機)接收到I2C傳輸?shù)囊粋€字節(jié)數(shù)據(jù)或地址后,若希望對方繼續(xù)發(fā)送數(shù)據(jù),則需要向?qū)Ψ桨l(fā)送“應答(ACK)”信號,發(fā)送方會繼續(xù)發(fā)送下一個數(shù)據(jù);若接收端希望結(jié)束數(shù)據(jù)傳輸,則向?qū)Ψ桨l(fā)送“非應答(NACK)”信號,發(fā)送方接收到該信號后會產(chǎn)生一個停止信號,結(jié)束信號傳輸。

?

?Linux代碼

int linux_common_i2c_write(struct i2c_client *client, uint8_t *reg_addr, uint8_t *txbuf, int count) {int ret = -1;int ii = 0;uint8_t buf[MAX_XFER_SIZE + 1] = {0};struct i2c_msg msg[1];if(count > HX9031A_MAX_XFER_SIZE) {count = HX9031A_MAX_XFER_SIZE;PRINT_ERR("block write over size!!!\n");}buf[0] = *reg_addr;memcpy(buf + 1, txbuf, count);msg[0].addr = client->addr; //要寫的寄存器地址和數(shù)據(jù)msg[0].flags = 0;//write //讀寫操作,讀為1 寫為0msg[0].len = count + 1; // 要讀的字節(jié)數(shù)msg[0].buf = buf; //數(shù)據(jù)存放的地址ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));if (ARRAY_SIZE(msg) != ret) {PRINT_ERR("linux_common_i2c_write failed. ret=%d\n", ret);ret = -1;for(ii = 0; ii < msg[0].len; ii++) {PRINT_ERR("msg[0].addr=0x%04X, msg[0].flags=0x%04X, msg[0].len=0x%04X, msg[0].buf[%02d]=0x%02X\n",msg[0].addr,msg[0].flags,msg[0].len,ii,msg[0].buf[ii]);}} else {ret = 0;}return ret; }lin linux_common_i2c_read(struct i2c_client *client, uint8_t *reg_addr, uint8_t *rxbuf, int count) {int ret = -1;int ii = 0;struct i2c_msg msg[2];if(count > MAX_XFER_SIZE) {count = MAX_XFER_SIZE;PRINT_ERR("block read over size!!!\n");}//先寫需要讀的寄存器地址msg[0].addr = client->addr; //要讀的寄存器地址msg[0].flags = 0;//write //讀寫操作,讀為1 寫為0msg[0].len = 1;msg[0].buf = reg_addr;//再讀數(shù)據(jù)msg[1].addr = client->addr;msg[1].flags = I2C_M_RD;//readmsg[1].len = count;msg[1].buf = rxbuf;ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));if (ARRAY_SIZE(msg) != ret) {PRINT_ERR("linux_common_i2c_read failed. ret=%d\n", ret);ret = -1;PRINT_ERR("msg[0].addr=0x%04X, msg[0].flags=0x%04X, msg[0].len=0x%04X, msg[0].buf[0]=0x%02X\n",msg[0].addr,msg[0].flags,msg[0].len,msg[0].buf[0]);if(msg[1].len >= 1) {for(ii = 0; ii < msg[1].len; ii++) {PRINT_ERR("msg[1].addr=0x%04X, msg[1].flags=0x%04X, msg[1].len=0x%04X, msg[1].buf[%02d]=0x%02X\n",msg[1].addr,msg[1].flags,msg[1].len,ii,msg[1].buf[ii]);}}} else {ret = 0;}return ret; }

8310代碼

struct i2c_msg {uint16 addr;/* slave address */uint16 flags;#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */#define I2C_M_RD 0x0001 /* read data, from slave to master */#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */uint16 len; /* msg length */uint8 *buf; /* pointer to msg data */ }; struct SPRD_I2C sprd_i2c[I2C_DEVICE_MAX] = {{/*i2c0*/CTL_I2C0_BASE,400000,0,12,1,TB_I2C0_INT,REG_AP_CLK_CORE_CGM_I2C0_CFG,I2C_26M,REG_AP_APB_APB_EB,BIT_AP_APB_I2C0_EB,REG_AP_APB_APB_RST,BIT_AP_APB_I2C0_SOFT_RST,1,DMA_I2C0_TX,DMA_I2C0_RX,},{/*i2c1*/CTL_I2C1_BASE,100000,1,12,1,TB_I2C1_INT,REG_AP_CLK_CORE_CGM_I2C1_CFG,I2C_26M,REG_AP_APB_APB_EB,BIT_AP_APB_I2C1_EB,REG_AP_APB_APB_RST,BIT_AP_APB_I2C1_SOFT_RST,0, //DMA使能位打開可能會影響讀的正確性DMA_I2C1_TX,DMA_I2C1_RX,},{/*i2c2*/CTL_I2C2_BASE,400000,1,12,1,TB_I2C2_INT,REG_AP_CLK_CORE_CGM_I2C2_CFG,I2C_26M,REG_AP_APB_APB_EB,BIT_AP_APB_I2C2_EB,REG_AP_APB_APB_RST,BIT_AP_APB_I2C2_SOFT_RST,1,DMA_I2C2_TX,DMA_I2C2_RX,},}; int i2c_write(uint8_t addr, uint8_t *txbuf, int count) {int ret = -1, transfer = -1, config_msg = -1, close = -1;uint8_t buf[32 + 1] = {0};buf[0] = addr;memcpy(buf + 1, txbuf, count);struct i2c_client MEIG_IIC;MEIG_IIC.index = 1;struct i2c_msg msgs[2];ret = I2C_Open(&MEIG_IIC);if(ret == -1){return -1;}MG_LOGD( "mg_i2c_write ret =%d", ret );msgs[0].buf = buf; //寄存器地址加要寫的數(shù)據(jù)msgs[0].len = count + 1 ;msgs[0].flags = 0; //讀寫為似乎不起作用msgs[0].addr = 0x50; //寄存器地址左移一位,最后一位為讀寫位 寄存器地址為0x28 即00101000 左移一位最后一位為讀寫位 即01010000transfer = i2c_transfer((uint32)MEIG_IIC.i2c, msgs, 1);MG_LOGD( "mg_i2c_write transfer =%d", transfer );close = I2C_Close((uint32)(&MEIG_IIC));if(close == -1){return -1;}MG_LOGD( "mg_i2c_write close =%d", close );return 0; };int i2c_read(uint8_t addr, uint8_t *rxbuf, int count) {int ret = -1, transfer = -1, config_msg = -1, close = -1;struct i2c_client MEIG_IIC;MEIG_IIC.index = 1; //i2c設(shè)備struct i2c_msg msgs[2];ret = I2C_Open(&MEIG_IIC);if(ret == -1){return -1;}MG_LOGD( "mg_i2c_read ret =%d", ret );msgs[0].buf = &addr;msgs[0].len = 1; //讀寫為似乎不起作用msgs[0].flags = 0;msgs[0].addr = 0x50; //寄存器地址左移一位,最后一位為讀寫位 寄存器地址為0x28 即00101000 左移一位最后一位為讀寫位 即01010000msgs[1].buf = rxbuf; msgs[1].len = count;msgs[1].flags = I2C_M_RD; //讀寫為似乎不起作用msgs[1].addr = 0x51; //寄存器地址左移一位,最后一位為讀寫位 寄存器地址為0x28 即00101000 左移一位最后一位為讀寫位 即01010001transfer = i2c_transfer((uint32)MEIG_IIC.i2c, msgs ,2);uint8_t reg_value = *(msgs[1].buf);MG_LOGD( "mg_i2c_read transfer =%d ,reg_value = %x", transfer ,rxbuf[0] );close = I2C_Close((uint32)(&MEIG_IIC));if(close == -1){return -1;}MG_LOGD( "mg_i2c_read close =%d", close );return 0; };

總結(jié)

以上是生活随笔為你收集整理的linux下的I2c 和展锐8310下的I2c的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。