找回密码
 立即注册
查看: 355|回复: 4

AI8H1K28作为IIC从机,意外触发停止条件

[复制链接]

3

主题

1

回帖

37

积分

新手上路

积分
37
发表于 2024-12-10 15:05:43 | 显示全部楼层 |阅读模式

程序如下,上位机从2号寄存器开始读取5个字节。

bit isda; //设备地址标志
bit isma; //存储地址标志
unsigned char AddrSend;
unsigned char AddrRev;
unsigned char pdata BufferSend[10];
unsigned char pdata BufferRev[10];

void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构定义

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[7:1]=010_1101B,MA=0B。
                                            //由于MA为0,主机发送的的设备地址必须与
                                            //I2CSLADR[7:1]相同才能访问此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[0]	=0x81;
BufferSend[1]	=0x82;
BufferSend[2]	=0x83;
BufferSend[3]	=0x84;
BufferSend[4]	=0x85;
BufferSend[5]	=0x86;
BufferSend[6]	=0x87;
BufferSend[7]	=0x88;
BufferSend[8]	=0x89;
BufferSend[9]	=0x90;

I2CTXD = BufferSend[AddrSend];

}
//=======================================================================================================================================================================

void I2C_Isr() interrupt 24
{
push(P_SW2); //将 切换控制寄存器 进栈处理
P_SW2 |= 0x80;

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[AddrSend];
		//memory_addr = I2CRXD;
		//IICdata_addr =0;
    }					//由于初始化的时候,IIC接收所有设备地址 ,不过从这里可继续添加  else if 语句进行判断特点指令
    else				//数据1 和 数据2
    {
        BufferRev[AddrRev++] = I2CRXD;            //处理RECV事件(RECV DATA)
		//if(IICdata_addr >= 2) IICdata_addr = 0;
		//I2C_Buffer[IICdata_addr++] = 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-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);								//出栈处理

}

//=======================================================================================================================================================================

001.png

当吧寄存器的数据修改为最高位均不为1,则正常。如下:

BufferSend[0] =0x01;
BufferSend[1] =0x72;
BufferSend[2] =0x03;
BufferSend[3] =0x74;
BufferSend[4] =0x65;
BufferSend[5] =0x46;
BufferSend[6] =0x77;
BufferSend[7] =0x48;
BufferSend[8] =0x59;
BufferSend[9] =0x90;

002.png

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:172
  • 最近打卡:2025-04-28 08:49:07
已绑定手机

90

主题

961

回帖

2318

积分

超级版主

积分
2318
QQ
发表于 2024-12-10 15:41:28 | 显示全部楼层
程序打包在这里

VLT400-RS232test.rar

566.16 KB, 下载次数: 25

电路.rar

25.97 KB, 下载次数: 21

热线19952583534
www.STCAI.com
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-12-10 17:24:38 | 显示全部楼层
和最高位有关,用示波器看一下是不是上升沿速度不够
打开内部4K上拉
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-12-10 17:45:01 | 显示全部楼层
或者主机上拉,或者外接上拉电阻
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-12-10 17:46:16 | 显示全部楼层
看您的程序中只配置为准双向了,没有打开内部4K上拉
截图202412101745451879.jpg
DebugLab
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:33 , Processed in 0.152903 second(s), 74 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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