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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

怎么寫ii2c的協(xié)議,要注意些什么

[復(fù)制鏈接]
ID:386789 發(fā)表于 2018-10-9 14:49 | 顯示全部樓層 |閱讀模式
最近要做一個ii2c的從機協(xié)議程序,應(yīng)該怎么入手,初步想法是用外部中斷
回復(fù)

使用道具 舉報

ID:164602 發(fā)表于 2018-10-9 16:33 | 顯示全部樓層
個人理解:
IIC協(xié)議比較固定,可以找找別人的程序理解。當(dāng)然,如果自己想試試,也可以,寫好后看能不能用,能用最好,不能用,就對照別人的程序看看。
個人的經(jīng)驗:那個延時最不好搞!!!!!有的多一點延時就行不通,有的少了一點點也不行。發(fā)一個我最常用的IIC協(xié)議給你看看。
I2C.c程序:
#include"i2c.h"
/*******************************************************************************
* 函數(shù)名         : Delay1us()
* 函數(shù)功能                   : 延時
* 輸入           : 無
* 輸出                  : 無
*******************************************************************************/

void Delay10us()
{
        unsigned char a,b;
        for(b=1;b>0;b--)
                for(a=2;a>0;a--);

}
/*******************************************************************************
* 函數(shù)名         : I2cStart()
* 函數(shù)功能                   : 起始信號:在SCL時鐘信號在高電平期間SDA信號產(chǎn)生一個下降沿
* 輸入           : 無
* 輸出                  : 無
* 備注           : 起始之后SDA和SCL都為0
*******************************************************************************/

void I2cStart()
{
        SDA=1;
        Delay10us();
        SCL=1;
        Delay10us();//建立時間是SDA保持時間>4.7us
        SDA=0;
        Delay10us();//保持時間是>4us
        SCL=0;                       
        Delay10us();               
}
/*******************************************************************************
* 函數(shù)名         : I2cStop()
* 函數(shù)功能                   : 終止信號:在SCL時鐘信號高電平期間SDA信號產(chǎn)生一個上升沿
* 輸入           : 無
* 輸出                  : 無
* 備注           : 結(jié)束之后保持SDA和SCL都為1;表示總線空閑
*******************************************************************************/

void I2cStop()
{
        SDA=0;
        Delay10us();
        SCL=1;
        Delay10us();//建立時間大于4.7us
        SDA=1;
        Delay10us();               
}
/*******************************************************************************
* 函數(shù)名         : I2cSendByte(unsigned char num)
* 函數(shù)功能                   : 通過I2C發(fā)送一個字節(jié)。在SCL時鐘信號高電平期間,保持發(fā)送信號SDA保持穩(wěn)定
* 輸入           : num
* 輸出                  : 0或1。發(fā)送成功返回1,發(fā)送失敗返回0
* 備注           : 發(fā)送完一個字節(jié)SCL=0,SDA=1
*******************************************************************************/

unsigned char I2cSendByte(unsigned char dat)
{
        unsigned char a=0,b=0;//最大255,一個機器周期為1us,最大延時255us。               
        for(a=0;a<8;a++)//要發(fā)送8位,從最高位開始
        {
                SDA=dat>>7;         //起始信號之后SCL=0,所以可以直接改變SDA信號
                dat=dat<<1;
                Delay10us();
                SCL=1;
                Delay10us();//建立時間>4.7us
                SCL=0;
                Delay10us();//時間大于4us               
        }
        SDA=1;
        Delay10us();
        SCL=1;
        while(SDA)//等待應(yīng)答,也就是等待從設(shè)備把SDA拉低
        {
                b++;
                if(b>200)         //如果超過2000us沒有應(yīng)答發(fā)送失敗,或者為非應(yīng)答,表示接收結(jié)束
                {
                        SCL=0;
                        Delay10us();
                        return 0;
                }
        }
        SCL=0;
        Delay10us();
        return 1;               
}
/*******************************************************************************
* 函數(shù)名         : I2cReadByte()
* 函數(shù)功能                   : 使用I2c讀取一個字節(jié)
* 輸入           : 無
* 輸出                  : dat
* 備注           : 接收完一個字節(jié)SCL=0,SDA=1.
*******************************************************************************/

unsigned char I2cReadByte()
{
        unsigned char a=0,dat=0;
        SDA=1;                        //起始和發(fā)送一個字節(jié)之后SCL都是0
        Delay10us();
        for(a=0;a<8;a++)//接收8個字節(jié)
        {
                SCL=1;
                Delay10us();
                dat<<=1;
                dat|=SDA;
                Delay10us();
                SCL=0;
                Delay10us();
        }
        return dat;               
}
/*******************************************************************************
* 函數(shù)名         : I2cReadRespon()
* 函數(shù)功能                   : 接收完一個字節(jié)之后產(chǎn)生應(yīng)答,以便接著接收下一個字節(jié)
* 輸入           : 無
* 輸出                  : 無
* 備注           : 接收完一個字節(jié)SCL=0
*******************************************************************************/
//void I2cReadRespon()
//{
//        SDA=0;
//        Delay10us();
//        SDA=1;
//        Delay10us();
//}


I2C.H程序:
#ifndef __I2C_H_
#define __I2C_H_

#include<reg51.h>
sbit SCL=P2^1;
sbit SDA=P2^0;

void I2cStart();
void I2cStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
void I2cReadRespon();
#endif

這個程序,是用于24C02的,符合I2C協(xié)議的一般要求。
回復(fù)

使用道具 舉報

ID:23606 發(fā)表于 2018-10-9 16:46 | 顯示全部樓層
論壇里面很多,搜一下
回復(fù)

使用道具 舉報

ID:7485 發(fā)表于 2018-10-9 16:52 | 顯示全部樓層
ii2c協(xié)議是一種通信協(xié)議,凡是采用這種協(xié)議的器件,都是一定要按照這個協(xié)議(約定的時序)編寫程序。
回復(fù)

使用道具 舉報

ID:387733 發(fā)表于 2018-10-9 18:05 | 顯示全部樓層
論壇里主機協(xié)議的多,從機協(xié)議的不多,但是從機是主機的對手機,因此做從機協(xié)議可以多看看主機的。另外要搞通IIC的通訊協(xié)議的時序,根據(jù)時序?qū)懗绦颉?/td>
回復(fù)

使用道具 舉報

ID:386789 發(fā)表于 2018-10-9 18:06 | 顯示全部樓層
是從機協(xié)議,不是主機協(xié)議,在百度找了很久都沒有想關(guān)的協(xié)議,要怎么操作的時序圖
回復(fù)

使用道具 舉報

ID:246050 發(fā)表于 2018-10-9 19:18 | 顯示全部樓層
這個肯定是時序最要注意的啦
回復(fù)

使用道具 舉報

ID:387733 發(fā)表于 2018-10-9 19:36 | 顯示全部樓層
網(wǎng)上找來的,可能會有所幫助吧

/****************************************************************/
bit iic_start_decide()    //IIC 開始判斷
{
         while(SCL==0);                                       //開始不滿足條件
        while((SCL==1)&&(SDA==1));                 //開始條件
         if((SCL==1)&&(SDA==0))                               //開始
         {
          while(SCL==1);                                        //等待到時鐘開始低跳變
          return 1;
         }
         else
         return 0;
}

/****************************************************************/
bit iic_stop_decide()                        //IIC 結(jié)束判斷
{
        while(SCL==0);                                //結(jié)束不滿足條件
        if((SCL==1)&&(0==SDA))                        //結(jié)束
        {
          while(SDA==0);                                //等待到數(shù)據(jù)開始高跳變
          return 1;
         }
         else
         {
                 return 0;
        }
}
/****************************************************************/
uchar iic_receive()
{
         uchar i;
         uchar rdata='0';

         SDA=1;
         for(i=0;i<8;i++)
         {
          rdata<<=1;
          while(SCL==0);        //當(dāng)時鐘為低時,數(shù)據(jù)無效,等待
          if(SDA==1)
                  rdata++;
          while(SCL==1);        //防止在一個高電平時讀8次
         }
        return (rdata);
}
/****************************************************************/
bit iic_ack_decide()
{
        bit ack_flag;                //局部變量
        SDA=0;                                        ////8位發(fā)送完畢,釋放數(shù)據(jù)線SDA,準(zhǔn)備接收應(yīng)答位
        while(SCL==0);        //等待SCL變高電平
        //ack_flag=0;
        while(SCL==1);        //等待SCL變高電平
        SDA=1;
        ack_flag=1;
        return(ack_flag);
}
回復(fù)

使用道具 舉報

ID:390615 發(fā)表于 2018-10-9 21:22 | 顯示全部樓層
兄弟,你研究到了嗎?我近來也在做這個,聽說從機的時序是很難模擬的
回復(fù)

使用道具 舉報

ID:386789 發(fā)表于 2018-10-10 09:28 | 顯示全部樓層
sxhwdz 發(fā)表于 2018-10-9 19:36
網(wǎng)上找來的,可能會有所幫助吧

/****************************************************************/

謝謝,哥們
回復(fù)

使用道具 舉報

ID:386789 發(fā)表于 2018-10-10 09:29 | 顯示全部樓層
authority 發(fā)表于 2018-10-9 21:22
兄弟,你研究到了嗎?我近來也在做這個,聽說從機的時序是很難模擬的

兄弟,一起研究一下,我打算先用外部中斷來調(diào)試
回復(fù)

使用道具 舉報

ID:155507 發(fā)表于 2018-10-10 10:54 | 顯示全部樓層
你可以用STC8,有硬件I2C。
硬件I2C只要把數(shù)據(jù)送到指定的寄存器就可以了,不用自己寫時序什么的。

  1. /* I2C從機模式(查詢方式) */
  2. // 芯片型號 : STC8A8K64S4A12

  3. #include "reg51.h"
  4. #include "intrins.h"

  5. sfr     P_SW2       =   0xba;

  6. #define I2CCFG          (*(unsigned char volatile xdata *)0xfe80)
  7. #define I2CMSCR         (*(unsigned char volatile xdata *)0xfe81)
  8. #define I2CMSST         (*(unsigned char volatile xdata *)0xfe82)
  9. #define I2CSLCR         (*(unsigned char volatile xdata *)0xfe83)
  10. #define I2CSLST         (*(unsigned char volatile xdata *)0xfe84)
  11. #define I2CSLADR        (*(unsigned char volatile xdata *)0xfe85)
  12. #define I2CTXD          (*(unsigned char volatile xdata *)0xfe86)
  13. #define I2CRXD          (*(unsigned char volatile xdata *)0xfe87)

  14. sbit    SDA         =   P1^4;
  15. sbit    SCL         =   P1^5;

  16. bit isda;                                       //設(shè)備地址標(biāo)志
  17. bit isma;                                       //存儲地址標(biāo)志
  18. unsigned char addr;
  19. unsigned char pdata buffer[256];

  20. void main()
  21. {
  22.     P_SW2 = 0x80;

  23.     I2CCFG = 0x81;                              //使能I2C從機模式
  24.     I2CSLADR = 0x5a;                            //設(shè)置從機設(shè)備地址為5A
  25.     I2CSLST = 0x00;
  26.     I2CSLCR = 0x00;                             //禁止從機模式中斷

  27.     isda = 1;                                   //用戶變量初始化
  28.     isma = 1;
  29.     addr = 0;
  30.     I2CTXD = buffer[addr];

  31.     while (1)
  32.     {
  33.         if (I2CSLST & 0x40)
  34.         {
  35.             I2CSLST &= ~0x40;                   //處理START事件
  36.         }
  37.         else if (I2CSLST & 0x20)
  38.         {
  39.             I2CSLST &= ~0x20;                   //處理RECV事件
  40.             if (isda)
  41.             {
  42.                 isda = 0;                       //處理RECV事件(RECV DEVICE ADDR)
  43.             }
  44.             else if (isma)
  45.             {
  46.                 isma = 0;                       //處理RECV事件(RECV MEMORY ADDR)
  47.                 addr = I2CRXD;
  48.                 I2CTXD = buffer[addr];
  49.             }
  50.             else
  51.             {
  52.                 buffer[addr++] = I2CRXD;        //處理RECV事件(RECV DATA)
  53.             }
  54.         }
  55.         else if (I2CSLST & 0x10)
  56.         {
  57.             I2CSLST &= ~0x10;                   //處理SEND事件
  58.             if (I2CSLST & 0x02)
  59.             {
  60.                 I2CTXD = 0xff;
  61.             }
  62.             else
  63.             {
  64.                 I2CTXD = buffer[++addr];
  65.             }
  66.         }
  67.         else if (I2CSLST & 0x08)
  68.         {
  69.             I2CSLST &= ~0x08;                   //處理STOP事件
  70.             isda = 1;
  71.             isma = 1;
  72.         }
  73.     }
  74. }


復(fù)制代碼
回復(fù)

使用道具 舉報

ID:155507 發(fā)表于 2018-10-10 10:56 | 顯示全部樓層
  1. //芯片型號 : STC8A8K64S4A12
  2. //STC8單片機 I2C從機模式(中斷方式)

  3. #include "reg51.h"
  4. #include "intrins.h"

  5. sfr     P_SW2       =   0xba;

  6. #define I2CCFG          (*(unsigned char volatile xdata *)0xfe80)
  7. #define I2CMSCR         (*(unsigned char volatile xdata *)0xfe81)
  8. #define I2CMSST         (*(unsigned char volatile xdata *)0xfe82)
  9. #define I2CSLCR         (*(unsigned char volatile xdata *)0xfe83)
  10. #define I2CSLST         (*(unsigned char volatile xdata *)0xfe84)
  11. #define I2CSLADR        (*(unsigned char volatile xdata *)0xfe85)
  12. #define I2CTXD          (*(unsigned char volatile xdata *)0xfe86)
  13. #define I2CRXD          (*(unsigned char volatile xdata *)0xfe87)

  14. sbit    SDA         =   P1^4;
  15. sbit    SCL         =   P1^5;

  16. bit isda;                                       //設(shè)備地址標(biāo)志
  17. bit isma;                                       //存儲地址標(biāo)志
  18. unsigned char addr;
  19. unsigned char pdata buffer[256];

  20. void I2C_Isr() interrupt 24 using 1
  21. {
  22.     _push_(P_SW2);
  23.     P_SW2 |= 0x80;

  24.     if (I2CSLST & 0x40)
  25.     {
  26.         I2CSLST &= ~0x40;                       //處理START事件
  27.     }
  28.     else if (I2CSLST & 0x20)
  29.     {
  30.         I2CSLST &= ~0x20;                       //處理RECV事件
  31.         if (isda)
  32.         {
  33.             isda = 0;                           //處理RECV事件(RECV DEVICE ADDR)
  34.         }
  35.         else if (isma)
  36.         {
  37.             isma = 0;                           //處理RECV事件(RECV MEMORY ADDR)
  38.             addr = I2CRXD;
  39.             I2CTXD = buffer[addr];
  40.         }
  41.         else
  42.         {
  43.             buffer[addr++] = I2CRXD;            //處理RECV事件(RECV DATA)
  44.         }
  45.     }
  46.     else if (I2CSLST & 0x10)
  47.     {
  48.         I2CSLST &= ~0x10;                       //處理SEND事件
  49.         if (I2CSLST & 0x02)
  50.         {
  51.             I2CTXD = 0xff;
  52.         }
  53.         else
  54.         {
  55.             I2CTXD = buffer[++addr];
  56.         }
  57.     }
  58.     else if (I2CSLST & 0x08)
  59.     {
  60.         I2CSLST &= ~0x08;                       //處理STOP事件
  61.         isda = 1;
  62.         isma = 1;
  63.     }

  64.     _pop_(P_SW2);
  65. }

  66. void main()
  67. {
  68.     P_SW2 = 0x80;

  69.     I2CCFG = 0x81;                              //使能I2C從機模式
  70.     I2CSLADR = 0x5a;                            //設(shè)置從機設(shè)備地址為5A
  71.     I2CSLST = 0x00;
  72.     I2CSLCR = 0x78;                             //使能從機模式中斷
  73.     EA = 1;

  74.     isda = 1;                                   //用戶變量初始化
  75.     isma = 1;
  76.     addr = 0;
  77.     I2CTXD = buffer[addr];

  78.     while (1);
  79. }

復(fù)制代碼
回復(fù)

使用道具 舉報

ID:155507 發(fā)表于 2018-10-10 10:57 | 顯示全部樓層
  1. //芯片型號 : STC8A8K64S4A12
  2. //STC8單片機 測試I2C從機模式代碼的主機代碼

  3. #include "reg51.h"
  4. #include "intrins.h"

  5. sfr     P_SW2       =   0xba;

  6. #define I2CCFG          (*(unsigned char volatile xdata *)0xfe80)
  7. #define I2CMSCR         (*(unsigned char volatile xdata *)0xfe81)
  8. #define I2CMSST         (*(unsigned char volatile xdata *)0xfe82)
  9. #define I2CSLCR         (*(unsigned char volatile xdata *)0xfe83)
  10. #define I2CSLST         (*(unsigned char volatile xdata *)0xfe84)
  11. #define I2CSLADR        (*(unsigned char volatile xdata *)0xfe85)
  12. #define I2CTXD          (*(unsigned char volatile xdata *)0xfe86)
  13. #define I2CRXD          (*(unsigned char volatile xdata *)0xfe87)

  14. sbit    SDA         =   P1^4;
  15. sbit    SCL         =   P1^5;

  16. void Wait()
  17. {
  18.     while (!(I2CMSST & 0x40));
  19.     I2CMSST &= ~0x40;
  20. }

  21. void Start()
  22. {
  23.     I2CMSCR = 0x01;                             //發(fā)送START命令
  24.     Wait();
  25. }

  26. void SendData(char dat)
  27. {
  28.     I2CTXD = dat;                               //寫數(shù)據(jù)到數(shù)據(jù)緩沖區(qū)
  29.     I2CMSCR = 0x02;                             //發(fā)送SEND命令
  30.     Wait();
  31. }

  32. void RecvACK()
  33. {
  34.     I2CMSCR = 0x03;                             //發(fā)送讀ACK命令
  35.     Wait();
  36. }

  37. char RecvData()
  38. {
  39.     I2CMSCR = 0x04;                             //發(fā)送RECV命令
  40.     Wait();
  41.     return I2CRXD;
  42. }

  43. void SendACK()
  44. {
  45.     I2CMSST = 0x00;                             //設(shè)置ACK信號
  46.     I2CMSCR = 0x05;                             //發(fā)送ACK命令
  47.     Wait();
  48. }

  49. void SendNAK()
  50. {
  51.     I2CMSST = 0x01;                             //設(shè)置NAK信號
  52.     I2CMSCR = 0x05;                             //發(fā)送ACK命令
  53.     Wait();
  54. }

  55. void Stop()
  56. {
  57.     I2CMSCR = 0x06;                             //發(fā)送STOP命令
  58.     Wait();
  59. }

  60. void Delay()
  61. {
  62.     int i;

  63.     for (i=0; i<3000; i++)
  64.     {
  65.         _nop_();
  66.         _nop_();
  67.         _nop_();
  68.         _nop_();
  69.     }
  70. }

  71. void main()
  72. {
  73.     P_SW2 = 0x80;

  74.     I2CCFG = 0xe0;                              //使能I2C主機模式
  75.     I2CMSST = 0x00;

  76.     Start();                                    //發(fā)送起始命令
  77.     SendData(0x5a);                             //發(fā)送設(shè)備地址+寫命令
  78.     RecvACK();
  79.     SendData(0x00);                             //發(fā)送存儲地址
  80.     RecvACK();
  81.     SendData(0x12);                             //寫測試數(shù)據(jù)1
  82.     RecvACK();
  83.     SendData(0x78);                             //寫測試數(shù)據(jù)2
  84.     RecvACK();
  85.     Stop();                                     //發(fā)送停止命令

  86.     Start();                                    //發(fā)送起始命令
  87.     SendData(0x5a);                             //發(fā)送設(shè)備地址+寫命令
  88.     RecvACK();
  89.     SendData(0x00);                             //發(fā)送存儲地址高字節(jié)
  90.     RecvACK();
  91.     Start();                                    //發(fā)送起始命令
  92.     SendData(0x5b);                             //發(fā)送設(shè)備地址+讀命令
  93.     RecvACK();
  94.     P0 = RecvData();                            //讀取數(shù)據(jù)1
  95.     SendACK();
  96.     P2 = RecvData();                            //讀取數(shù)據(jù)2
  97.     SendNAK();
  98.     Stop();                                     //發(fā)送停止命令

  99.     P_SW2 = 0x00;

  100.     while (1);
  101. }

復(fù)制代碼
回復(fù)

使用道具 舉報

ID:386789 發(fā)表于 2018-10-10 13:43 | 顯示全部樓層
回復(fù)

使用道具 舉報

ID:390615 發(fā)表于 2018-10-28 10:06 | 顯示全部樓層

我也覺得總不能依賴stc提供的硬件i2c,自己需要懂得模擬才是萬全之策
回復(fù)

使用道具 舉報

ID:275111 發(fā)表于 2020-4-1 10:45 | 顯示全部樓層
我在網(wǎng)上找了下,鍵盤IC一般實際上是3線制,I2C 2根,中斷1根。  現(xiàn)在就是要求只用I2C來做從機。感覺無從下手。
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 羞羞视频在线网站观看 | 伊人网站 | 伊人网在线综合 | 在线一区观看 | 三级国产三级在线 | 自拍偷拍第一页 | 免费av直接看 | 国产成人精品综合 | 国产精品区二区三区日本 | 4hu最新网址 | 久久com| 国产成人在线一区 | 国产四虎 | 日韩欧美二区 | 国产精品国产a级 | 九九在线视频 | 国产午夜视频 | 国产精品美女久久久久久久网站 | 五月天综合网 | 国产成人在线一区 | 久久精品视频一区二区三区 | 亚洲国产乱码 | 日韩精品一区二区三区久久 | 91操操操| 一本大道久久a久久精二百 欧洲一区二区三区 | 日韩欧美在线一区 | 狠狠视频| 日韩激情视频一区 | 久久精品久久久久久 | 羞羞视频在线观看免费观看 | 亚洲xx在线 | av网站在线免费观看 | 午夜影院网站 | 91中文| www日韩欧美 | 少妇性l交大片免费一 | 午夜av电影 | 在线看成人av | 日本精品一区二区三区在线观看视频 | a久久| 日韩高清www |