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

QQ登錄

只需一步,快速開始

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

注釋很詳細(xì)的IIC做從機(jī)發(fā)送數(shù)據(jù)源程序

  [復(fù)制鏈接]
ID:613800 發(fā)表于 2019-12-23 11:42 | 顯示全部樓層 |閱讀模式
感覺寫的很好,有參考價(jià)值,畢竟寫主發(fā)從列程很多。從發(fā)主列程是真的少

單片機(jī)源程序如下:
  1. /*************        用戶系統(tǒng)配置        **************/

  2. #define MAIN_Fosc                12000000L        //定義主時(shí)鐘, 模擬串口和紅外接收會(huì)自動(dòng)適應(yīng)。5~36MHZ

  3. #define D_TIMER0                125                        //選擇定時(shí)器時(shí)間, us, 紅外接收要求在60us~250us之間

  4. #define        User_code                0xFD02                //定義紅外接收用戶碼
  5. #define DECVICE_ADD 0x55<<1

  6. /*************        以下宏定義用戶請(qǐng)勿修改        **************/
  7. #include        "reg51.H"
  8. #include        "string.H"

  9. #define        uchar        unsigned char
  10. #define uint        unsigned int

  11. //#define freq_base                        (MAIN_Fosc / 1200)
  12. //#define Timer0_Reload                (65536 - (D_TIMER0 * freq_base / 10000))




  13. /*************        本地常量聲明        **************/



  14. /*************        本地變量聲明        **************/
  15. sbit        SDA = P3^0;                //SDA
  16. sbit        SCL = P3^1;                //SCL

  17. bit                PreState;               
  18. bit                NowState;
  19. bit     START_flag;
  20. bit     STOP_flag;               
  21. //uchar        IR_SampleCnt;                //采樣計(jì)數(shù)
  22. uchar NN;
  23. uchar DEVICE_ADR;        //器件地址
  24. uchar WORD_ADR;                //內(nèi)存地址
  25. uchar REC_DATA;                //接收到的內(nèi)容
  26. unsigned int  *send_ptr;//
  27. code unsigned AA0[9] = {0x70,0x2c,0x6e,0x2a,0x00,0x00,0x00,0xc0};  //
  28. code unsigned AA8[2] = {0xff,0x2c};  //
  29. //code unsigned AA0[9] = {0x70,0x2c,0x6e,0x2a,0x00,0x00,0x00,0xc0};  //
  30. code unsigned A00[33] = {0xed,0xcf,0x48,0xe6,0x89,0xe8,0x0c,0xe8,
  31.                                              0x97,0xaf,0xd2,0x40,0x6d,0xc2,0xc4,0x04,
  32.                                                  0xca,0xd5,0xea,0xa7,0xae,0x43,0x37,0xe2,
  33.                                                  0x12,0x05,0x3b,0x59,0xb7,0xfb,0x3d,0xa5
  34.                                                  };  //
  35. code unsigned A20[33] = {0xCB,0x85,0x8b,0x54,0x6d,0x97,0x3c,0x05,
  36.                          0x46,0x0f,0x45,0xb4,0xd1,0x0a,0xb8,0x9b,
  37.                                                  0xdf,0xa2,0x43,0x8d,0xe6,0x7a,0x6f,0xf8,
  38.                                                  0x7f,0xaa,0x52,0x37,0xa6,0x8f,0xdc,0x71
  39.                         
  40.                                                 };  //
  41. code unsigned A40[33] = {
  42.                          0x15,0x67,0xc5,0x82,0xfe,0x01,0x87,0x44,
  43.                                                  0x10,0xcd,0xf8,0xe2,0xd7,0xb1,0x7d,0xb6,
  44.                                                  0x53,0xc0,0x43,0x39,0x3a,0xb3,0x32,0xba,
  45.                                                  0x5d,0x84,0xf1,0x03,0x13,0xcd,0x74,0x28

  46.                                                 };  //
  47. code unsigned A60[33] = {
  48.                          0x34,0x39,0xab,0x32,0x3b,0x32,0x76,0x4b,
  49.                                                  0xff,0x6f,0x2d,0xd6,0x20,0xab,0x8c,0x73,
  50.                                                  0x6b,0xd0,0xad,0xa6,0x83,0xdf,0x60,0xe0,
  51.                                                  0x63,0x51,0xe4,0x76,0x1e,0x58,0x9f,0x52
  52.                                                
  53.                                                 };  //


  54. uchar temp;






  55. /*************  外部函數(shù)和變量聲明 *****************/
  56. void init(void);//初如化函數(shù)
  57. void delay_24C02(void); // 延時(shí) 5us
  58. void ACK(void);//應(yīng)答
  59. void WaitACK(void);//等待主機(jī)回復(fù)

  60. /********************* 主函數(shù) *************************/
  61. void main(void)
  62. {
  63.   uchar gg,MM,i,count;
  64.   init();//初如化

  65.   while(1)
  66.    {
  67.          NN=50;
  68.          PreState = SDA;         
  69.          while(SCL && NN--)
  70.           {
  71.                 NowState = SDA;
  72.                 if(PreState && !NowState) //啟動(dòng)
  73.                  {
  74.                     START_flag = 1;
  75.                     //_DINT();
  76.                  }
  77.                 if(!PreState && NowState) //結(jié)束
  78.                  {
  79.                 STOP_flag = 1;
  80.                     //_EINT();
  81.                  }
  82.                 PreState = NowState;

  83.                 if(START_flag) //如果是啟動(dòng)的話
  84.                  {
  85.                         START_flag=0;
  86.                         while(SCL); //START時(shí)的SCL高電平狀態(tài)就等待
  87.                         for(gg=8;gg>0;gg--) //接收器件地址
  88.                      {
  89.                                 while(!SCL); //SCL低電平狀態(tài)就等待
  90.                                
  91.                                 DEVICE_ADR<<=1;
  92.                                 if(SDA) //數(shù)據(jù)的第一個(gè)CLK高電平來臨
  93.                                 DEVICE_ADR |= 0x01;
  94.                                
  95.                                 while(SCL); //SCL高電平狀態(tài)就等待
  96.                          }

  97.                         ACK(); //對(duì)設(shè)備地址ACK應(yīng)答信
  98.                 //-----------以上收到了設(shè)備地址,并知曉主機(jī)要對(duì)從機(jī)進(jìn)行讀還是寫操作---
  99.                     for(gg=8;gg>0;gg--) //接收內(nèi)存單元地址
  100.                          {
  101.                            while(!SCL);
  102.                                
  103.                                 WORD_ADR<<=1;
  104.                                 if(SDA)
  105.                                 WORD_ADR |= 0x01;
  106.                                
  107.                                 while(SCL);
  108.                          }
  109.                         //-----------以上就已經(jīng)接收到內(nèi)存單元地址------------
  110.                         ACK(); //對(duì)內(nèi)存單元ACK應(yīng)答信號(hào)

  111.                         //--------------------- 以上就已經(jīng)接收到內(nèi)存單元地址 -------------------------
  112.                         delay_24C02();//5us
  113.                         delay_24C02();
  114.                         delay_24C02();//5us
  115.                         delay_24C02();
  116.                         MM=50;
  117.                         PreState = SDA;
  118.                         while(SCL && MM--)
  119.                          {
  120.                                 NowState = SDA;
  121.                                 if(PreState && !NowState) // 如果 SDA 下降沿且 SCL 為高 , 則示開始信號(hào)
  122.                                 {
  123.                                    START_flag = 1;
  124.                                 }
  125.                          }

  126.                         //--------------------START_Flag=1: 表示隨即讀數(shù)據(jù) -------------------------
  127.                         if(START_flag==1)
  128.                         {
  129.                                 //--------------------------- 讀取器件地址 ---------------------------------
  130.                                 //while(!SCL);
  131.                                 START_flag=0; // 清除標(biāo)志位
  132.                                 while(SCL); //START 時(shí)的 SCL 高電平狀態(tài)就等待
  133.                                 for(gg=8;gg>0;gg--) // 接收器件地址
  134.                                 {
  135.                                         while(!SCL); //SCL 低電平狀態(tài)就等待
  136.                                          DEVICE_ADR<<=1; // 高位在前
  137.                                         if(SDA) // 數(shù)據(jù)的第一個(gè) CLK 高電平來臨
  138.                                          DEVICE_ADR |= 0x01; // 上升沿讀取數(shù)據(jù)位
  139.                                         while(SCL); //SCL 高電平狀態(tài)就等待
  140.                                 }
  141.                                 ACK(); // 對(duì)設(shè)備地址 ACK 應(yīng)答信

  142.        
  143.                  

  144.                                 //------------------ 判斷地址是否為 0xa1 ,表示讀數(shù)據(jù)指令 -------------------
  145.                                 if(DEVICE_ADR == 0xab)           //( DECVICE_ADD+1)
  146.                                 {
  147.                        
  148.                                         switch(WORD_ADR)
  149.                                      {
  150.                                                 case 0xa0:  count=8; send_ptr =AA0;        //                  memcpy(temp,AA0,count);
  151.                                               break;
  152.                                             case 0xa8:  count=1; send_ptr =AA8;        //            memcpy(temp,AA8,count);
  153.                                                          break;
  154.                                                 case 0x00:  count=32; send_ptr =A00; //  memcpy(temp,A00,count);
  155.                                                          break;
  156.                                                 case 0x20:  count=32; send_ptr =A20;//  memcpy(temp,A20,count);
  157.                                                          break;
  158.                                                 case 0x40:  count=32; send_ptr =A40; //                  memcpy(temp,A40,count);
  159.                                                          break;
  160.                                                 case 0x60:  count=32; send_ptr =A60;//        /          memcpy(temp,A60,count);
  161.                                                          break;
  162.                                                  
  163.                                          }
  164.                                                                                
  165.                                         for(i=0;i<count;i++) // 要 讀 多 少 字 節(jié) , 由
  166.                                         {
  167.                                             //*send_ptr =WORD_ADR;
  168.                                                 temp = send_ptr[i];
  169.                                                 for(gg=8;gg>0;gg--) // 輸出數(shù)據(jù)給主機(jī)
  170.                                                 {
  171.                                                         while(SCL);//如果為高,保持
  172.                                                         if( temp & 0x80)
  173.                                                          {
  174.                                                                 SDA=1; // 輸出 1
  175.                                                          }
  176.                                                         else
  177.                                                          {
  178.                                                                 SDA=0; // 輸出 0
  179.                                                          }
  180.                                                         while(!SCL);
  181.                                                         //while(SCL); //SCL 為 1 ,就保持 SDA 輸出不變
  182.                                                     //  SDA=1;
  183.                                                         //*send_ptr <<=1;
  184.                                                         temp <<=1;
  185.                                                 }
  186.                                            WaitACK();//主機(jī)回復(fù)ACK
  187.                                            //send_ptr++;
  188.                                         }

  189.                                     
  190.                                 }//if(DEVICE_ADR==0xa1)
  191.                                 else  //如果不是,退出
  192.                                 {
  193.                                   
  194.                                 }
  195.                         }//if(START_flag==1)
  196.                         else // 如果 START_flag!=1 則表示主機(jī)對(duì)從機(jī)進(jìn)行寫操作
  197.                         {       
  198.                             if(WORD_ADR == 0xa9)
  199.                              {
  200.                                         for(i=0;i<8;i++)
  201.                                         {
  202.                                                 for(gg=8;gg>0;gg--) // 讀取主機(jī)發(fā)來的數(shù)據(jù)
  203.                                                 {
  204. //                                                        while(!SCL);
  205. //                                                         //READ_BUF[i] <<=1;
  206. //                                                         //SDA=0;
  207. //                                                        if(SDA)
  208. //                                                         ;
  209. //                                                         //READ_BUF[i] |= 0x01;
  210. //                                                         //SDA=0;
  211. //                                                        while(SCL);
  212.                                                   
  213.                                                    while(!SCL);
  214.                                                                                                   
  215.                                                         while(SCL);

  216.                                                 }
  217.                                                
  218.                                                 ACK(); // 對(duì)設(shè)備地址 ACK 應(yīng)答信
  219.                                     }                                 
  220.                                  
  221.                                  }


  222.                      }





  223.           }// if(START_flag)


  224.           }//end while(SCL && NN--)


  225.    }//end while(1)
  226. }

  227. /********************************************************************
  228. 函數(shù)功能:初始化函數(shù)
  229. 入口參數(shù):無(wú)
  230. 返 回:無(wú)。
  231. 備 注:無(wú)。
  232. ********************************************************************/
  233. void init(void)
  234. {
  235.         SDA=1; // 初始數(shù)據(jù)引腳
  236.         SCL=1; // 初始時(shí)鐘引腳
  237. //        EA=1; // 開總中斷
  238. //        IP=0x90; // 中斷優(yōu)先級(jí)設(shè)定,設(shè)為串口 >INTO>T0>INT1>T1
  239. //        EX0=1; // 開外部中斷 0
  240. }

  241. /********************************************************************
  242. 函數(shù)功能:從機(jī)應(yīng)答函數(shù)
  243. 入口參數(shù):無(wú)
  244. 返 回:無(wú)。
  245. 備 注:應(yīng)答函數(shù),保證在兩個(gè)時(shí)鐘跳變沿 SDA 為低,則主機(jī)認(rèn)為是從機(jī)應(yīng)答
  246. ********************************************************************/
  247. void ACK(void)
  248. {
  249. //        while(!SCL);
  250. //        SDA=0; // 第 9 個(gè) CLK 變高的情況下, SDA 輸出 0
  251. //        while(SCL);
  252. //        SDA=1; // 第 9 個(gè) CLK 變低的情況下, SDA 輸出 1

  253.         while(SCL); //低就阻塞
  254.         delay_24C02();
  255.         SDA=0; // 第 9 個(gè) CLK 變高的情況下, SDA 輸出 0
  256.         while(!SCL); //低就阻塞
  257.         while(SCL);         //高就阻塞
  258.         delay_24C02();
  259.         SDA=1; // 第 9 個(gè) CLK 變低的情況下, SDA 輸出 1


  260. }


  261. /********************************************************************
  262. 函數(shù)功能:主機(jī)應(yīng)答函數(shù)
  263. 入口參數(shù):無(wú)
  264. 返 回:無(wú)。
  265. 備 注:應(yīng)答函數(shù),保證在兩個(gè)時(shí)鐘跳變沿 SDA 為低,則主機(jī)認(rèn)為是從機(jī)應(yīng)答
  266. ********************************************************************/
  267. void WaitACK(void)
  268. {
  269. //        while(!SCL);
  270. //        SDA=0; // 第 9 個(gè) CLK 變高的情況下, SDA 輸出 0
  271. //        while(SCL);
  272. //        SDA=1; // 第 9 個(gè) CLK 變低的情況下, SDA 輸出 1

  273.         while(SCL); //高就阻塞
  274.         delay_24C02();
  275.         SDA=1; // 第 9 個(gè) CLK 變高的情況下, SDA 輸出 0
  276.         while(!SCL); //低就阻塞
  277.         while(SCL);         //高就阻塞
  278.         delay_24C02();
  279.         //SDA=1; // 第 9 個(gè) CLK 變低的情況下, SDA 輸出 1


  280. }
  281. /********************************************************************
  282. 函數(shù)功能:延時(shí) us
  283. 入口參數(shù):無(wú)
  284. 返 回:無(wú)。
  285. 備 注:函數(shù)是用來實(shí)現(xiàn)短暫延時(shí),用于對(duì)接上主機(jī)時(shí)鐘
  286. ********************************************************************/
  287. void delay_24C02(void) // 延時(shí) 5us
  288. {
  289. //; ; ; ; ;
  290. uchar i;
  291. i=3;
  292. while(i--);
  293. }
復(fù)制代碼

所有資料51hei提供下載:
IICSTC2.rar (40.35 KB, 下載次數(shù): 178)


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:241627 發(fā)表于 2022-10-11 17:48 | 顯示全部樓層
感謝分享,試試看能不能行
回復(fù)

使用道具 舉報(bào)

ID:824308 發(fā)表于 2022-10-16 14:46 | 顯示全部樓層
看起來感覺不錯(cuò), 感謝分享.
回復(fù)

使用道具 舉報(bào)

ID:160197 發(fā)表于 2022-10-17 15:01 | 顯示全部樓層
現(xiàn)在的MCU都集成了硬件IIC功能。實(shí)際工程都用硬件的IIC。
回復(fù)

使用道具 舉報(bào)

ID:84492 發(fā)表于 2024-9-4 22:21 | 顯示全部樓層
找了很久,自己調(diào)一直不通,多謝
回復(fù)

使用道具 舉報(bào)

ID:149799 發(fā)表于 2024-9-5 09:01 | 顯示全部樓層
謝謝樓主,這個(gè)程序即解決了問題,又給初學(xué)者提供了學(xué)習(xí)的興趣,注釋的比較詳細(xì)。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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