亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 308|回復: 0
打印 上一主題 下一主題
收起左側

第12章 I2C總線與EEPROM 12.2

[復制鏈接]
跳轉到指定樓層
樓主
12.2.I2C尋址模式
上一節介紹的是I2C每一位信號的時序流程,而I2C通信在字節級的傳輸中,也有固定的時序要求。I2C通信的起始信號(Start)后,首先要發送一個從機的地址,這個地址一共有7位,緊跟著的第8位是數據方向位(R/W),“0”表示接下來要發送數據(寫),‘“1”表示接下來是請求數據(讀)。
打電話的時候,當撥通電話,接聽方撿起電話肯定要回一個“喂”,這就是告訴撥電話的人,這邊有人了。同理,這個第九位ACK實際上起到的就是這樣一個作用。當發送完了這7位地址和1位方向后,如果發送的這個地址確實存在,那么這個地址的器件應該回應一個ACK(拉低SDA即輸出“0”),如果不存在,就沒“人”回應NACKSDA將保持高電平即“1”)。
寫一個簡單的程序,訪問一下Kingst51開發板上的EEPROM的地址,另外再寫一個不存在的地址,看看它們是否能回一個ACK,來了解和確認一下這個問題。
Kingst51開發板上的EEPROM器件型號是24C02,在24C02的數據手冊3.6節中可查到,24C027位地址中,其中高4位是0b1010,低3位的地址取決于具體電路的設計,由芯片的A2A1A03個引腳的實際電平決定,來看一下電路圖,如圖12-4所示。

12-4 24C02原理圖
從圖12-4可以看出,A2A1A0都是接的GND,也就是說都是0,因此24C027位地址實際上是二進制的0b1010000,也就是0x50。用I2C的協議來尋址0x50,另外再尋址一個不存在的地址0x62,尋址完畢后,通過邏輯分析儀觀察一下兩個地址是否回復ACK
/*****************************main.c文件程序源代碼******************************/
#include <reg52.h>
#include <intrins.h>
#define I2CDelay()  {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
bit I2CAddressing(unsigned char addr);
void main()
{
    I2CAddressing(0x50); //查詢地址為0x50的器件
    I2CAddressing(0x62); //查詢地址為0x62的器件
    while (1);
}
/* 產生總線起始信號 */
void I2CStart()
{
    I2C_SDA = 1; //首先確保SDASCL都是高電平
    I2C_SCL = 1;
    I2CDelay();
    I2C_SDA = 0; //先拉低SDA
    I2CDelay();
    I2C_SCL = 0; //再拉低SCL
}
/* 產生總線停止信號 */
void I2CStop()
{
    I2C_SCL = 0; //首先確保SDASCL都是低電平
    I2C_SDA = 0;
    I2CDelay();
    I2C_SCL = 1; //先拉高SCL
    I2CDelay();
    I2C_SDA = 1; //再拉高SDA
    I2CDelay();
}
/* I2C總線寫操作,dat-待寫入字節,返回值-從機應答位的值 */
bit I2CWrite(unsigned char dat)
{
    bit ack;  //用于暫存應答位的值
    unsigned char mask;  //用于探測字節內某一位值的掩碼變量
    for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進行
    {
        if ((mask&dat) == 0)  //該位的值輸出到SDA
            I2C_SDA = 0;
        else
            I2C_SDA = 1;
        I2CDelay();
        I2C_SCL = 1;          //拉高SCL
        I2CDelay();
        I2C_SCL = 0;          //再拉低SCL,完成一個位周期
    }
    I2C_SDA = 1;   //8位數據發送完后,主機釋放SDA,以檢測從機應答
    I2CDelay();
    I2C_SCL = 1;   //拉高SCL
    ack = I2C_SDA; //讀取此時的SDA值,即為從機的應答值
    I2CDelay();
    I2C_SCL = 0;   //再拉低SCL完成應答位,并保持住總線
    return ack;    //返回從機應答值
}
/* I2C尋址函數,即檢查地址為addr的器件是否存在,返回值-從器件應答值 */
bit I2CAddressing(unsigned char addr)
{
    bit ack;
    I2CStart();  //產生起始位,即啟動一次總線操作
    ack = I2CWrite(addr<<1);  //器件地址需左移一位,因尋址命令的最低位
                              //為讀寫位,用于表示之后的操作是讀或寫
    I2CStop();   //不需進行后續讀寫,而直接停止本次總線操作
   
    return ack;
}
前面的章節中已經提到利用庫函數_nop_()可以進行精確延時,一個_nop_()的時間就是一個機器周期,這個庫函數包含在intrins.h這個文件中,如果要使用這個庫函數,只需要在程序最開始,和包含reg52.h一樣,include<intrins.h>之后,程序中就可以使用這個庫函數了。
還有一點要提一下,I2C通信分為低速模式100kbit/s、快速模式400kbit/s和高速模式3.4Mbit/s。因為所有的I2C器件都支持低速,但卻未必支持另外兩種速度,所以作為通用的I2C程序選擇100k這個速率,也就是說實際程序產生的時序必須小于等于100k的時序參數,很明顯也就是要求SCL的高低電平持續時間都不短于5us,因此在時序函數中通過插入I2CDelay()這個總線延時函數(它實際上就是4NOP指令,用define在文件開頭做了定義),加上改變SCL值語句本身占用的至少一個周期,來達到這個速度限制。如果以后需要提高速度,那么只需要減小這里的總線延時時間即可。
此外學習一個發送數據的技巧,就是I2C通信時如何將一個字節的數據發送出去。注意函數I2CWrite中,用的for循環的技巧。for (mask=0x80; mask!=0; mask>>=1),由于I2C通信是從高位開始發送數據,所以先從最高位開始,0x80dat進行按位與運算,從而得知dat7位是0還是1,然后右移一位,也就是變成了用0x40dat按位與運算,得到第6位是0還是1,一直到第0位結束,最終通過if語句,把dat8位數據依次發送了出去。
使用Kingst LA5016邏輯分析儀將抓到的波形顯示出來,并且用過I2C的協議解碼器將協議解析出來,如圖12-5所示。從圖上可以看出,第一個字節發的是0x50,回復了一個ACK;第二個字節發了一個0x62,但是出現的是NAK,說明這個地址沒有產生應答。

12-5 邏輯分析儀抓取I2C地址
在邏輯分析儀的I2C協議設置中,有三種地址格式顯示方式,也就是目前市面上各種資料對I2C協議地址定義的方式。如圖12-6所示。

12-6  I2C地址顯示格式
前邊講I2C發送的第一個字節是7位地址加一位讀寫位,但是有些資料直接將讀寫位歸結到I2C的地址,也有的資料將7位地址位認為是高7位,以開發板的0x50地址和0x62地址為例,即地址二進制0b1010 000,寫的時候是0b1010 0000;讀的時候是0b1010 0001
方式18-bit,包含讀/寫位,0x50地址對應這種方式寫地址為0xA0;讀地址為0xA1
方式28-bit,讀/寫位顯示為0即寫地址和讀地址都是0xA0
方式37-bit,本教材采用的方式,寫地址和讀地址都是0x50

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表