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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3965|回復(fù): 9
收起左側(cè)

對于51單片機I2C傳送的問題

[復(fù)制鏈接]
ID:254333 發(fā)表于 2018-2-14 20:47 | 顯示全部樓層 |閱讀模式
//************向AT24C02寫入數(shù)據(jù)*******************//
bit write_byte(uchar write_data)
{
        uchar i;
        bit ack_bit;        //定義應(yīng)答信號
        for(i=0;i<8;i++)    // 循環(huán)移入8個位
        {
                SDA=(bit)(write_data & 0x80);
                _nop_();
                SCL = 1;
                _nop_();
                    _nop_();
                SCL = 0;
                write_data=write_data<<1;
        }
        SDA = 1;                        // 讀取應(yīng)答
        _nop_();
        _nop_();
        SCL = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ack_bit=SDA;
        SCL = 0;
        return ack_bit;                        // 返回AT24Cxx應(yīng)答位
}
這是原函數(shù)
1、SDA=(bit)(write_data & 0x80);我的這行代碼有一些疑惑,不知道我的理解是否正確,我們寫入的數(shù)據(jù)比如說是1000 0000&1000 0000那么結(jié)果就是1000 0000只取最高位,是這樣嗎?
2、SDA = 1;                        // 讀取應(yīng)答
        _nop_();
        _nop_();
        SCL = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ack_bit=SDA;
        SCL = 0;
        return ack_bit;                        // 返回AT24Cxx應(yīng)答位
主機和從機的SDA是同一根線吧?SDA=1是設(shè)置總線為空閑狀態(tài),SCL從1到0是為了傳輸傳輸信號。定義的應(yīng)答信號是從機的嗎?最后返回應(yīng)答位給主調(diào)函數(shù)。還是不太明白這個ack_bit存在的意義。
求解

回復(fù)

使用道具 舉報

ID:279646 發(fā)表于 2018-2-28 18:30 | 顯示全部樓層
我來給你解答一下吧。
第一個問題 C51里面有bit這個關(guān)鍵字。這個關(guān)鍵字定義了一個位,我們在單片機里所說的置位和復(fù)位,一個是把位變成1,一個是把位變成0. 這里SDA=(bit)(write_data & 0x80);  bit加了小括號代表強制類型轉(zhuǎn)換。也就是說 后面的(write_data & 0x80) 做了與運算以后, 如果不是0,就會被強制轉(zhuǎn)化為1,如果是0那么就是0.你說的write_data=0x80的時候 運算以后是 0x80,強制類型轉(zhuǎn)換就變成了1.
第二個問題的原因在于,你沒有理解I2C總線的時序。不要只看代碼,你要去深刻理解時序圖。樓上給的圖很好。你看看,不管是應(yīng)答0 還是非應(yīng)答1. 讀取這個應(yīng)答信號的時候SCL都要為高電平。在代碼里面就是SCL=1,根據(jù)時序圖先延時一下。然后再采樣SDA線上的數(shù)據(jù),于是4個延時以后ack_bit=SDA; 這個時候SDA上的狀態(tài)就放到了這個ack_bit里。然后看這個變量是0還是1來判斷從機是否有應(yīng)答。一開始SDA=1,釋放了總線。如果有應(yīng)答,器件就會把SDA線拉低變成0.如果沒有應(yīng)答,那么SDA一直為高。

評分

參與人數(shù) 1黑幣 +80 收起 理由
admin + 80 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

ID:123289 發(fā)表于 2018-2-16 10:31 | 顯示全部樓層

回帖獎勵 +10

如果你想知道線上的數(shù)據(jù)是什么,當(dāng)然是可以調(diào)用一個子程序來實現(xiàn)。
你想啊,調(diào)用結(jié)束后,線上的數(shù)據(jù)會在哪里呢?
回復(fù)

使用道具 舉報

ID:254333 發(fā)表于 2018-2-16 22:07 | 顯示全部樓層
yzwzfyz 發(fā)表于 2018-2-16 10:31
如果你想知道線上的數(shù)據(jù)是什么,當(dāng)然是可以調(diào)用一個子程序來實現(xiàn)。
你想啊,調(diào)用結(jié)束后,線上的數(shù)據(jù)會在哪 ...

我把全文貼出來吧
#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
bit flag=0;   //寫24C02的標(biāo)志位類型bit可以定義一個位類型的變量,它的值是一個二進制位,只有一個0或者1
sbit SDA=P3^7;                    
sbit SCL=P3^6;
sbit shi=P3^0;
sbit ge=P3^1;
uchar sec,tcnt;//sec表示讀出的數(shù)據(jù),tcnt表示定時器中斷次數(shù)
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//******************** 延時函數(shù) *********************//
void delayms(uint ms)
{
        uchar i;
        while(ms--)
        {
                for(i=0;i<120;i++);
        }
}
//***********起始信號 ********************//
void start()
{
        SDA=1;
        SCL=1;
        _nop_();
        _nop_();
        SDA=0;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SCL=0;
}

//***********停止信號 ********************//       
void stop()
{
        SDA=0;
        _nop_();
        _nop_();
        SCL=1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SDA=1;               
}
//************從AT24C02讀取數(shù)據(jù)*******************//
uchar read_byte( )
{
        uchar i,da;
        for(i=0; i<8;i++)
        {
                SCL=1;
                da=da<<1;
                da=da|(uchar)SDA;
                SCL=0;
        }
        return(da);
}
//************向AT24C02寫入數(shù)據(jù)*******************//
bit write_byte(uchar write_data)
{
        uchar i;
        bit ack_bit;        //定義應(yīng)答信號
        for(i=0;i<8;i++)    // 循環(huán)移入8個位
        {
                SDA=(bit)(write_data & 0x80);
                _nop_();
                SCL = 1;
                _nop_();
            _nop_();
                SCL = 0;
                write_data=write_data<<1;
        }
        SDA = 1;                        // 讀取應(yīng)答
        _nop_();
        _nop_();
        SCL = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ack_bit=SDA;
        SCL = 0;
        return ack_bit;                        // 返回AT24Cxx應(yīng)答位
}
//************向AT24C02指定地址寫入數(shù)據(jù)************//
void write_byte_add(uchar addr, uchar write_data)
{
        start();
        write_byte(0xa0);//E2PROM的地址碼,最后一位0寫方向位
        write_byte(addr);
        write_byte(write_data);
        stop();
        delayms(10);               
}
//************從AT24C02當(dāng)前地址讀取數(shù)據(jù)************//
unsigned char read_current()
{
        uchar read_data;
        start();
        write_byte(0xa1);//同理為地址碼,最后一位1讀方向位
        read_data=read_byte();
        stop();
        return read_data;
}
//************從AT24C02指定地址讀取數(shù)據(jù)************//
unsigned char read_random(uchar random_addr)
{
        start();
        write_byte(0xa0);
        write_byte(random_addr);
        return(read_current());
}

//*******************顯示函數(shù) **************//
void display(uchar bai_c,uchar sh_c)
{
        shi=1;
        P2=table[bai_c];  //顯示第一位
        delayms(5);
        shi=0;
        P2=table[sh_c];  //顯示第二位
        ge=1;
        delayms(5);
        ge=0;
}

//*******************主函數(shù) **************//
void main()
{
        SDA = 1;//總線初始化
        SCL = 1;//總線初始化
        sec=read_random(0x02); //讀出保存的數(shù)據(jù)賦予sec
        if(sec>100)                 //防止首次讀出錯誤數(shù)據(jù)
                sec=0;
        TMOD=0x01;   //定時器T0工作在定時方式1
        ET0=1;                  //T0中斷允許
        EA=1;                  //CPU中斷允許
        TH0=(65536-50000)/256; //
        TL0=(65536-50000)%256; //TH0、TL0送初值
        TR0=1;  //啟動T0
        while(1)
        {
                display(sec/10,sec%10);
                if(flag==1)   //判斷計時器是否計時1秒
                {
                        flag=0;   //清0
                        write_byte_add(2,sec); //在24C02的地址02中寫入數(shù)據(jù)sec
                }
        }
}
//*******************定時器T0中斷函數(shù)**************//
void t0() interrupt 1
{
        TH0=(65536-50000)/256; //
        TL0=(65536-50000)%256; //重裝TH0、TL0送初值
        tcnt++;  //50ms         tcnt加1
        if(tcnt==20)
        {
                tcnt=0;         //
                sec++;
                flag=1; //1秒寫一次24C02
                if(sec==100)
                {
                        sec=0;
                }
        }
}
謝謝了,線上的數(shù)據(jù)是具有記憶功能秒表的時間,0~99
回復(fù)

使用道具 舉報

ID:254333 發(fā)表于 2018-2-26 20:43 | 顯示全部樓層
求助,有沒有大佬可以回答一下我的問題。
回復(fù)

使用道具 舉報

ID:280512 發(fā)表于 2018-2-26 22:37 | 顯示全部樓層
(bit)是個轉(zhuǎn)換類型符。只要write_data非零,(bit)(write_data & 0x80)就為“1”,然后,write_data左移,寫入一位。ack_bit,是你定義的一位返回值的位,是這樣吧?
回復(fù)

使用道具 舉報

ID:280512 發(fā)表于 2018-2-26 22:40 | 顯示全部樓層
你需要的是最高位,所以,要用0x80作為判斷的條件
回復(fù)

使用道具 舉報

ID:111634 發(fā)表于 2018-2-26 22:56 | 顯示全部樓層

回帖獎勵 +10

本帖最后由 zl2168 于 2018-2-26 23:03 編輯

能讀懂IIC收發(fā)時序圖就能理解。介紹你一本書,《80C51單片機實用教程——基于Keil C和Proteus》高等教育出版社ISBN 978-7-04-044532-9,內(nèi)有IIC詳細(xì)講解。
I2C總線基本信號.jpg I2C總線數(shù)據(jù)傳送時序.jpg
回復(fù)

使用道具 舉報

ID:247040 發(fā)表于 2018-2-28 18:42 | 顯示全部樓層
同求ack_bit存在的意義樓主解決沒
回復(fù)

使用道具 舉報

ID:304404 發(fā)表于 2018-4-24 08:59 | 顯示全部樓層
樓主有沒有仿真圖  讓我參考一下
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 自拍偷拍第一页 | www日本在线播放 | 午夜午夜精品一区二区三区文 | 欧美一区2区三区4区公司二百 | 久久免费观看一级毛片 | 欧美激情精品久久久久 | 中文字幕第二十页 | 免费在线观看黄色av | 中文字幕视频在线观看 | 久久国内精品 | 二区精品| 日韩av成人 | 亚洲人成人一区二区在线观看 | 51ⅴ精品国产91久久久久久 | 成人在线观看免费 | 日韩欧美在 | 国产精品一区一区 | 亚洲一区二区三区免费在线观看 | 欧美日韩国产在线观看 | 九色91视频 | 天天久久 | 粉嫩一区二区三区国产精品 | 亚洲电影中文字幕 | 成人av在线网站 | 伦理片97| 欧美在线视频不卡 | 国产午夜精品一区二区三区四区 | 欧美一卡二卡在线观看 | 国产一区高清 | 婷婷免费在线 | 一区二区在线 | 国产aⅴ爽av久久久久久久 | 中文字幕久久久 | 中文字幕在线观看一区 | 日韩久久久久久久 | 国产美女在线观看 | 97精品超碰一区二区三区 | 亚洲精品2区 | 欧美精品欧美精品系列 | 久久蜜桃资源一区二区老牛 | 一区二区三区在线电影 |