KNW123 发表于 2024-12-23 16:14:43

I2C卡死在发送起始信号

<p>#include &quot;stc8h.h&quot;<br />
//#include &quot;ds1307.h&quot;<br />
#include &quot;intrins.h&quot;<br />
#include &quot;I2C.h&quot;</p>
<p>unsigned char IIC_addr = 0x3C ;<br />
//引脚初始化,全部设为上拉<br />
void I2C_pin_init()<br />
{<br />
P1M0 &amp;= ~0x10;                              //设置P1.4为双向口模式<br />
P1M1 &amp;= ~0x10;</p>
<pre><code>P1M0 &amp;= ~0x20;                              //设置P1.5为双向口模式
P1M1 &amp;= ~0x20;

P1PU |= 0x10 ;                                        //设置P1.4的上拉电阻
        P1PU |= 0x20 ;                                        //设置P1.5的上拉电阻
</code></pre>
<p>}</p>
<p>//寄存器初始化</p>
<p>void I2C_Init(void)</p>
<p>{</p>
<p>// CLK_PCKENR1 |= 0x01;                                //使能IIC外设时钟<br />
I2C_pin_init();</p>
<pre><code>//P_SW2 |= 0x80;                                                                //打开扩展寄存器的操作功能

I2CCFG = 0xe0;                              //使能I2C主机模式
I2CMSST = 0x00;                                                        //I2C主机状诚寄存器清0
</code></pre>
<p>}</p>
<p>void Wait()<br />
{<br />
<em><strong>while (!(I2CMSST &amp; 0x40));</strong></em><br />
I2CMSST &amp;= ~0x40;<br />
}</p>
<p>void Start()<br />
{<br />
I2CMSCR = 0x01;                           //发送START命令<br />
Wait();<br />
}</p>
<p>void SendData(char dat)<br />
{<br />
I2CTXD = dat;                               //写数据到数据缓冲区<br />
I2CMSCR = 0x02;                           //发送SEND命令<br />
Wait();<br />
}</p>
<p>void RecvACK()<br />
{<br />
I2CMSCR = 0x03;                           //发送读ACK命令<br />
Wait();<br />
}</p>
<p>char RecvData()<br />
{<br />
I2CMSCR = 0x04;                           //发送RECV命令<br />
Wait();<br />
return I2CRXD;<br />
}</p>
<p>void SendACK()<br />
{<br />
I2CMSST = 0x00;                           //设置ACK信号<br />
I2CMSCR = 0x05;                           //发送ACK命令<br />
Wait();<br />
}</p>
<p>void SendNAK()<br />
{<br />
I2CMSST = 0x01;                           //设置NAK信号<br />
I2CMSCR = 0x05;                           //发送ACK命令<br />
Wait();<br />
}</p>
<p>void Stop()<br />
{<br />
I2CMSCR = 0x06;                           //发送STOP命令<br />
Wait();<br />
}</p>
<p>//读取连续接收到的数据,读取多个数据<br />
unsigned char I2C_ReceiveData(unsigned char *ptime,unsigned char num)<br />
{<br />
unsigned char i=0;//cnt=0;</p>
<pre><code>                        for( i = 0 ; i &lt; num ; i ++ )
                        {
                                ptime = RecvData() ;                        //读取秒值

                                if( i == 6 )
                                {
                                        SendNAK() ;
                                }
                                else
                                {
                                        SendACK();
                                }
                        }
</code></pre>
<p>return 0;<br />
}<br />
/*<br />
void Delay()<br />
{<br />
int i;</p>
<pre><code>for (i=0; i&lt;3000; i++)
{
    _nop_();
    _nop_();
    _nop_();
    _nop_();
}
</code></pre>
<p>}*/</p>
<p>//读寄存器中的数据<br />
unsigned char I2C_Read_Byte(unsigned char reg, unsigned char *p_data)<br />
{<br />
unsigned int cnt = 0;</p>
<pre><code>      Start();                              //发送起始命令
    SendData(IIC_addr&lt;&lt;1);                         //发送设备地址+写命令
    RecvACK();
    SendData(reg);                         //发送存储地址
    RecvACK();
          //Stop();                                 //发送停止命令

    Start();                              //发送起始命令
    SendData((IIC_addr&lt;&lt;1)|0x01);                         //发送设备地址+读命令
                        //SendACK();
    RecvACK();
          I2C_ReceiveData(p_data,7);
      //SendNAK() ;
          Stop();                                 //发送停止命令
        //Delay();
        return 1;
</code></pre>
<p>}</p>
<p>//读单个字节并反回<br />
unsigned char I2cread(unsigned char reg)<br />
{<br />
//unsigned int cnt = 0;<br />
unsigned char p_data = 0 ;<br />
Start();                              //发送起始命令<br />
SendData(IIC_addr&lt;&lt;1);                         //发送设备地址+写命令<br />
RecvACK();<br />
SendData(reg);                         //发送存储地址<br />
RecvACK();<br />
//Stop();                                 //发送停止命令</p>
<pre><code>    Start();                              //发送起始命令
    SendData((IIC_addr&lt;&lt;1)|0x01);                         //发送设备地址+读命令
                        //SendACK();
    RecvACK();
          I2C_ReceiveData(&amp;p_data,1);
      //SendNAK() ;
          Stop();                                 //发送停止命令
        //Delay();
        return p_data;
</code></pre>
<p>}</p>
<p>//向相应的寄存器中写入相应的值<br />
unsigned charI2C_Write_Byte(unsigned charreg,unsigned char dat )<br />
{<br />
unsigned int cnt = 0;</p>
<pre><code>Start();                                    //发送起始命令
SendData(IIC_addr&lt;&lt;1);                           //发送设备地址+写命令
RecvACK();
SendData(reg);                           //发送存储地址
RecvACK();
SendData(dat);                           //设置小时值
RecvACK();
Stop();                                     //发送停止命令

return 0;
</code></pre>
<p>}</p>
<p><em><strong>在写入时会卡在发送起始信号这……while (!(I2CMSST &amp; 0x40));</strong></em></p>
<p><em><strong>看到有的评论说IO要设成开漏,但我之前用过,也是设成准双向IO,可以使用,而且说明书中的例程也是设成的双向IO!</strong></em></p>
<p>***芯片型号为STC8H1K08<br />
<img src="data/attachment/forum/202412/23/225712atzlm7dy4tl4lh7n.png" alt="捕获.PNG" title="捕获.PNG" /></p>
<p><em><strong>没有发现结贴模式,问题已解决是硬件问题,两个IIC器件通信时用的软排线,FPC线连接,在焊接座子时有一根线,恰好是GND断开了,不知道是座子变形断开还是别的原因,引脚应该是焊接上的。是怎么发现的呢,是因为测量两块板的对地电压不一致,从机电压偏高,奇怪的是没有连接GND,从机的PW6513也能输出电压!还有一个原因,在测试PW6513时烧过后级芯片,因为输入电容没有直接接到PW6513的VCC脚上,导致烧了几个后级习片,此时也把从机的IO口烧了,所以是好多问题叠加出现了卡在启动信号发送问题这的!</strong></em></p>
<hr />

_奶咖君_ 发表于 2024-12-23 16:30:50

没看到是不是开了这个
    P_SW2 |= 0x80;

如果没有开的话 你的内部上拉电阻的配置是无效的。。

_奶咖君_ 发表于 2024-12-23 16:32:06

再者根据你说 准双向模式下,可以使用,,

开漏模式下不行,且要使用内部上拉电阻的操作,我是不是可以猜测你外部没有上拉电阻,,,

DebugLab 发表于 2024-12-23 16:38:19

几个I2C测试正常的程序,可以参考一下:

https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4612

https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4613

https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4698


KNW123 发表于 2024-12-23 16:38:40

_奶咖君_ 发表于 2024-12-23 16:32
再者根据你说 准双向模式下,可以使用,,

开漏模式下不行,且要使用内部上拉电阻的操作,我是不是可以猜 ...

是没有上拉电阻,问题是现在不行了卡死在发起始信号等待中断置位

DebugLab 发表于 2024-12-23 16:42:25

void I2C_Start(void)
{
      I2C_Busy=1;
      I2CMSCR=0x81;
      while(I2C_Busy);
}

void I2C_SendData(unsigned char dat)
{
      I2CTXD=dat;
      I2C_Busy=1;
      I2CMSCR=0x82;
      while(I2C_Busy);
}

void I2C_RecvACK(void)
{
      I2C_Busy=1;
      I2CMSCR=0x83;
      while(I2C_Busy);
}

unsigned char I2C_RecvData(void)
{
      I2C_Busy=1;
      I2CMSCR=0x84;
      while(I2C_Busy);
      return I2CRXD;
}

void I2C_SendACK(void)
{
      I2CMSST=0x00;
      I2C_Busy=1;
      I2CMSCR=0x85;
      while(I2C_Busy);
}

void I2C_SendNAK(void)
{
      I2CMSST=0x01;
      I2C_Busy=1;
      I2CMSCR=0x85;
      while(I2C_Busy);
}

void I2C_Stop(void)
{
      I2C_Busy=1;
      I2CMSCR=0x86;
      while(I2C_Busy);
}void Init(void)
{
      P_SW2|=EAXFR;
      
      P3M0=0x00;
      P3M1=0x00;
      P5M0=0x00;
      P5M1=0x00;
      P3PU=0x0c;
      
      I2CCFG=0xC6;      //345.6K@11.0592M
      I2CMSCR=EMSI;
      I2CMSST=0x00;
      
      EA=1;                        //启用总中断
}

KNW123 发表于 2024-12-23 16:45:04

_奶咖君_ 发表于 2024-12-23 16:30
没看到是不是开了这个




开了,在主时钟设置那开了后没关闭,我在外部加上拉试下,之前的模拟I2C是没有加外部上拉,用的内部上拉,可以工作。

DebugLab 发表于 2024-12-23 16:45:54

DebugLab 发表于 2024-12-23 16:42


PxMx和PxPU改成和你硬件一致的

KNW123 发表于 2024-12-23 16:46:29

KNW123 发表于 2024-12-23 16:45
开了,在主时钟设置那开了后没关闭,我在外部加上拉试下,之前的模拟I2C是没有加外部上拉,用的内部上拉 ...

一定要加外部上拉吗?我感觉好多我都是用内部上拉程序也没问题的啊

KNW123 发表于 2024-12-23 16:46:54

DebugLab 发表于 2024-12-23 16:45
PxMx和PxPU改成和你硬件一致的

是P14和P15啊
页: [1] 2 3
查看完整版本: I2C卡死在发送起始信号