您尚未登录。

楼主 # 2021-12-19 22:28:55

hotkey
会员
注册时间: 2019-06-23
已发帖子: 51
积分: 76

报告一例SWM19SCBT6的I2C的bug

如题,使用本芯片小批做了一批货,在I2C1上(PA14,PA15),SCK/SDA均通过2.2k电阻上拉,外设为RX8025T时钟芯片。

现象为:部分设备在上电后,SCK/SDA均无波形输出,通过拉低2脚RESET到地复位,故障依旧,短接3.3V供电电源到地,实现硬复位,故障恢复

概率大约为1%

解决办法:通过IO模拟I2C时序解决,放弃使用硬件I2C。

希望帮到大家。

离线

楼主 #1 2021-12-19 22:35:01

hotkey
会员
注册时间: 2019-06-23
已发帖子: 51
积分: 76

Re: 报告一例SWM19SCBT6的I2C的bug

附上IO模拟I2C的程序给大家参考:

#define SCL_0	GPIO_ClrBit(GPIO_RTC_SCL_PORT, GPIO_RTC_SCL_PIN)//SCL
#define SCL_1	GPIO_SetBit(GPIO_RTC_SCL_PORT, GPIO_RTC_SCL_PIN)
#define SDA_0	GPIO_ClrBit(GPIO_RTC_SDA_PORT, GPIO_RTC_SDA_PIN)//SDA
#define SDA_1	GPIO_SetBit(GPIO_RTC_SDA_PORT, GPIO_RTC_SDA_PIN)
#define SDA_SET_IN	GPIO_Init(GPIO_RTC_SDA_PORT, GPIO_RTC_SDA_PIN, 0, 0, 0, 0)//设置成输入
#define SDA_SET_OUT	GPIO_Init(GPIO_RTC_SDA_PORT, GPIO_RTC_SDA_PIN, 1, 1, 0, 0)//设置成输出
#define SDA_VALUE	GPIO_GetBit(GPIO_RTC_SDA_PORT, GPIO_RTC_SDA_PIN)


#define ts  15
#define th  15
#define tcycle  30   // half the cycle


/* 用于短暂的延时,在xxMHz的频率下延时时长yyus */
void __delay_cycles(unsigned int z)
{
	volatile unsigned int y;
	for(y=z; y>0; y--);
}

/*********************************************************
函数名称:I2C_IO_Start()
函数功能:产生一个起始条件
入口参数:无
出口参数:无
备注:
**********************************************************/
static void I2C_IO_Start(void)
{
	SCL_0;
	__delay_cycles(ts);
	SDA_1;
	SCL_1;
	__delay_cycles(th);
	SDA_0;
	__delay_cycles(10);
	SCL_0;
}

/*********************************************************
函数名称:I2C_IO_Stop()
函数功能:产生一个停止条件
入口参数:无
出口参数:无
备注:
**********************************************************/
static void I2C_IO_Stop(void)
{
	__delay_cycles(th);
	SDA_0;
	__delay_cycles(ts);
	SCL_1;
	__delay_cycles(10);
	SDA_1;
	__delay_cycles(5);
}

/*********************************************************
函数名称:I2C_IO_Ack()
函数功能:产生一个ACK
入口参数:无
出口参数:无
备注:
**********************************************************/
static void I2C_IO_Ack(void)
{
    SDA_0;
	__delay_cycles(ts);
    SCL_1;
	__delay_cycles(th);
    SCL_0;
	__delay_cycles(ts);
    SDA_1;
}

/*********************************************************
函数名称:I2C_IO_Nack()
函数功能:产生一个NACK
入口参数:无
出口参数:无
备注:
**********************************************************/
static void I2C_IO_Nack(void)
{
    SDA_1;
	__delay_cycles(ts);
    SCL_1;
	__delay_cycles(th);
    SCL_0;
	__delay_cycles(ts);
    SDA_0;
}

/*********************************************************
函数名称:I2C_IO_WriteOneByte()
函数功能:写操作 一个字节
入口参数:byte 待写字节
出口参数:1 子器件无应答; 0 完成写一个字节。
备注:
**********************************************************/
static U_CHAR I2C_IO_WriteOneByte(U_CHAR byte)
{
	U_CHAR i;

	for (i = 0; i < 8; i++) {
		SCL_0;
		__delay_cycles(ts);
		
		if((byte >> 7) & 0x01) 
			SDA_1;
		else 
			SDA_0;
		
		byte <<= 1;
		SCL_1;
		__delay_cycles(tcycle);
	}
	SCL_0;
	SDA_0;
	__delay_cycles(ts);
	SDA_SET_IN;//SDA 输入,用来检测子器件ACK
	SCL_1;
	__delay_cycles(th);
	
	i = 0;
	while (SDA_VALUE) { //8025T ACK为0
		if (++i > 12) {
			SCL_0;
			SDA_SET_OUT;//SDA作为输出
			I2C_IO_Stop();
			return 1;   //NACK  return
		}
	}
	SDA_SET_OUT;//SDA作为输出
	SCL_0;
	SDA_0;
	__delay_cycles(ts);

	return 0;
}

/*********************************************************
函数名称:I2C_IO_Write()
函数功能:写操作 iic时序写多个字节
入口参数:registerAddress 器件地址;
		WriteBuf 待写数据缓存
		len 数据长度(字节数)
出口参数:1 子器件无应答; 0 写操作完成。
备注:
**********************************************************/
U_CHAR I2C_IO_Write(U_CHAR registerAddress, U_CHAR *WriteBuf, U_CHAR len)
{
	U_CHAR temp;
	
	I2C_IO_Start();

	if (I2C_IO_WriteOneByte(RX8025T_WRITE_ADDR))//写器件地址
		return 1;
	
	if (I2C_IO_WriteOneByte(registerAddress))//写寄存器地址
		return 1;
	
	while (len--) {
		temp = *WriteBuf++;//寄存器地址自动增加,只需写数据
		if (I2C_IO_WriteOneByte(temp))//写数据
			return 1;
	}
	
	I2C_IO_Stop();
	return 0;
}

/*********************************************************
函数名称:I2C_IO_ReadOneByte()
函数功能:读操作 一个字节
入口参数:读数据存放地址
出口参数:无
备注:
**********************************************************/
static void I2C_IO_ReadOneByte(U_CHAR *byte)
{
	U_CHAR i, retc = 0;
	SCL_0;
	SDA_SET_OUT;
	SDA_1;
	SDA_SET_IN;//SDA 输入
	for (i = 0; i < 8; i++) {		  
		SCL_1;
		__delay_cycles(th);
		
		retc <<= 1;
		if (SDA_VALUE)
			retc |= 1;
		SCL_0;
		__delay_cycles(ts);
	}
	SDA_SET_OUT;
	SDA_0;
	SCL_0;	  
	*byte = retc;
}

/*********************************************************
函数名称:I2C_IO_Read()
函数功能:读操作
入口参数:registerAddress 器件地址;
		ReadBuf 读数据缓存
		len 数据长度(字节数)
出口参数:无
备注:	最后一个字节发送NACK,子器件准备接收停止条件
**********************************************************/
U_CHAR I2C_IO_Read(U_CHAR registerAddress, U_CHAR *ReadBuf, U_CHAR len)
{
	I2C_IO_Start();
	if (I2C_IO_WriteOneByte(RX8025T_WRITE_ADDR))//写器件地址
		return 1;
	
	if (I2C_IO_WriteOneByte(registerAddress))//写寄存器地址
		return 1;
	
	SDA_SET_OUT;//SDA作为输出
	I2C_IO_Start();//重新发送起始条件【Sr】
	
	if (I2C_IO_WriteOneByte(RX8025T_READ_ADDR))//写器件地址(读模式)
		return 1;
	
	while (len--) {//读数据
		I2C_IO_ReadOneByte(ReadBuf);
		ReadBuf++;
		if (len == 0)
			I2C_IO_Nack();
		else
			I2C_IO_Ack();
	}
	I2C_IO_Stop();
	return 0;
}

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn