找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 14386|回復(fù): 7
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)模擬I2c接口 原理與程序

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
1、I2c啟動(dòng)

    由上圖可知SDA在SCL為高電平時(shí)由高變?yōu)榈捅硎締?dòng)I2c,注意時(shí)間。


2、I2c關(guān)閉

    由上圖可知SDA在SCL為高電平時(shí)由低變?yōu)楦弑硎締?dòng)I2c,注意時(shí)間。

3、數(shù)據(jù)0

    由上圖可知SDA在SCL為高電平時(shí)拉低表示0,注意時(shí)間。



4、數(shù)據(jù)1

    由上圖可知SDA在SCL為高電平時(shí)拉高表示0,注意時(shí)間。

5、I2c寫(xiě)數(shù)據(jù)(數(shù)據(jù)由51到設(shè)備)
由上圖可以看書(shū)寫(xiě)數(shù)據(jù)的步驟為:1)啟動(dòng)I2c;
2)寫(xiě)入設(shè)備地址(七位設(shè)備地址加一位讀寫(xiě)命令,最后1為讀,0為寫(xiě));
3)等待應(yīng)答(由設(shè)備發(fā)出,讀數(shù)據(jù)時(shí)由51給應(yīng)答),這一步可以和第二部寫(xiě)在一個(gè)函數(shù)中;
4)寫(xiě)入數(shù)據(jù)要存放的地址;
5)等待應(yīng)答;
6)寫(xiě)入數(shù)據(jù);
7)等待應(yīng)答;
8)關(guān)閉I2c。
若將等待應(yīng)答與寫(xiě)數(shù)據(jù)放在一個(gè)函數(shù)中可簡(jiǎn)化為:1)啟動(dòng)I2c;
2)寫(xiě)入設(shè)備地址

3)寫(xiě)入數(shù)據(jù)要存放的地址;

4)寫(xiě)入數(shù)據(jù);

5)關(guān)閉I2c。

6、I2c讀數(shù)據(jù)(51從設(shè)備中讀取數(shù)據(jù))

由上圖可以看書(shū)寫(xiě)數(shù)據(jù)的步驟為:1)啟動(dòng)I2c;
2)寫(xiě)入設(shè)備地址;

3)寫(xiě)入要讀取數(shù)據(jù)存放的地址;

4)啟動(dòng)I2c;

5)寫(xiě)入設(shè)備地址(第八位為1,表示讀數(shù)據(jù));
6)讀數(shù)據(jù);
7)給設(shè)備發(fā)送應(yīng)答信號(hào);
8)關(guān)閉I2c;

7、對(duì)應(yīng)的51程序
  1. #include <STC12C5A60S2.H>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4.         
  5. sbit SCL=P2^1;
  6. sbit SDA=P2^0;
  7. uchar code duan[]=
  8. {
  9.         0xfc,0x60,0xda,
  10.         0xf2,0x66,0xb6,
  11.         0xbe,0xe0,0xfe,0xf6
  12. };

  13. void delay(uint time)
  14. {
  15.         uint i,j;
  16.         for(i=0;i<time;i++)
  17.                 for(j=0;j<10;j++);
  18. }

  19. void I2c_start()
  20. {
  21.         SDA=1;
  22.         delay(1);
  23.         SCL=1;
  24.         delay(1);           
  25.         SDA=0;
  26.         delay(1);      
  27.         SCL=0;
  28.         delay(1);
  29. }


  30. void I2c_stop()
  31. {
  32.         SDA=0;
  33.         delay(1);
  34.         SCL=1;
  35.         delay(1);      
  36.         SDA=1;
  37.         delay(1);
  38. }

  39. //·¢Ëíack
  40. void I2c_sendAck(bit ack)
  41. {
  42.     SDA = ack;      
  43.     SCL = 1;      
  44.     delay(1);   
  45.     SCL = 0;
  46.                 delay(1);
  47.                
  48. }

  49. //»ñè¡ack
  50. bit I2c_getAck(void)
  51. {
  52.     bit ack;        
  53.     SDA = 1;        
  54.     SCL = 1;        
  55.     delay(1);   
  56.     ack = SDA;      
  57.     SCL = 0;
  58.     return ack;
  59. }

  60. uchar I2c_read()
  61. {
  62.         uchar i,dat=0;
  63.         SDA=1;
  64.         delay(1);
  65.         for(i=0;i<8;i++)
  66.         {
  67.                 SCL=1;
  68.                 delay(1);
  69.                 dat<<=1;
  70.                 dat|=SDA;
  71.                 delay(1);
  72.                 SCL=0;
  73.         }
  74.         return dat;
  75. }

  76. void I2c_write(uchar dat)
  77. {
  78.         uchar i;
  79.         for(i=0;i<8;i++)
  80.         {
  81.                 SDA=dat>>7;
  82.                 dat<<=1;
  83.                 delay(1);
  84.                 SCL=1;
  85.                 delay(1);
  86.                 SCL=0;
  87.                 delay(1);
  88.         }
  89.         I2c_getAck();
  90. }

  91. void I2c_toDevice(uchar deviceAdd,uchar datAdd,uchar dat)
  92. {
  93.         I2c_start();
  94.         I2c_write(deviceAdd);
  95.         I2c_write(datAdd);
  96.         I2c_write(dat);
  97.         I2c_stop();
  98. }
  99. uchar I2c_fromDevice(uchar deviceAdd,uchar datAdd  )
  100. {
  101.         uchar dat;
  102.         I2c_start();
  103.         I2c_write(deviceAdd);
  104.         I2c_write(datAdd);
  105.         I2c_start();
  106.         I2c_write(deviceAdd+1);
  107.         dat=I2c_read();
  108.         I2c_sendAck(1);
  109.         I2c_stop();
  110.         return dat;
  111. }

  112. void main()
  113. {
  114.         uchar num;
  115.         I2c_toDevice(0xa0,3,7);
  116.         delay(130);
  117.         num=I2c_fromDevice(0xa0,3);
  118.         while(1)
  119.         {
  120.                 P0=0x00;
  121.                 P1=duan[num];
  122.                 delay(10);
  123.                 P1=0x00;
  124.         }

  125. }
復(fù)制代碼

8、注意事項(xiàng)
1)關(guān)閉I2c和啟動(dòng)I2c之間要有1ms間隔,給IO口準(zhǔn)備時(shí)間,否則亂碼。
2)關(guān)于應(yīng)答,當(dāng)寫(xiě)數(shù)據(jù)時(shí)由設(shè)備應(yīng)答,讀數(shù)據(jù)時(shí)MCU應(yīng)答。
3)讀數(shù)據(jù)時(shí)啟動(dòng)兩次I2c。


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

使用道具 舉報(bào)

沙發(fā)
ID:74784 發(fā)表于 2018-3-24 22:14 | 只看該作者
有匯編代碼嗎?
回復(fù)

使用道具 舉報(bào)

板凳
ID:138443 發(fā)表于 2018-3-24 22:39 | 只看該作者
不錯(cuò),支持樓主,支持51hei
回復(fù)

使用道具 舉報(bào)

地板
ID:296886 發(fā)表于 2018-3-25 21:38 | 只看該作者
挺好的啊
回復(fù)

使用道具 舉報(bào)

5#
ID:200295 發(fā)表于 2021-4-14 17:52 | 只看該作者
剛好用到,謝謝樓主分享。
回復(fù)

使用道具 舉報(bào)

6#
ID:940533 發(fā)表于 2021-9-4 15:16 | 只看該作者
應(yīng)用代碼中void I2c_start()和void I2c_stop(),程序變的可運(yùn)行,好評(píng)
回復(fù)

使用道具 舉報(bào)

7#
ID:161164 發(fā)表于 2021-9-7 15:29 | 只看該作者
試了整天,Protues 里的I2C Debugger 都是收到A0 FF FF
看了其他文章才知道,等ACK時(shí)要先把SDA 置0
bit I2c_getAck(void)
{
    bit ack;        
    SDA = 0;//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<        
    SCL = 1;        
    delay(1);   
    ack = SDA;      
    SCL = 0;
    return ack;
}
回復(fù)

使用道具 舉報(bào)

8#
ID:997051 發(fā)表于 2024-4-6 02:53 | 只看該作者
//·¢Ëíack
void I2c_sendAck(bit ack)
{
    SDA = ack;      
    SCL = 1;      
    delay(1);   
    SCL = 0;


//»ñè¡ack
bit I2c_getAck(void)
{
    bit ack;        
    SDA = 1;        
    SCL = 1;   

什么意思?!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表