I2C卡死在发送起始信号
<p>#include "stc8h.h"<br />//#include "ds1307.h"<br />
#include "intrins.h"<br />
#include "I2C.h"</p>
<p>unsigned char IIC_addr = 0x3C ;<br />
//引脚初始化,全部设为上拉<br />
void I2C_pin_init()<br />
{<br />
P1M0 &= ~0x10; //设置P1.4为双向口模式<br />
P1M1 &= ~0x10;</p>
<pre><code>P1M0 &= ~0x20; //设置P1.5为双向口模式
P1M1 &= ~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 & 0x40));</strong></em><br />
I2CMSST &= ~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 < 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<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<<1); //发送设备地址+写命令
RecvACK();
SendData(reg); //发送存储地址
RecvACK();
//Stop(); //发送停止命令
Start(); //发送起始命令
SendData((IIC_addr<<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<<1); //发送设备地址+写命令<br />
RecvACK();<br />
SendData(reg); //发送存储地址<br />
RecvACK();<br />
//Stop(); //发送停止命令</p>
<pre><code> Start(); //发送起始命令
SendData((IIC_addr<<1)|0x01); //发送设备地址+读命令
//SendACK();
RecvACK();
I2C_ReceiveData(&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<<1); //发送设备地址+写命令
RecvACK();
SendData(reg); //发送存储地址
RecvACK();
SendData(dat); //设置小时值
RecvACK();
Stop(); //发送停止命令
return 0;
</code></pre>
<p>}</p>
<p><em><strong>在写入时会卡在发送起始信号这……while (!(I2CMSST & 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 />
没看到是不是开了这个
P_SW2 |= 0x80;
如果没有开的话 你的内部上拉电阻的配置是无效的。。 再者根据你说 准双向模式下,可以使用,,
开漏模式下不行,且要使用内部上拉电阻的操作,我是不是可以猜测你外部没有上拉电阻,,, 几个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
_奶咖君_ 发表于 2024-12-23 16:32
再者根据你说 准双向模式下,可以使用,,
开漏模式下不行,且要使用内部上拉电阻的操作,我是不是可以猜 ...
是没有上拉电阻,问题是现在不行了卡死在发起始信号等待中断置位 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; //启用总中断
} _奶咖君_ 发表于 2024-12-23 16:30
没看到是不是开了这个
开了,在主时钟设置那开了后没关闭,我在外部加上拉试下,之前的模拟I2C是没有加外部上拉,用的内部上拉,可以工作。 DebugLab 发表于 2024-12-23 16:42
PxMx和PxPU改成和你硬件一致的 KNW123 发表于 2024-12-23 16:45
开了,在主时钟设置那开了后没关闭,我在外部加上拉试下,之前的模拟I2C是没有加外部上拉,用的内部上拉 ...
一定要加外部上拉吗?我感觉好多我都是用内部上拉程序也没问题的啊 DebugLab 发表于 2024-12-23 16:45
PxMx和PxPU改成和你硬件一致的
是P14和P15啊