AI8H1K28作为IIC从机,意外触发停止条件
<p>程序如下,上位机从2号寄存器开始读取5个字节。</p><p>bit isda; //设备地址标志<br />
bit isma; //存储地址标志<br />
unsigned char AddrSend;<br />
unsigned char AddrRev;<br />
unsigned char pdata BufferSend;<br />
unsigned char pdata BufferRev;</p>
<p>void I2C_GPIO_Config(void)<br />
{<br />
GPIO_InitTypeDef GPIO_InitStructure; //结构定义</p>
<pre><code>GPIO_InitStructure.Pin= GPIO_Pin_4 | GPIO_Pin_5; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P2,&GPIO_InitStructure); //初始化
P_SW2 |= 0x80;
//P_SW2 |= 0x00; //SDA/P1.4下降沿唤醒
P_SW2 |= 0x10; //SDA_2/P2.4下降沿唤醒
//P_SW2 |= 0x30; //SDA_4/P3.3下降沿唤醒
I2CCFG = 0x80; //使能I2C从机模式
I2CSLADR = 0x28; //设置从机设备地址寄存器I2CSLADR=0101_1010B
//即I2CSLADR=010_1101B,MA=0B。
//由于MA为0,主机发送的的设备地址必须与
//I2CSLADR相同才能访问此I2C从机设备。
//主机若需要写数据则要发送5AH(0101_1010B)
//主机若需要读数据则要发送5BH(0101_1011B)
I2CSLST = 0x00;
I2CSLCR = 0x78; //使能从机模式中断
EA = 1;
isda = 1; //用户变量初始化
isma = 1;
AddrSend = 0;
AddrRev =0;
//当发送寄存器的第一个要发送的数据最高位为1时可以被上位机正常读取,从第二个字节开始,如果最高位为1,将直接触发停止条件,之后的数据无法读取。
//如果所有字节的最高位都不为1,则全部可以正常读取。
BufferSend =0x81;
BufferSend =0x82;
BufferSend =0x83;
BufferSend =0x84;
BufferSend =0x85;
BufferSend =0x86;
BufferSend =0x87;
BufferSend =0x88;
BufferSend =0x89;
BufferSend =0x90;
I2CTXD = BufferSend;
</code></pre>
<p>}<br />
//=======================================================================================================================================================================</p>
<p>void I2C_Isr() interrupt 24<br />
{<br />
<em>push</em>(P_SW2); //将 切换控制寄存器 进栈处理<br />
P_SW2 |= 0x80;</p>
<pre><code>if(I2CSLST & 0x40) //收到开始信号
{
I2CSLST &= ~0x40; //处理START事件,开始信号清零 STAIF 位清零
}
else if(I2CSLST & 0x20) //从机模式时接收到 1 字节的数据后的中断请求位
{
I2CSLST &= ~0x20; //处理RECV事件,1 字节的数据 RXIF 位清零
if(isda) //设备地址,第一个字节是设备地址
{
isda = 0; //处理RECV事件(RECV DEVICE ADDR)
//deviceID_addr = I2CRXD;
}
else if(isma) //寄存器地址,第二个字节为寄存器地址
{
isma = 0; //处理RECV事件(RECV MEMORY ADDR)
AddrSend = I2CRXD;
I2CTXD = BufferSend;
//memory_addr = I2CRXD;
//IICdata_addr =0;
} //由于初始化的时候,IIC接收所有设备地址 ,不过从这里可继续添加else if 语句进行判断特点指令
else //数据1 和 数据2
{
BufferRev = I2CRXD; //处理RECV事件(RECV DATA)
//if(IICdata_addr >= 2) IICdata_addr = 0;
//I2C_Buffer = I2CRXD; //处理 RECV 事件(数据1 和 数据2)
}
}
else if(I2CSLST & 0x10) //从机模式时发送完成 1 字节的数据后的中断请求位
{
I2CSLST &= ~0x10; //处理SEND事件,从机模式时发送完成1字节的数据后的中断请求位
if (I2CSLST & 0x02) //从机模式时,接收到的 ACK 数据
{
I2CTXD = 0xff; //接收到NAK则停止读取数据
}
else //接收到 ACK 则继续读取数据 (重点)可持续发送 数据出去 主机觉得不断开
{
I2CTXD = BufferSend[++AddrSend]; //接收到ACK则继续读取数据
/*
if(deviceID_addr == 0xC3) //判断是否发出了24个字节 这里是我芯片特定的规律
{
I2CTXD = buffer1_24byte[++Read_organize_one];
if(Read_organize_one >= 24)
{
//printf("打印出_I2CTXD:%X ADD:%d\r\n", buffer1_24byte,Read_organize_one-1); //打印会影响数据输出准确性
Read_organize_one = 0;
I2CSLST &= ~0x10; //处理 SEND 事件 从机模式时发送完成1字节的数据后的中断请求位
I2CSLST &= ~0x08; //处理 STOP 事件 从机模式时接收到STOP信号后的中断请求位
}
}
if(deviceID_addr == 0xC5) //判断是否发出了24个字节 这里是我芯片特定的规律
{
I2CTXD = buffer2_24byte[++Read_organize_two];
if(Read_organize_two >= 24)
{
Read_organize_two = 0;
I2CSLST &= ~0x10; //处理 SEND 事件 从机模式时发送完成1字节的数据后的中断请求位
I2CSLST &= ~0x08; //处理 STOP 事件 从机模式时接收到STOP信号后的中断请求位
}
}
*/
}
}
else if(I2CSLST & 0x08) //从机模式时接收到 STOP 信号后的中断请求位
{
I2CSLST &= ~0x08; //处理STOP事件
isda = 1;
isma = 1;
AddrSend = 0;
AddrRev =0;
}
_pop_(P_SW2); //出栈处理
</code></pre>
<p>}</p>
<p>//=======================================================================================================================================================================</p>
<p><img src="data/attachment/forum/202412/10/150359caqzin7zi836mj88.png" alt="001.png" title="001.png" /></p>
<p>当吧寄存器的数据修改为最高位均不为1,则正常。如下:</p>
<p>BufferSend =0x01;<br />
BufferSend =0x72;<br />
BufferSend =0x03;<br />
BufferSend =0x74;<br />
BufferSend =0x65;<br />
BufferSend =0x46;<br />
BufferSend =0x77;<br />
BufferSend =0x48;<br />
BufferSend =0x59;<br />
BufferSend =0x90;</p>
<p><img src="data/attachment/forum/202412/10/150459ffqkf0rkxlxx7sqe.png" alt="002.png" title="002.png" /></p>
程序打包在这里
和最高位有关,用示波器看一下是不是上升沿速度不够
打开内部4K上拉
或者主机上拉,或者外接上拉电阻 看您的程序中只配置为准双向了,没有打开内部4K上拉
页:
[1]