久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

學習I2C總線感覺有幾個不明白的地方,希望大家給予幫助

  [復制鏈接]
跳轉到指定樓層
樓主
ID:485870 發表于 2019-3-8 21:02 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

*****以下代碼來源于清翔電子教程******


    問題1:I2C為什么要初始化呢?感覺不初始化得到的也是一樣的結果啊
描述:I2C總線初始化
====================================*/
void I2C_init()
{
        SDA = 1;   //數據總線高
        _nop_();
        SCL = 1;   //時鐘總線高
        _nop_();
}


       問題2: I2C的停止信號函數為什么要先把數據總線SDA拉低呢
描述:I2C停止信號
====================================*/
void I2C_Stop()
{
        SDA = 0;
        _nop_();
        SCL = 1;
        Delay5us();
        SDA = 1;
        Delay5us();
}

       問題3:I2C主機發送應答函數為什么最后要拉高數據總線呢?那個釋放SDA又是什么意思
描述:I2C主機發送應答
====================================*/
void Master_ACK(bit i)       
{
        SCL = 0; // 拉低時鐘總線允許SDA數據總線上的數據變化
        _nop_(); // 讓總線穩定
        if (i)         //如果i = 1 那么拉低數據總線 表示主機應答
        {
                SDA = 0;
        }
        else         
        {
                SDA = 1;         //發送非應答
        }
        _nop_();//讓總線穩定
        SCL = 1;//拉高時鐘總線 讓從機從SDA線上讀走 主機的應答信號
        Delay5us();
        SCL = 0;//拉低時鐘總線, 占用總線繼續通信
        _nop_();
        SDA = 1;//釋放SDA數據總線。
        _nop_();
}


        問題4: 檢測到從機非應答或者非應答后為什么要把SCL拉低呢(代碼中標有問題4處)
描述:I2C檢測從機應答
====================================*/
bit Test_ACK()         // 檢測從機應答
{
        SCL = 1;//時鐘總線為高電平期間可以讀取從機應答信號
        Delay5us();
        if (SDA)
        {
                SCL = 0;        //問題4
                I2C_Stop();
                return(0);
        }
        else
        {
                SCL = 0;
                return(1);
        }
}


還有為什么在這個AD—DA轉換代碼中,數碼管顯示轉換過來的數字量不會隨光照的變化而變化呢,用LED檢測I2C讀寫結果都沒有問題。

#include <reg52.h>
#include <intrins.h>
#define MAIN_Fosc                11059200UL        //宏定義主時鐘HZ
#define PCF8591_ADDR        0x90                //PCF8591地址
#define DACOUT_EN                0x40                //DAC輸出使能

/*====================================
自定義類型名
====================================*/
typedef unsigned char INT8U;
typedef unsigned char uchar;

typedef unsigned int INT16U;
typedef unsigned int uint;

/*====================================
硬件接口位聲明
====================================*/
sbit SDA = P2^0;   //I2C串行數據
sbit SCL = P2^1;   //I2C串行時鐘
sbit DU  = P2^6;   //數碼管段選
sbit WE  = P2^7;   //數碼管位選
sbit LED1= P1^0;   //讀取AD的值是否成功(亮成功,滅失敗)
sbit LED2= P1^1;   //DAC成功輸出(亮成功,滅失敗)
sbit BEEP= P2^3;   //蜂鳴器引腳定義

uchar AD_Value;        //存儲AD轉換回的數字量
/*====================================
共陰極數碼管段選碼
====================================*/
uchar code table[]={
//0                1         2     3     4     5     6     7     8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9     A     B           C         D           E         F                -         .          關顯示
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00
                   };

/*====================================
數碼管位選碼
====================================*/
                                  //第1位        2位          3位         4位   5位        6位          7位        8位
uchar code T_COM[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};//數碼管位碼

/*====================================
函數:void Delay_Ms(INT16U ms)
參數:ms,毫秒延時形參
描述:12T 51單片機自適應主時鐘毫秒級延時函數
====================================*/
void Delay_Ms(INT16U ms)
{
     INT16U i;
         do{
              i = MAIN_Fosc / 96000;
                  while(--i);   //96T per loop
     }while(--ms);
}

/*====================================
函數:void Delay5us()
描述:12T 51單片機5微秒延時函數自適應時鐘(11.0592M,12M,22.1184M)
====================================*/
void Delay5us()
{
        #if MAIN_Fosc == 11059200
                _nop_();
        #elif MAIN_Fosc == 12000000
                _nop_()
        #elif MAIN_Fosc == 22118400
                _nop_(); _nop_(); _nop_();
        #endif
}

/*====================================
函數:void Display(INT8U Value)
參數:Value,顯示值 取值0-255
描述:共陰極數碼管顯示函數可顯示一個字節的數
====================================*/
void Display(INT8U Value)
{
//------------------------------
        DU = 1;
        P0 = table[Value/100];        //管顯示百位
        DU = 0;

        P0 = 0xff;                                  //清除斷碼

        WE = 1;
        P0 = T_COM[0];                          //第一位數碼管
        WE = 0;
        Delay_Ms(5);
//-------------------------------
        DU = 1;
        P0 = table[Value%100/10]; //顯示十位
        DU = 0;

        P0 = 0xff;                                  //清除斷碼

        WE = 1;
        P0 = T_COM[1];                          //第二位數碼管
        WE = 0;
        Delay_Ms(5);
//-------------------------------
        DU = 1;
        P0 = table[Value%10];                //顯示個位
        DU = 0;
                                                               
        P0 = 0xff;                                        //清除斷碼

        WE = 1;
        P0 = T_COM[2];                                //第三位數碼管
        WE = 0;
        Delay_Ms(5);
}

/*====================================
函數:I2C_init()
描述:I2C總線初始化
====================================*/
void I2C_init()
{
        SDA = 1;   //數據總線高
        _nop_();
        SCL = 1;   //時鐘總線高
        _nop_();
}

/*====================================
函數:I2C_Start()
描述:I2C起始信號
====================================*/
void I2C_Start()  
{
        SCL = 1;
        _nop_();
        SDA = 1;
        Delay5us();
        SDA = 0;
        Delay5us();
}

/*====================================
函數:I2C_Stop()
描述:I2C停止信號
====================================*/
void I2C_Stop()
{
        SDA = 0;
        _nop_();
        SCL = 1;
        Delay5us();
        SDA = 1;
        Delay5us();
}

/*====================================
函數:Master_ACK(bit i)
參數:i 為0時發送非應答 為1時發送應答
描述:I2C主機發送應答
====================================*/
void Master_ACK(bit i)       
{
        SCL = 0; // 拉低時鐘總線允許SDA數據總線上的數據變化
        _nop_(); // 讓總線穩定
        if (i)         //如果i = 1 那么拉低數據總線 表示主機應答
        {
                SDA = 0;
        }
        else         
        {
                SDA = 1;         //發送非應答
        }
        _nop_();//讓總線穩定
        SCL = 1;//拉高時鐘總線 讓從機從SDA線上讀走 主機的應答信號
        Delay5us();
        SCL = 0;//拉低時鐘總線, 占用總線繼續通信
        _nop_();
        SDA = 1;//釋放SDA數據總線。
        _nop_();
}

/*====================================
函數:Test_ACK()
返回:0為非應答 1為應答
描述:I2C檢測從機應答
====================================*/
bit Test_ACK()         // 檢測從機應答
{
        SCL = 1;//時鐘總線為高電平期間可以讀取從機應答信號
        Delay5us();
        if (SDA)
        {
                SCL = 0;
                I2C_Stop();
                return(0);
        }
        else
        {
                SCL = 0;
                return(1);
        }
}

/*====================================
函數:I2C_send_byte(uchar byte)
參數:byte 要發送的字節
描述:I2C發送一個字節
====================================*/
void I2C_send_byte(uchar byte)
{
        uchar i;
        for(i = 0 ; i < 8 ; i++)
        {
                SCL = 0;
                _nop_();
                if (byte & 0x80)       
                {
                        SDA = 1;
                        _nop_();
                }
                else
                {
                        SDA = 0;
                        _nop_();
                }
                SCL = 1;
                _nop_();
                byte <<= 1;
        }
        SCL = 0;
        _nop_();
        SDA = 1;
        _nop_();       
}

/*====================================
函數:I2C_read_byte()
返回:讀取的字節
描述:I2C讀一個字節
====================================*/
uchar I2C_read_byte()
{
        uchar i, dat;
        SCL = 0 ;
        _nop_();
        SDA = 1;
        _nop_();
        for(i = 0 ; i < 8 ; i++)
        {
                SCL = 1;
                _nop_();
                dat <<= 1;          
                if (SDA)
                {
                        dat |= 0x01;  
                }
                _nop_();
                SCL = 0;
                _nop_();
        }
        return(dat);
}

/*DAC輸出*/
bit DAC_OUT(uchar DAT)
{
        I2C_Start();
        I2C_send_byte(PCF8591_ADDR+0);
        if (!Test_ACK())
        {
                return(0);
        }
        I2C_send_byte(DACOUT_EN);        //DA輸出使能
        if (!Test_ACK())
        {
                return(0);
        }
        I2C_send_byte(DAT);
        if (!Test_ACK())
        {
                return(0);
        }
        I2C_Stop();
        return(1);       
}

/*讀AD數據*/
bit ADC_Read(uchar CON)
{
        I2C_Start();
        I2C_send_byte(PCF8591_ADDR+0);
        if (!Test_ACK())
        {
                return(0);
        }
        I2C_send_byte(CON);
        Master_ACK(0);
        I2C_Start();
        I2C_send_byte(PCF8591_ADDR+1);
        if (!Test_ACK())
        {
                return(0);
        }
        AD_Value = I2C_read_byte();
        Master_ACK(0);
        I2C_Stop();
        return(1);       
}

void main()
{
        I2C_init();
        while(1)
        {               
                //單端輸入,讀出通道2的值
                if (ADC_Read(0x02))        LED1 = 0;        else        LED1 = 1;       
                if (DAC_OUT(AD_Value))        LED2 = 0;        else        LED2 = 1;
                Display(AD_Value);
                if (AD_Value > 150)        BEEP = 0;        else        BEEP = 1;
                Delay_Ms(5);
        }       
}







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

使用道具 舉報

沙發
ID:469417 發表于 2019-3-9 02:40 | 只看該作者
所謂初始化并不是一定要達到什么目的,有時我們是在做一些聲明,有些是對一些數據進行使用前的預處理或者是清零,方便后面的使用不會出錯,比如我們聲明一個變量的時候,我們明明知道他開始的值是0,但有時我們就是要聲明讓它等于0,道理都是一個樣。不過有的初始化就必須要做。

評分

參與人數 1黑幣 +10 收起 理由
zhengchong60 + 10 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

板凳
ID:401564 發表于 2019-3-9 09:12 | 只看該作者
這都是IIC的基礎知識,說了也是和網上復制過來的一樣。
你應該是沒有去看過IIC協議的時序圖,IIC是一個有嚴格的時序要求的通訊協議,每一步都要嚴格按照IIC的協議來走的。
推薦你去PIC的官方網站找一下24VL04的中文數據手冊,它就是一個IIC器件,里面有對于IIC的時序圖,比較完整的。
需要說明的是“釋放SDA線”,8051的端口是默認的雙向端口,既可以讀也可以寫。如果你把這個SDA端口變成低電平,那么你讀取這個SDA端口的狀態就只能讀取到一個低電平。但如果你把SDA拉高了,它可以讀取到高電平,如果外部是低電平的話,那么這個低電平會把SDA線拉低,讀取到的內容就是低電平,這樣一來,CPU就可以正確的讀取到SDA的電平狀態了。
這個操作只在8051這類默認端口為雙向的單片機上用到,如果是別的單片機(像PIC這種)就沒有這個操作了,PIC的端口是要去設定這個端口是讀取的還是輸出的,設定為讀取了就不能輸出了,設定為輸出了就讀取不到外部的信號了。

評分

參與人數 1黑幣 +10 收起 理由
zhengchong60 + 10 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

地板
ID:485870 發表于 2019-3-11 19:15 | 只看該作者
刀刀見紅 發表于 2019-3-9 02:40
所謂初始化并不是一定要達到什么目的,有時我們是在做一些聲明,有些是對一些數據進行使用前的預處理或者是 ...

謝謝您!
回復

使用道具 舉報

5#
ID:485870 發表于 2019-3-11 19:16 | 只看該作者
Y_G_G 發表于 2019-3-9 09:12
這都是IIC的基礎知識,說了也是和網上復制過來的一樣。
你應該是沒有去看過IIC協議的時序圖,IIC是一個有 ...

十分感謝
回復

使用道具 舉報

6#
ID:142059 發表于 2019-3-11 21:13 來自手機 | 只看該作者
不管哪種通訊協議,總線在空閑的時候,都是高電平,為什么?因為io口內部的設計原因,只有高電平能被拉低成低電平,而低電平是不能被拉高成高電平的,因為拉低是內部mos管直接導通,等效io接在GND,所以怎么拉高都不會變成高電平。所以我們要用高電平表示空閑,這樣我們要傳輸數據的時候,把總線拉低一下就可以表示要準備傳輸數據了。所以要初始化為高電平。而有的人還有疑問,51單片機io口開機狀態就是高電平啊,初始化再設置高電平不是多此一舉么?是的,在開機為高電平的單片機里是多此一舉,但是有的單片機開機后,io口是浮空狀態的,也就是電平不確定的狀態,這時候的初始化就很重要了。說了這么多,不知道你有沒有理解。

評分

參與人數 2黑幣 +55 收起 理由
_nop_() + 5 很給力!
admin + 50 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

7#
ID:162622 發表于 2019-3-11 23:47 | 只看該作者
IIC的應答是誰接收數據(或命令)誰應答,因而就有主機應答與從機應答之分,最后一次接收完可以不應答給停止信號
回復

使用道具 舉報

8#
ID:473159 發表于 2019-3-12 06:29 來自手機 | 只看該作者
初始化又不妨礙你什么你干嘛要那樣斤斤計較

評分

參與人數 1黑幣 +15 收起 理由
正規007 + 15 很給力!

查看全部評分

回復

使用道具 舉報

9#
ID:449525 發表于 2019-3-12 08:24 | 只看該作者
大家都在2跟線上。如何通信?如何判斷是你在發送還是在接受?所以要規定下。
回復

使用道具 舉報

10#
ID:370231 發表于 2019-3-12 10:19
51黑論壇_iic協議.pdf (7.15 MB, 下載次數: 0)

11#
ID:471782 發表于 2019-3-12 12:00 來自手機 | 只看該作者
建議樓主在網上找個iic的協議資料好好看下
回復

使用道具 舉報

12#
ID:485870 發表于 2019-3-14 20:55 | 只看該作者
Angle145 發表于 2019-3-11 21:13
不管哪種通訊協議,總線在空閑的時候,都是高電平,為什么?因為io口內部的設計原因,只有高電平能被拉低成 ...

非常感謝您的幫助,這點理解到了
回復

使用道具 舉報

13#
ID:485870 發表于 2019-3-14 21:03 | 只看該作者
Y_G_G 發表于 2019-3-9 09:12
這都是IIC的基礎知識,說了也是和網上復制過來的一樣。
你應該是沒有去看過IIC協議的時序圖,IIC是一個有 ...

我看了時序圖手冊的,感覺代碼并沒有完全按照時序圖的要求來
回復

使用道具 舉報

14#
ID:485870 發表于 2019-3-14 21:15 | 只看該作者
Angle145 發表于 2019-3-11 21:13
不管哪種通訊協議,總線在空閑的時候,都是高電平,為什么?因為io口內部的設計原因,只有高電平能被拉低成 ...

能加一下qq嗎?以后遇到的問題還希望有人能幫幫忙,謝謝
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美日韩三级 | 国产日韩精品一区 | 久久天堂 | 天天综合久久网 | 精品久久久久久久人人人人传媒 | 日韩欧美三级在线 | 国产精品美女www爽爽爽 | 久久精品免费观看 | 精品视频在线播放 | 日本在线看片 | 免费在线黄 | 成人亚洲一区 | 国产视频一区二区 | 美女福利网站 | 精品国产精品三级精品av网址 | 97超碰在线播放 | 亚洲人精品 | 久久精品国内 | 久久久久久久久国产成人免费 | 欧美日韩不卡合集视频 | 亚洲精品自拍视频 | 久久国产视频一区 | 伊人久久麻豆 | 久久久久中文字幕 | 日日摸夜夜添夜夜添特色大片 | 在线看成人av | 色综合久久久久 | 日韩精品视频在线 | 一区二区三区高清 | 五月免费视频 | 久热精品在线 | 国产成人午夜高潮毛片 | 欧美激情在线精品一区二区三区 | 国产精品一区二区欧美 | 久久噜噜噜精品国产亚洲综合 | 日韩和的一区二在线 | 免费一二区| 欧美久久久久久久 | 人人cao| 最新中文字幕第一页视频 | 范冰冰一级做a爰片久久毛片 |