找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2388|回复: 2
收起左侧

I2C通信ID自动查找,读写器制作 附单片机程序+仿真电路图

[复制链接]
ID:282074 发表于 2020-2-23 20:43 | 显示全部楼层 |阅读模式
本帖最后由 ksljxxq 于 2020-2-24 14:13 编辑

    I2C通信ID自动查找,在维修时碰到I2C通信要找ID地址也很麻烦,我们常用的比如24Cxx系列,显示屏通信,一般都是信号SDA与SCL,本主板用的主控芯片是stc15f2k60s2,编码开关,1602显示屏,二个按钮,编码开关按钮是移动光标,见下图24C测试ID 0XA0,TW8816测试ID 0X8A读写都正常,在i2c压缩包是程序和仿真

制作出来的实物图如下:
IMG_20200223_183218.jpg IMG_20200223_183521.jpg IMG_20200223_183505.jpg IMG_20200223_183206.jpg IMG_20200223_164345.jpg

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei截图.png

单片机源程序如下:
  1. #include<reg51.h>      
  2. #include<intrins.h>  
  3. #define uchar unsigned char
  4. #define uint unsigned int //函数声明
  5. #define yh 0x80    //第1行+3位数显示
  6. uint yi,ra,si,ra1,si1;
  7. void Init_Timer0(void);
  8. sbit  rs=P1^0;
  9. sbit  rw=P1^1;
  10. sbit  en=P1^2;

  11. sbit k3=P3^4;          //光标  
  12. sbit k1=P3^2;        //读开关
  13. sbit k2=P3^3;        //检测地址
  14. sbit CodingsWitch_B=P3^5; //A脚定义(即1脚) 这两脚必须接10K上拉电阻
  15. sbit CodingsWitch_A=P3^6; //B脚定义(即3脚?

  16. sbit SCL=P2^7;    //24c02  6
  17. sbit SDA=P2^6;          //       5
  18. void delay()
  19. {;;}
  20. void delay1(uint z)//延时为 1ms
  21. {
  22.   uchar x,x1;
  23.   for(;z>0;z--)
  24.   {
  25.    for(x=0;x<114;x++)
  26.     {
  27.     for(x1=0;x1<1;x1++);
  28.     }
  29.    }
  30. }

  31. write_1602com(uchar com)//****液晶写入指令函数****
  32. {
  33.         rs=0;//数据/指令选择置为指令
  34.         rw=0;
  35.         P0=com;//送入数据
  36.         delay1(1);
  37.         en=1;//拉高使能端,为制造有效的下降沿做准备
  38.         delay1(1);
  39.         en=0;//en由高变低,产生下降沿,液晶执行命令
  40. }

  41. write_1602dat(uchar dat)//***液晶写入数据函数****
  42. {
  43.         rs=1;//数据/指令选择置为数据
  44.         rw=0;
  45.         P0=dat;//送入数据
  46.         delay1(1);
  47.         en=1; //en置高电平,为制造下降沿做准备
  48.         delay1(1);
  49.         en=0; //en由高变低,产生下降沿,液晶执行命令
  50. }


  51. lcd_init()//***液晶初始化函数****
  52. {
  53.         write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
  54.         write_1602com(0x0c);//开显示不显示光标
  55.         write_1602com(0x06);//整屏不移动,光标自动右移
  56.         write_1602com(0x01);//清显示
  57. }


  58. void dsplay()
  59. {
  60.            if(xianshi==0)
  61.                         {               
  62.                                 unsigned int c, d;
  63.         //          a = (WriteDeviceAddress/256)/16; //    16进制千位
  64.         //    b = (WriteDeviceAddress/256)%16; //          百位
  65.                                 c = (WriteDeviceAddress%256)/16; //           十位
  66.                                 d = (WriteDeviceAddress%256)%16; //           个位
  67.                
  68.                                 write_1602com(yh);//指定显示
  69.                                 write_1602dat('I'); //
  70.                                 write_1602dat('D'); //
  71.                                 write_1602dat(':'); //
  72.                                 write_1602dat('0'); //
  73.                                 write_1602dat('x'); //
  74.                                 write_1602dat(hex_table[c]);    //
  75.                                 write_1602dat(hex_table[d]);    //
  76.                         }
  77.                         if(xianshi==1)
  78.                         {
  79.                           uchar a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1;
  80.                                 a = (yi%256)/16; //           十位
  81.                                 b = (yi%256)%16; //           个位
  82.                                 c = (ra%256)/16; //           十位
  83.                                 d = (ra%256)%16; //           个位
  84.                                 e = (yi+1%256)/16; //          十位
  85.                                 f = (yi+1%256)%16; //          个位
  86.                                 g = (si%256)/16; //           十位
  87.                                 h = (si%256)%16; //           个位
  88.                                 a1 = (yi+2%256)/16; //           十位
  89.                                 b1 = (yi+2%256)%16; //           个位
  90.                                 c1 = (ra1%256)/16; //           十位
  91.                                 d1 = (ra1%256)%16; //           个位
  92.                                 e1 = (yi+3%256)/16; //          十位
  93.                                 f1 = (yi+3%256)%16; //          个位
  94.                                 g1 = (si1%256)/16; //           十位
  95.                                 h1 = (si1%256)%16; //           个位
  96.                                 write_1602com(yh);//指定显示
  97.                                 write_1602dat('0');
  98.                                 write_1602dat('x');
  99.                                 write_1602dat(hex_table[a]);    //
  100.                                 write_1602dat(hex_table[b]);    //
  101.                                 write_1602dat(',');
  102.                                 write_1602dat(hex_table[c]);    //
  103.                                 write_1602dat(hex_table[d]);    //
  104.                                 write_1602dat(' ');
  105.                                 write_1602dat('0');
  106.                                 write_1602dat('x');
  107.                                 write_1602dat(hex_table[e]);    //
  108.                                 write_1602dat(hex_table[f]);    //
  109.                                 write_1602dat(',');
  110.                                 write_1602dat(hex_table[g]);    //
  111.                                 write_1602dat(hex_table[h]);    //
  112.                         
  113.                                 write_1602com(er);//指定显
  114.         write_1602dat('0');
  115.                                 write_1602dat('x');                                
  116.                                 write_1602dat(hex_table[a1]);    //
  117.                                 write_1602dat(hex_table[b1]);    //
  118.                                 write_1602dat(',');
  119.                                 write_1602dat(hex_table[c1]);    //
  120.                                 write_1602dat(hex_table[d1]);    //
  121.                                 write_1602dat(' ');
  122.                                 write_1602dat('0');
  123.                                 write_1602dat('x');
  124.                                 write_1602dat(hex_table[e1]);    //
  125.                                 write_1602dat(hex_table[f1]);    //
  126.                                 write_1602dat(',');
  127.                                 write_1602dat(hex_table[g1]);    //
  128.                                 write_1602dat(hex_table[h1]);    //
  129.                                        
  130.                         }        
  131.       if(xianshi==2)
  132.                         {
  133.                           uchar a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1;
  134.                                 a = (yi%256)/16; //           十位
  135.                                 b = (yi%256)%16; //           个位
  136.                                 c = (ra%256)/16; //           十位
  137.                                 d = (ra%256)%16; //           个位
  138.                                 e = (yi+1%256)/16; //          十位
  139.                                 f = (yi+1%256)%16; //          个位
  140.                                 g = (si%256)/16; //           十位
  141.                                 h = (si%256)%16; //           个位
  142.                                 a1 = (yi+2%256)/16; //           十位
  143.                                 b1 = (yi+2%256)%16; //           个位
  144.                                 c1 = (ra1%256)/16; //           十位
  145.                                 d1 = (ra1%256)%16; //           个位
  146.                                 e1 = (yi+3%256)/16; //          十位
  147.                                 f1 = (yi+3%256)%16; //          个位
  148.                                 g1 = (si1%256)/16; //           十位
  149.                                 h1 = (si1%256)%16; //           个位
  150.                                 write_1602com(yh);//指定显示
  151.                                 write_1602dat('0');
  152.                                 write_1602dat('x');
  153.                                 write_1602dat(hex_table[a]);    //
  154.                                 write_1602dat(hex_table[b]);    //
  155.                                 write_1602dat(',');
  156.                                 write_1602dat(hex_table[c]);    //
  157.                                 write_1602dat(hex_table[d]);    //
  158.                                 write_1602dat(' ');
  159.                                 write_1602dat('0');
  160.                                 write_1602dat('x');
  161.                                 write_1602dat(hex_table[e]);    //
  162.                                 write_1602dat(hex_table[f]);    //
  163.                                 write_1602dat(',');
  164.                                 write_1602dat(hex_table[g]);    //
  165.                                 write_1602dat(hex_table[h]);    //
  166.                         
  167.                                 write_1602com(er);//指定显
  168.         write_1602dat('0');
  169.                                 write_1602dat('x');                                
  170.                                 write_1602dat(hex_table[a1]);    //
  171.                                 write_1602dat(hex_table[b1]);    //
  172.                                 write_1602dat(',');
  173.                                 write_1602dat(hex_table[c1]);    //
  174.                                 write_1602dat(hex_table[d1]);    //
  175.                                 write_1602dat(' ');
  176.                                 write_1602dat('0');
  177.                                 write_1602dat('x');
  178.                                 write_1602dat(hex_table[e1]);    //
  179.                                 write_1602dat(hex_table[f1]);    //
  180.                                 write_1602dat(',');
  181.                                 write_1602dat(hex_table[g1]);    //
  182.                                 write_1602dat(hex_table[h1]);    //
  183.                                 
  184.                                 
  185.                         }        

  186. }

  187. void Start()  //开始总线
  188. {
  189.    SDA=1;
  190.    delay();
  191.    SCL=1;
  192.    delay();
  193.    SDA=0;
  194.    delay();
  195.    SCL=0;
  196.    delay();
  197. }


  198. void Stop()  //结束总线
  199. {
  200.    SCL=0;
  201.    delay();
  202.    SDA=0;
  203.    delay();
  204.    SCL=1;
  205.    delay();
  206.    SDA=1;
  207.    delay();
  208. }

  209. void NoAck()  //发 ACK0
  210. {
  211.     SDA=1;
  212.     delay();
  213.     SCL=1;
  214.     delay();
  215.     SCL=0;
  216.     delay();
  217.             
  218. }

  219. bit TestAck()  //测试 ACK
  220. {
  221.     bit ErrorBit;
  222.     SDA=1;
  223.     delay();
  224.     SCL=1;
  225.     delay();
  226.     ErrorBit=SDA;
  227.    
  228.     delay();
  229.     SCL=0;
  230.     delay();
  231.     return(ErrorBit);           
  232. }

  233. Write8Bit(unsigned char input)//写入 8 个 bit 到 24c02  
  234. {
  235.   unsigned char temp;
  236.    for(temp=8;temp!=0;temp--)  
  237.    {
  238.      SDA=(bit)(input&0x80);
  239.      delay();
  240.      SCL=1;
  241.      delay();
  242.      SCL=0;
  243.      delay();
  244.      input=input<<1;
  245.    }
  246. }

  247. void Write24c02(uchar ch,uchar address)//写入一个字节到 24c02 中  
  248. {
  249.     Start();
  250.     Write8Bit(WriteDeviceAddress);
  251.     TestAck();
  252.     Write8Bit(address);
  253.     TestAck();
  254.     Write8Bit(ch);
  255.     TestAck();
  256.     Stop();
  257.     delay1(10);
  258. }

  259. //从 24c02 中读出 8 个 bit
  260. uchar Read8Bit()  
  261. {
  262.    unsigned char temp,rbyte=0;
  263.     for(temp=8;temp!=0;temp--)  
  264.     {
  265.      SCL=1;
  266.      rbyte=rbyte<<1;
  267.      rbyte=rbyte|((unsigned char)(SDA));
  268.      SCL=0;
  269.     }
  270.     return(rbyte);
  271. }

  272. uchar Read24c02(uchar address) //从 24c02 中读出 1 个字节
  273. {
  274.      uchar ch;
  275.      Start();
  276.      Write8Bit(WriteDeviceAddress);
  277.      TestAck();
  278.      Write8Bit(address);
  279.      TestAck();
  280.      Start();
  281.      Write8Bit(ReadDviceAddress);
  282.      TestAck();
  283.      ch=Read8Bit();
  284.      NoAck();
  285.      Stop();
  286.      return(ch);
  287. }

  288. void xie()
  289. {
  290.            Write24c02(ra,yi);
  291.        delay1(10);
  292.            Write24c02(si,yi+1);
  293.        delay1(10);
  294.            Write24c02(ra1,yi+2);
  295.        delay1(10);
  296.            Write24c02(si1,yi+3);
  297.        delay1(10);
  298.        Stop();
  299. }
  300. void du()
  301. {
  302.            ra=Read24c02(yi);
  303.            delay1(20);
  304.            si=Read24c02(yi+1);
  305.            delay1(20);
  306.            ra1=Read24c02(yi+2);
  307.            delay1(20);
  308.            si1=Read24c02(yi+3);
  309.            delay1(20);
  310.            Stop();  
  311. }

  312. void set()
  313. {
  314.      Start();
  315.      Write8Bit(WriteDeviceAddress);
  316.      TestAck();
  317.            delay1(5);
  318.            Stop();
  319. }
  320. void keyscan()
  321. {
  322.       
  323.                    if(k2==0)
  324.                         {
  325.                           delay1(10);
  326.                           if(!k2)
  327.                           {
  328.                             delay1(10);
  329.                             while(!k2);
  330.                                         key1n+=1;
  331.                                         if(key1n>2)
  332.                                         {
  333.                                           key1n=1;
  334.                                         }
  335.                                         switch(key1n)
  336.                {
  337.                  case 1:open=1;        key3n=0;dsplaysw=0; write_1602com(0x0c);ra=0;si=0;ra1=0;si1=0;//关闭光标     
  338.                                           break;
  339.                        case 2:open=0;num=0;jishu=0; dsplaysw=0;xianshi=0;lcd_init(); key2n=0; key3n=0;   
  340.                                           break;
  341.                            }
  342.                          }
  343.                    }
  344.                 if(k1==0)
  345.                  {
  346.                         delay1(10);
  347.                         if(!k1)
  348.                         {
  349.                          delay1(10);
  350.                          while(!k1);
  351.                                 key2n+=1;
  352.                                         if(key2n>2)
  353.                                         {
  354.                                           key2n=1;
  355.                                         }
  356.                                         switch(key2n)
  357.                {
  358.                  case 1:        du();xianshi=1;key3n=0; dsplaysw=0; write_1602com(0x0c);//关闭光标     
  359.                                           break;
  360.                        case 2:  dsplaysw=1;xianshi=2; write_1602com(yh+5);write_1602com(0x0f);key3n=1;
  361.                                           break;
  362.                             }
  363.                            }
  364.                     }
  365.                  
  366.                 if(key2n==2)
  367.                 {
  368.      if(k3==0)
  369.                  {
  370.                         delay1(50);
  371.                         if(!k3)
  372.                         {
  373.                          delay1(50);
  374.                          while(!k3);
  375.                                 key3n+=1;
  376.                                         if(key3n>5)
  377.                                         {
  378.                                           key3n=1;
  379.                                         }
  380.                                         switch(key3n)
  381.                {
  382.                  case 1:  write_1602com(yh+5);  //设置按键按动一次秒位置显示光标
  383.                                             write_1602com(0x0f);  //设置光标为闪烁                                          
  384.                                           break;
  385.                        case 2:  write_1602com(yh+13);
  386.                     write_1602com(0x0f);  //设置光标为闪烁                                         
  387.                                           break;
  388.                                          case 3:  write_1602com(er+5);
  389.                     write_1602com(0x0f);  //设置光标为闪烁                                         
  390.                                           break;
  391.                                          case 4:  write_1602com(er+13);
  392.                                                   write_1602com(0x0f);  //设置光标为闪烁
  393.                                           break;
  394.                                          case 5:  write_1602com(0x0c);//关闭光标
  395.                                                   xie();
  396.                                                   xianshi=1;key2n=1;key3n=0; dsplaysw=0;
  397.                                           break;
  398.                             }
  399.                            }
  400.                     }
  401.                    }
  402. }

  403. uint CodingsWitchPolling()  
  404. {
  405.     static uchar Aold,Bold; //两个变量用来储存上一次调用时编码开关两引脚的电平   
  406.         static uchar st=0;       //用来储存以前是否出现了两个引脚都为高电平的状态
  407.         static uint tmp=0;    // ***这3个均为静态变量,以便保持上次结果***     
  408.         
  409.         if(CodingsWitch_A&&CodingsWitch_B)     
  410.          st = 1;            
  411.          if(st)                 //如果st为1执行下面的步骤      
  412.          {
  413.           if(CodingsWitch_A==0&&CodingsWitch_B==0) //如果两引脚都为低执行下面         
  414.           {           
  415.             if(Bold)         //为高说明编码开关在向加大的方向转            
  416.                  {               
  417.                   st = 0;               
  418.                    if(yi==9999)yi=9999;
  419.        if(ra>255)ra=0;        
  420.                    if(si>255)si=0;
  421.        if(ra1>255)ra1=0;        
  422.                    if(si1>255)si1=0;                          
  423.                           else
  424.         if(key2n==1){yi+=4;du();}                                       
  425.                           if(key3n==1){ra+=1;write_1602com(0x0c);dsplay();write_1602com(yh+5);write_1602com(0x0f);}
  426.         if(key3n==2){si+=1;write_1602com(0x0c);dsplay();write_1602com(yh+13);write_1602com(0x0f);}
  427.         if(key3n==3){ra1+=1;write_1602com(0x0c);dsplay();write_1602com(er+5);write_1602com(0x0f);}
  428.         if(key3n==4){si1+=1;write_1602com(0x0c);dsplay();write_1602com(er+13);write_1602com(0x0f);}                                
  429.                           }            
  430.                          if(Aold)   //为高说明编码开关在向减小的方向转            
  431.                           {               
  432.                            st = 0;                                       
  433.                            if(yi==0)yi=0;
  434.          if(ra<0)ra=0;        
  435.                      if(si<0)si=0;
  436.          if(ra1<0)ra1=0;        
  437.                      if(si1<0)si1=0;                                       
  438.                                 else                 
  439.                                  if(key2n==1){yi-=4;du();}     //设返回值
  440.          if(key3n==1){ra-=1;write_1602com(0x0c);dsplay();write_1602com(yh+5);write_1602com(0x0f);}
  441.          if(key3n==2){si-=1;write_1602com(0x0c);dsplay();write_1602com(yh+13);write_1602com(0x0f);}
  442.          if(key3n==3){ra1-=1;write_1602com(0x0c);dsplay();write_1602com(er+5);write_1602com(0x0f);}
  443.          if(key3n==4){si1-=1;write_1602com(0x0c);dsplay();write_1602com(er+13);write_1602com(0x0f);}                                         
  444.                                 }               
  445.                          }
  446.                   
  447.                  }
  448.                        
  449.             Aold = CodingsWitch_A;  //保持这次检测的电平,以备下次调用比较用      
  450.            Bold = CodingsWitch_B;      //     
  451.           return tmp;               //返回计数值  
  452.         }

  453.         
  454. void main()
  455. {                                 
  456.           lcd_init();
  457.     Init_Timer0();
  458.   while(1)
  459. {
  460.          keyscan();
  461.    if(dsplaysw==0){dsplay();}         
  462.    }        
  463. }

  464. void Init_Timer0(void)
  465. {
  466.          TMOD=0x01;
  467.          ET0=1;           //定时器中断打开
  468.          TR0=1;           //定时器开关打开
  469.          ET1=1;           //定时器中断打开
  470.          TR1=1;           //定时器开关打?
  471.          EA=1;            //总中断打开
  472. }
  473. void Timer0_isr(void) interrupt 1
  474. {

  475.          TH0=(65536-50000)/256;                  //重新赋值 2ms  62500
  476.          TL0=(65536-50000)%256;
  477.         
  478.           if(open==1)
  479.           {
  480.              num++;
  481.                  if(num==3)
  482.                  {
  483.                     num=0;
  484.                     jishu++;
  485.                           set();
  486.                          if(jishu>255)
  487.                   {
  488.                      jishu=255;        
  489.                     }
  490.                   }
  491.                   
  492.           }
  493.                
  494.         
  495.    }  
  496.          
  497.         void Timer1_isr(void) interrupt 3   
  498.         {
  499.           TH1=0xec;
  500.     TL1=0xec;
  501.     CodingsWitchPolling(); //调用编码开关函数
  502.                
  503.         }
复制代码

所有资料51hei提供下载:
i2c测地址.rar (87.22 KB, 下载次数: 31)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:275111 发表于 2020-4-1 10:03 | 显示全部楼层
好帖子。虽然刚刚开始看还没懂。正在学习I2C。还请高人多写。谢谢。
回复

使用道具 举报

ID:295423 发表于 2024-2-7 14:24 | 显示全部楼层
好帖子。虽然刚刚开始看还没懂。正在学习I2C。还请高人多写。谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表