娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

I2C協(xié)議->裸機(jī)程序->adapter驅(qū)動(dòng)程序分析

發(fā)布者:電子設(shè)計(jì)藝術(shù)家最新更新時(shí)間:2021-11-24 關(guān)鍵字:I2C協(xié)議  adapter 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

開(kāi)發(fā)板:mini2440


內(nèi)核  :linux2.6.32.2


參考  :韋東山畢業(yè)班I2C視頻教程


1、i2c協(xié)議簡(jiǎn)要分析


    i2c中線是一種由 PHILIPS 公司開(kāi)發(fā)的串行總線,用于連接微控制器及其外圍設(shè)備,它具有以下特點(diǎn)。

        1、只有兩條總線線路:一條串行數(shù)據(jù)線SDA,一條串行時(shí)鐘線SCL。

        2、每個(gè)連接到總線的器件都可以使用軟件根據(jù)它的唯一的地址來(lái)確定。

        3、傳輸數(shù)據(jù)的設(shè)備之間是簡(jiǎn)單的主從關(guān)系。

        4、主機(jī)可以用作主機(jī)發(fā)送器或者主機(jī)接收器。

        5、它是一個(gè)真正的多主機(jī)總線,兩個(gè)或多個(gè)主機(jī)同時(shí)發(fā)起數(shù)據(jù)傳輸時(shí),可以通過(guò)沖突檢測(cè)和仲裁來(lái)防止數(shù)據(jù)被破壞。

        6、串行的8位雙向傳輸,位速在標(biāo)準(zhǔn)模式下可達(dá) 100kbit/s,在快速模式下可達(dá)400kbit/s,在高速模式下可待3.4Mbit/s。

        7、片上的濾波器可以增加抗干擾能力,保證數(shù)據(jù)的完整性。

        8、連接到同一總線上的IC數(shù)量只受到總線的最大電容400Pf的限制。

如上圖所示,啟動(dòng)一個(gè)傳輸時(shí),主機(jī)先發(fā)送一個(gè)S信號(hào),然后發(fā)送8位數(shù)據(jù)。這8位數(shù)據(jù)的前7位為從機(jī)地址,第八位表示傳輸?shù)姆较颍?表示寫,1表示讀),如果有數(shù)據(jù)則繼續(xù)發(fā)送,最后發(fā)出P信號(hào)停止。

信號(hào)類型:


    注意:正常數(shù)據(jù)傳輸時(shí),SDA 在 SCL 為低電平時(shí)改變,在 SCL 為高電平時(shí)保持穩(wěn)定。

    開(kāi)始信號(hào) S 信號(hào):

        SCL 為高電平時(shí),SDA由高電平向低電平跳變,開(kāi)始傳送數(shù)據(jù)。

    結(jié)束信號(hào) P 信號(hào):

        SCL 為高電平時(shí),SDA由低電平向高電平跳變,結(jié)束傳送數(shù)據(jù)。

    響應(yīng)信號(hào) ACK:

        接收器在接收到8位數(shù)據(jù)后,在第9個(gè)時(shí)鐘周期,拉低 SDA 電平

    注意:在第9個(gè)時(shí)鐘周期,發(fā)送器保持SDA為高,如果有ACK,那么第9個(gè)時(shí)鐘周期SDA為低電平,如果沒(méi)有為高電平,發(fā)送器根據(jù)電平高低分辨是否有ACK信號(hào)。

          如果使能了IIC中斷,發(fā)送完8bit數(shù)據(jù)后,主機(jī)自動(dòng)進(jìn)入中斷處理函數(shù),此時(shí)SCL被發(fā)送器拉低,讓接收器被迫等待。恢復(fù)傳輸只需要清除中斷掛起。


2、 s3c2440 讀寫流程

    1、設(shè)置傳輸模式 IICSTAT[7-6],我們做實(shí)驗(yàn)與AT24C08通信時(shí),2440作為主機(jī),因此只用到主機(jī)發(fā)模式和主機(jī)收模式。

    2、寫入從機(jī)地址到 IICDS[7-1],此時(shí)IICDS[7-1]位表示從機(jī)地址,第0位不關(guān)心。如 AT24C08 為 0xA0(最低位寫0了,發(fā)送到數(shù)據(jù)線上的7位地址的后邊以為才表示收發(fā),這里雖然寫0但并不是根據(jù)這里的0來(lái)真正發(fā)送的)。

    3、寫 0xF0(寫) 或 0xB0(讀)到 IICSTAT 寄存器, 高兩位表示 傳輸模式前邊設(shè)置過(guò)了,設(shè)置IICSTT[5-4] 為 11,使能傳輸,發(fā)送S信號(hào)。

    4、IIC控制器自動(dòng)將第2步中設(shè)置的 IICDS[7-1] 再根據(jù) 傳輸模式 補(bǔ)充 IICDS[0]位,發(fā)送出去。

    5、進(jìn)入第9個(gè)時(shí)鐘周期,此時(shí),從機(jī)決定是否發(fā)出ACK信號(hào),主機(jī)進(jìn)入中斷,判斷是否收到ACK信號(hào),以及是否繼續(xù)傳輸。

    繼續(xù)發(fā)送:

        1、將數(shù)據(jù)寫入 IICDS 

        2、清除中斷掛起,SCL時(shí)鐘恢復(fù),IICDS的數(shù)據(jù)被自動(dòng)發(fā)送到 SDA 線上,回到第5步。

    停止發(fā)送:

        1、寫 0xD0(寫) 和 0x90(讀) 到 IICATAT ,IICATAT[7-6]還是表示的傳輸模式,IICATAT[5-4] == 0 1,發(fā)送停止信號(hào)

        2、清除中斷掛起,SCL時(shí)鐘恢復(fù),發(fā)出停止信號(hào)

        3、延時(shí),等待停止信號(hào)發(fā)出

3、 AT24C08 讀寫分析


    1、寫過(guò)程

    寫過(guò)程與2440芯片的里的寫流程相一致,按照流程寫就OK


    2、讀過(guò)程

    讀過(guò)程是由2440芯片里的一個(gè)寫流程加一個(gè)讀流程組合而成,其中寫流程結(jié)束沒(méi)有發(fā)出P信號(hào),而是直接發(fā)出了S信號(hào)開(kāi)始讀流程,也就是我為什么加了一道紅線的原因。


附上一份簡(jiǎn)單的裸機(jī)程序,僅供參考:基于MINI2440



#include

#include "s3c2440.h"

 

void Delay(int time);

 

#define WRDATA      (1)

#define RDDATA      (2)

 

typedef struct tI2C {

    unsigned char *pData;   /* 數(shù)據(jù)緩沖區(qū) */

    volatile int DataCount; /* 等待傳輸?shù)臄?shù)據(jù)長(zhǎng)度 */

    volatile int Status;    /* 狀態(tài) */

    volatile int Mode;      /* 模式:讀/寫 */

    volatile int Pt;        /* pData中待傳輸數(shù)據(jù)的位置 */

}tS3C24xx_I2C, *ptS3C24xx_I2C;

 

static tS3C24xx_I2C g_tS3C24xx_I2C;

 

/*

 * I2C初始化

 */

void i2c_init(void)

{

    GPEUP  |= 0xc000;       // 禁止內(nèi)部上拉

/*

 * AT24C08 兩根線 I2CSCL I2CSDA 與 2440芯片相連

 *  配置2440 GPECON GPE15 GPE14引腳為I2C功能

 */

    GPECON |= 0xa0000000;   // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL

/* 開(kāi)INT_IIC中斷 */

    //INTMSK &= ~(BIT_IIC);

 

    /* bit[7] = 1, 使能ACK

     * bit[6] = 0, IICCLK = PCLK/16

     * bit[5] = 1, 使能中斷

     * bit[3:0] = 0xf, Tx clock = IICCLK/16

     * PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz

     */

    IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);  // 0xaf

 

    //IICADD  = 0x10;     // S3C24xx slave address = [7:1]

    IICSTAT = 0x10;     // I2C串行輸出使能(Rx/Tx)

}

 

void I_Write(unsigned int slvaddr, unsigned char addr, unsigned char data)  

{  

    unsigned int ack;  

// 寫從地址

IICSTAT |= 0x1<<6;//主機(jī)寫模式   

    IICSTAT |= 0x1<<7;  

    IICDS = slvaddr;//0xa0;  //write slave address to IICDS   

    IICCON&=~0x10; //clear pending bit   

    IICSTAT = 0xf0;  //(M/T start)   

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

    // 寫寄存器地址    

    IICDS = addr;  

    IICCON&=~0x10; //clear pending bit   

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

// 寫數(shù)據(jù)

    IICDS = data;  

    IICCON&=~0x10; //clear pending bit   

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

// 發(fā)出停止信號(hào)

    IICSTAT = 0xD0; //write (M/T stop to IICSTAT)   

    IICCON&=~0x10; //clear pending bit   

 

    while((IICSTAT & 1<<5) == 1);  

}  

unsigned char I_Read(unsigned int slvaddr, unsigned char addr)  

{  

    unsigned char data  = 1;  

    int ack;  

// 寫從地址

IICSTAT |= 0x1<<6;//主機(jī)寫模式   

    IICSTAT |= 0x1<<7;  

slvaddr = 0xA0;    

    IICDS = slvaddr;//0xa0;  //write slave address to IICDS   

    IICCON&=~0x10; //clear pending bit   

    IICSTAT = 0xf0;  //(M/T start)   

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

  

    // 寫寄存器地址

    IICDS = addr;  

    IICCON&=~0x10; //clear pending bit   

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

 

    // 寫從地址(讀模式)

    slvaddr = 0xA1;

    IICSTAT &= ~(0x1<<6);//主機(jī)接受模式  

    IICSTAT |= 0x1<<7;  

    IICDS = slvaddr;  

    IICCON&=~0x10; //clear pending bit   

    IICSTAT = 0xb0;  //(M/R Start)   

    while((IICCON & 1<<4) == 0);//udelay(10);//uart_SendByte('o');//ack period and then interrupt is pending::   

 

// 讀數(shù)據(jù)

    data = IICDS;  

    //IICCON&=~0x10; //clear pending bit

IICCON = 0x2f; //清掛起狀態(tài),并設(shè)置無(wú)應(yīng)答

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

    data = IICDS;  

    

//IICCON&=~0x10; //clear pending bit   

IICCON = 0x2f; //清掛起狀態(tài),并設(shè)置無(wú)應(yīng)答

    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   

 

 

    IICSTAT = 0x90;  

IICCON = 0xaf;

    //IICCON &= ~0x10; //clear pending bit   

 

    while((IICSTAT & 1<<5) == 1);  

 

    return data;  

      



4、adapter驅(qū)動(dòng)程序

    這里,我們主要分析驅(qū)動(dòng)里的發(fā)送核心算法,至于注冊(cè)中斷,IO內(nèi)存映射,設(shè)置寄存器不在討論。

    static int xxx_i2c_xfer(struct i2c_adapter *adpap, struct i2c_msg *msg,int num)

    這個(gè)算法函數(shù)的作用就是將上層封裝好的一些i2c_msg 進(jìn)行解析,將數(shù)據(jù)寫入寄存器,發(fā)送出去。在設(shè)備驅(qū)動(dòng)層,我們使用了類似i2c_smbus_write_byte 等函數(shù),類似的函數(shù)有很多,它們的作用就是封裝i2c_msg 結(jié)構(gòu)(比如讀和寫的 msg 肯定不一樣,讀一個(gè)字節(jié)和讀多個(gè)字節(jié)也不一樣),然后調(diào)用 i2c_smbus_xfer_emulated->i2c_transfer,最終調(diào)用到我們的xxx_i2c_xfer函數(shù)進(jìn)行傳輸。通過(guò)分析i2c_smbus_xfer_emulated函數(shù),我們可以了解i2c_msg是如何封裝的。下面,我們簡(jiǎn)單分析一下,知道最上層想干什么,我們才能知道實(shí)現(xiàn)哪些底層的功能不是。

struct i2c_msg {

__u16 addr; //從機(jī)地址

__u16 flags;

__u16 len; // buf 里 有多少個(gè)字節(jié)

__u8 *buf; // 本 msg 含有的數(shù)據(jù),可能是1個(gè)字節(jié),可有可能是多個(gè)字節(jié)

};

    此函數(shù),省略了很多內(nèi)容,舉例分析而已~,細(xì)節(jié)請(qǐng)看源碼



static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,

                                   unsigned short flags,

                                   char read_write, u8 command, int size,

                                   union i2c_smbus_data * data)

{

unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];

unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];

int num = read_write == I2C_SMBUS_READ?2:1; // 寫操作兩個(gè)Msg 讀操作一個(gè)msg 這和我們前面分析AT24c08是一致的

struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },

                          { addr, flags | I2C_M_RD, 0, msgbuf1 }

                        };

msgbuf0[0] = command; // 從機(jī)地址右移1位得到的,比如AT24C08  為 0x50

switch(size) {

case I2C_SMBUS_BYTE_DATA: // 單字節(jié)讀寫

if (read_write == I2C_SMBUS_READ)

msg[1].len = 1;

/*

* 讀:

* msgbuf0[0] = command

*  msg[1].len = 1 ,數(shù)據(jù)會(huì)讀到 msgbuf0[1] 里

*/

else {

msg[0].len = 2;

msgbuf0[1] = data->byte;

/*

* 寫:

* msgbuf0[0] = command

* msgbuf0[1] = data->byte

*/

}

break;

}

status = i2c_transfer(adapter, msg, num);

}

    上面代碼跟我們分析AT24C08的時(shí)候如出一轍,對(duì)于一個(gè)寫操作,我們只需要一個(gè)2440的寫流程對(duì)應(yīng)于這里的一個(gè)Msg,然而對(duì)于讀操作,我們需要2440的兩個(gè)流程,對(duì)應(yīng)于這里的兩個(gè)Msg。那么,我們底層控制器驅(qū)動(dòng)需要做的工作就是,取出所有的Msg,將每一個(gè)Msg里buf里的數(shù)據(jù)發(fā)送出去,如果有下一個(gè)Msg, 那么再將下一個(gè)Msg里的buf發(fā)送完畢,最后發(fā)出P停止信號(hào)。還有一點(diǎn),每發(fā)送一個(gè)Msg都要先發(fā)出S開(kāi)始信號(hào)。


    在看adapter程序之前,我們先來(lái)簡(jiǎn)單思考一下,發(fā)出S開(kāi)始信號(hào)之后,可能有以下3中情況:

        1、當(dāng)前msg.len == 0 ,如果有ACK直接發(fā)出stop信號(hào)。這種情況出現(xiàn)在,控制器枚舉設(shè)備的時(shí)候,因?yàn)樗话l(fā)送S信號(hào)以及設(shè)備地址,不發(fā)送數(shù)據(jù)。

        2、根據(jù)msg->flags 為 I2C_M_RD 等信息判斷讀寫,msg->flags 最低位為1表示讀,最低位為0表示寫。

            #define I2C_M_TEN0x0010          /* this is a ten bit chip address */

            #define I2C_M_RD0x0001           /* read data, from slave to master */

[1] [2]
關(guān)鍵字:I2C協(xié)議  adapter 引用地址:I2C協(xié)議->裸機(jī)程序->adapter驅(qū)動(dòng)程序分析

上一篇:i2c驅(qū)動(dòng)程序全面分析,從adapter驅(qū)動(dòng)程序到設(shè)備驅(qū)動(dòng)程序
下一篇:Linux ARMv7中斷向量表搬移(2)

推薦閱讀最新更新時(shí)間:2025-04-17 02:02

Tiny4412裸機(jī)程序之操作ICache
一、首先普及一下什么是Cache 基于程序訪問(wèn)的局限性,在主存和CPU通用寄存器之前設(shè)置了一類高速的、容量較小的存儲(chǔ)器,把正在執(zhí)行的指令地址附件的一部分指令或數(shù)據(jù)從主存調(diào)入這類存儲(chǔ)器,供CPU在一段時(shí)間內(nèi)使用,這對(duì)提高程序的運(yùn)行速度有很大的作用。這類介于主存和CPU之間的高速小容量存儲(chǔ)器稱作高速cache。比較常見(jiàn)的cache包括icache和dcache。 icache的使用比較簡(jiǎn)單,系統(tǒng)剛上電時(shí),icache中的內(nèi)容是無(wú)效的,并且icache的功能是關(guān)閉的,往CP15協(xié)處理器中的寄存器1的bit 寫1可以啟動(dòng)icache,寫0可以停止icache。icache關(guān)閉時(shí),CPU每次取指都要讀主存,性能非常低。因?yàn)閕cache可
[單片機(jī)]
ARM裸機(jī)程序設(shè)計(jì)—按鍵中斷程序設(shè)計(jì)
首先是按鍵中斷處理過(guò)程: 1、中斷控制器匯集各類外設(shè)發(fā)出的中斷信號(hào),然后告訴CPU 2、CPU保存當(dāng)前程序的運(yùn)行環(huán)境(各個(gè)寄存器等),調(diào)用中斷服務(wù)程序(ISR,Interrupt Service Routine) 3、在ISR中通過(guò)讀中斷控制器、外設(shè)的相關(guān)寄存器來(lái)識(shí)別這是哪個(gè)中斷,并進(jìn)行相應(yīng)的處理 4、清楚中斷:通過(guò)讀寫中斷控制器和外設(shè)的相關(guān)寄存器來(lái)實(shí)現(xiàn) 5、最好恢復(fù)中斷程序的運(yùn)行環(huán)境(即上面保存的各個(gè)寄存器等),繼續(xù)執(zhí)行 按鍵中斷程序設(shè)計(jì)流程: 1、按鍵以及按鍵中斷初始化 1)對(duì)按鍵中斷端口初始化,設(shè)置為特殊功能模式(10) 2)設(shè)置外部中斷觸發(fā)方式(EXTINTn低電平觸發(fā)000、高電平觸發(fā)001、上升沿觸
[單片機(jī)]
小廣播
設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號(hào)

 
EEWorld服務(wù)號(hào)

 
汽車開(kāi)發(fā)圈

 
機(jī)器人開(kāi)發(fā)圈

電子工程世界版權(quán)所有 京B2-20211791 京ICP備10001474號(hào)-1 電信業(yè)務(wù)審批[2006]字第258號(hào)函 京公網(wǎng)安備 11010802033920號(hào) Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 抚顺市| 娱乐| 娄底市| 石柱| 绩溪县| 庐江县| 涞水县| 大关县| 安丘市| 台南县| 屏南县| 安多县| 石狮市| 赤城县| 五华县| 泾源县| 嘉兴市| 双桥区| 遂平县| 习水县| 富宁县| 洪泽县| 周口市| 沙坪坝区| 龙州县| 轮台县| 姜堰市| 肇源县| 南阳市| 开平市| 绵阳市| 白河县| 和林格尔县| 呼和浩特市| 洮南市| 石家庄市| 鸡东县| 长阳| 都安| 阿瓦提县| 玛纳斯县|