全志T113-S3 裸机IIC驱动(TWI驱动)

        调试了蛮久,最后发现是开发板原理图看错了,总的来说还是比较简单的,就是需要使用状态机方式编程,与传统的STM32那种有点不一样,状态图如下:

然后寄存器STA里面就是状态值,实测会出现0xF9 异常状态,开发板上面的HYM8563在IIC没有正常结束时,会一直出现SCL=1,SDA=0,并且无法软件恢复,必须断电重启,而且这个RTC芯片挑晶振厉害。

代码支持中断模式与查询模式,实际代码几乎一样,一个是中断中处理状态机,一个是在轮训中判断是否有中断,然后处理状态机,非OS模式下,如果需要使用轮训模式,需要自己处理一个软件超时,避免出现死循环。

#define _IIC_INT_ENABLE			1	//是否使能中断模式

上代码,因为是裸机,寄存器是自己定义的但是与手册一致,底层的寄存器需要自己定义,然后中断模式需要GIC支持。

/*************************************************************************************************************
 * 文件名		:	t113_iic.h
 * 功能			:	t113芯片IIC主机通讯
 * 作者			:	cp1300@139.com
 * 创建时间		:	2024-07-10
 * 最后修改时间	:	2024-07-10
 * 详细			:	只支持IIC主机模式
*************************************************************************************************************/
#ifndef __T113_IIC_H___
#define __T113_IIC_H___
#include "typedef.h"
#include "t113_system.h"
#include "t113_map.h"

#define _IIC_INT_ENABLE			1	//是否使能中断模式

//IIC硬件接口选择
typedef enum
{
	IIC_CH0 = 0,	//IIC0
	IIC_CH1 = 1,	//IIC1
	IIC_CH2 = 2,	//IIC2
	IIC_CH3 = 3,	//IIC3
}IIC_CH_Type;
#define IIC_CH_COUNT	4	//4个IIC

typedef enum
{
	IIC_SPEED_100KHz = 0,
	IIC_SPEED_200KHz = 1,
	IIC_SPEED_300KHz = 2,
	IIC_SPEED_400KHz = 3,
}IIC_SPEED_TYPE;


//通讯错误状态
typedef enum
{
	IIC_OK = 0,	//没有错误
	IIC_PARAMETER_ERROR = 1,	//参数错误
	IIC_TIMEOUT = 2,	//超时错误,也可能是底层错误
	IIC_HAL_ERROR = 3,	//底层错误
	IIC_STOP_ERROR = 4,	//等待结束错误
	IIC_BUSY = 5,	//硬件忙
	IIC_NACK = 6,	//没有收到ACK
}IIC_ERROR;





bool IIC_Init(IIC_CH_Type ch, IIC_SPEED_TYPE Speed, u16 TimeOutUs);//硬件IIC初始化
IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8* pDataBuff, u16 ReadByteNum);	//IIC读取寄存器(可以读取1个或者多个寄存器)
IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 WriteByteNum);	//IIC写寄存器(可以写1个或者多个寄存器)

#endif /* __T113_IIC_H___ */
/*************************************************************************************************************
 * 文件名		:	t113_iic.c
 * 功能			:	t113芯片IIC主机通讯
 * 作者			:	cp1300@139.com
 * 创建时间		:	2024-07-10
 * 最后修改时间	:	2024-07-10
 * 详细			:	只支持IIC主机模式,10bit从机地址未测试
*************************************************************************************************************/
#include "t113_system.h"
#include "t113_map.h"
#include "typedef.h"
#include "t113_iic.h"
#include "t113_const.h"


#define IIC_10BIT_ADD_MASK		(0x1E<<10)	//如果是10bit地址,最高位需要进行填充


//IIC下一个任务指示,用于指示下一次中断中的任务操作
typedef enum
{
	IIC_NEXT_TASK_IDLE = 0,	//无任务->发送开始信号
	IIC_NEXT_TASK_WAIT_START = 1,	//等待开始信号发送完成发送高从机地址   发送低从机地址

	IIC_NEXT_TASK_WAIT_10BIT_ADDR_H = 2,	//等待10bit从机高地址发送完成-写入
	IIC_NEXT_TASK_WAIT_7BIT_ADDR = 3,	//等待7bit从机地址发送完成-写入

	IIC_NEXT_TASK_WAIT_16BIT_REG_H = 4,	//等待发送16bit寄存器地址高位
	IIC_NEXT_TASK_WAIT_8BIT_REG = 5,	//等待发送8bit寄存器地址
	IIC_NEXT_TASK_WAIT_RSTART = 6,	//等待重复开始信号发送完成

	IIC_NEXT_TASK_RR_ADDR = 7,	//下次发送低重复7bit地址或高2bit地址-用于读取数据
	IIC_NEXT_TASK_WAIT_WRITE_DATA = 8,	//等待发送完成
	IIC_NEXT_TASK_READ_DATA = 9,	//下次读取数据

	IIC_NEXT_TASK_END = 0xFF,//任务结束了
}IIC_NEXT_TASK_OPERATE;


//IIC数据传输任务句柄-用于中断中发送数据
typedef struct
{
	u16 SlaveAddr;			//从设备地址,7bit或者10bit
	bool is10BitSlaveAddr;	//是否为10bit地址,否则为7bit
	u16 RegAddr;			//寄存器地址
	bool is8bitRegAddr;		//是否为8bit寄存器地址,否则为16bit
	u16 NeedCount;			//要传输的数据数量
	u8* pDataBuff;			//要传输的数据缓冲区
	u16 TranCount;			//已经传输的数据计数
	bool isRead;			//是否为读取数据,否则为写入数据
	IIC_NEXT_TASK_OPERATE NextOperate;	//下次中断中执行的任务操作
	bool isBusy;			//是否忙
}IIC_TRAN_TASK;









//主机相关状态
typedef enum
{
	IIC_STAT_BUSS_ERR = 0x00,		//总线错误
	IIC_STAT_START	= 0x08,			//START条件已传输
	IIC_STAT_RSTART	= 0x10,			//发送重复START条件
	IIC_STAT_AW_ACK = 0x18,			//发送地址 + 写入位,收到ACK
	IIC_STAT_AW_NACK = 0x20,		//发送地址 + 写入位,未收到ACK
	IIC_STAT_WDATA_ACK = 0x28,		//主模式下发送的数据字节,收到ACK
	IIC_STAT_WDATA_NACK = 0x30,		//主模式下传输的数据字节,未收到ACK
	IIC_STAT_ARB_ERR = 0x38,		//仲裁在地址或数据字节中丢失
	IIC_STAT_AR_ACK = 0x40,			//发送地址 + 读取位,收到ACK
	IIC_STAT_AR_NACK = 0x48,		//发送地址 + 读取位,未收到ACK
	IIC_STAT_RDATA_ACK = 0x50,		//主模式下接收到数据字节,发送ACK
	IIC_STAT_RDATA_NACK = 0x58,		//主模式下接收到数据字节,未发送ACK
	//IIC_STAT_BUSS_ERR = 0x60,		//接收到从地址 + 写入位,发送ACK
	//IIC_STAT_BUSS_ERR = 0x68,		//仲裁在作为主地址、从地址的地址中丢失 + 收到写入位,发送ACK
	//IIC_STAT_BUSS_ERR = 0x70,		//接收到通用呼叫地址,发送ACK
	//IIC_STAT_BUSS_ERR = 0x78,		//仲裁在作为主机的地址中丢失,常规呼叫收到地址,发送ACK
	//IIC_STAT_BUSS_ERR = 0x80,		//接收到从地址后接收到的数据字节,ACK传输的
	//IIC_STAT_BUSS_ERR = 0x88,		//接收到从地址后接收到数据字节,不是ACK传输的
	//IIC_STAT_BUSS_ERR = 0x90,		//接收到普通呼叫后接收到的数据字节,ACK传输的
	//IIC_STAT_BUSS_ERR = 0x98,		//接收到普通呼叫后接收到的数据字节,不是ACK传输的
	//IIC_STAT_BUSS_ERR = 0xA0,		//在从属模式下接收到STOP或重复START条件
	//IIC_STAT_BUSS_ERR = 0xA8,		//接收到从地址 + 读取位,发送ACK
	//IIC_STAT_BUSS_ERR = 0xB0,		//仲裁在作为主地址、从地址的地址中丢失 + 接收到读取位,发送ACK
	//IIC_STAT_BUSS_ERR = 0xB8,		//从模式下发送的数据字节,收到ACK
	//IIC_STAT_BUSS_ERR = 0xC0,		//从机模式下发送的数据字节,未收到ACK
	//IIC_STAT_BUSS_ERR = 0xC8,		//从模式下发送的最后一个字节,收到ACK
	IIC_STAT_A2W_ACK = 0xD0,		//第二地址字节 + 发送写入位,收到ACK
	IIC_STAT_A2W_NACK = 0xD8,		//第二个地址字节 + 写入位已发送,ACK未发送收到
	IIC_STAT_NOT_STATUS = 0xF8,		//无相关状态信息,INT_FLAG = 0
	IIC_STAT_IIC_ERROR	=	0xF9,	//实测的时候出现F9状态,就是SCL=1,SDA=0,总线出现了异常,IIC从机死机不断电总线不可恢复

}IIC_STAT_Type;


typedef enum
{
	IIC_OPER_ING	=	0,	//正常操作中
	IIC_OPER_END	=	1,	//正常操作结束
	IIC_OPER_NACK	=	2,	//未收到ACK,异常结束
	IIC_OPER_ERROR	=	3,	//总线错误,异常结束
	IIC_OPER_ARB_ERROR = 4,	//总线仲裁错误,异常结束

}IIC_OPER_STATE;


//IIC句柄
typedef struct
{
	IIC_CH_Type ch;			//当前通道
	IIC_TypeDef* IICx;		//当前通道外设结构体
	IIC_SPEED_TYPE	Speed;
	bool isMasterMode;		//是否为主设备模式-目前只支持主设备模式
	IIC_TRAN_TASK TranTask;	//传输任务缓冲区
	IIC_STAT_Type IntStatus;	//中断状态
	bool isDebug;			//是否输出调试信息
	IIC_OPER_STATE OperState;	//当前操作状态,在中断中更新
}IIC_HANDLE;



//IIC通道句柄定义
static IIC_HANDLE sg_IIC_Handle[IIC_CH_COUNT];
//IIC外设结构指针
static const  IIC_TypeDef* const scg_IICx_Base[IIC_CH_COUNT] = { IIC0,IIC1,IIC2,IIC3 };

static void IIC_IntCallBack(IIC_CH_Type ch);//IIC中断函数

#if(_IIC_INT_ENABLE) //中断方式
#include "irq_gic400.h"
static void IIC0_IRQHandler(void) {IIC_IntCallBack(0);}		//IIC0中断回调
static void IIC1_IRQHandler(void) { IIC_IntCallBack(1); }	//IIC1中断回调
static void IIC2_IRQHandler(void) { IIC_IntCallBack(2); }	//IIC2中断回调
static void IIC3_IRQHandler(void) { IIC_IntCallBack(3); }	//IIC3中断回调

static const GIC_IRQ_Typedef scg_IICIrqType[IIC_CH_COUNT] = { GIC_IRQ_I2C0, GIC_IRQ_I2C1, GIC_IRQ_I2C2, GIC_IRQ_I2C3 };	//中断编号
static const void* scg_pIICIrqHandle[IIC_CH_COUNT] = { (const void*)IIC0_IRQHandler,(const void*)IIC1_IRQHandler,(const void*)IIC2_IRQHandler,(const void*)IIC3_IRQHandler}; //中断服务程序

#endif //_IIC_INT_ENABLE



/*************************************************************************************************************************
* 函数		:	static IIC_STAT_Type IIC_WaitStatus(IIC_HANDLE* pHandle)
* 功能		:	等待IIC中断有效
* 参数		:	pHandle:句柄
* 返回		:	IIC_STAT_Type
* 依赖		:	底层宏定义
* 作者		:	cp1300@139.com
* 时间		:	2022-01-18
* 最后修改时间: 	2022-01-18
* 说明		:
*************************************************************************************************************************/
static IIC_STAT_Type IIC_WaitStatus(IIC_HANDLE* pHandle)
{
	

	return pHandle->IICx->STAT;
}

//使能ACK
void IIC_EnableACK(IIC_HANDLE* pHandle) 
{ 
	pHandle->IICx->CNTR |= BIT2;			//收到数据后自动发送ACK
}
//禁止ACK
void IIC_DisableACK(IIC_HANDLE *pHandle)
{
	pHandle->IICx->CNTR &= ~BIT2;			//收到数据后不自动发送ACK
}

//发送STOP
void IIC_SendStop(IIC_HANDLE* pHandle)
{ 
	//pHandle->IICx->CNTR |= BIT3;			//清除中断标志
	pHandle->IICx->CNTR |= BIT4;			//发送完成后将会自动清零	
}
//发送START
void IIC_SendStart(IIC_HANDLE *pHandle)
{
	pHandle->IICx->CNTR |= BIT3;			//清除中断标志
	pHandle->IICx->CNTR |= BIT5;			//发送完成后将会自动清零
}

//IIC软复位
void IIC_SoftReset(IIC_HANDLE* pHandle)
{
	u16 TimeOut = 10;

	pHandle->IICx->SRST = 1;	//复位
	while (pHandle->IICx->SRST && TimeOut)
	{
		TimeOut--;
		SYS_DelayMS(1);
	}
	if (pHandle->IICx->SRST)
	{
		ERROR_S("IIC%d软复位超时\r\n", pHandle->ch);
	}
}




/*************************************************************************************************************************
* 函数	:			bool IIC_Init(IIC_CH_Type ch, IIC_SPEED_TYPE Speed, u16 TimeOutUs)
* 功能	:			硬件IIC初始化
* 参数	:			ch:IIC通道;Speed_KHz:速度;TimeOutUs:操作超时us(兼容性参数,无作用)
* 返回	:			IIC_ERROR
* 依赖	:			底层宏定义
* 作者	:			cp1300@139.com
* 时间	:			2024-07-18
* 最后修改时间 : 		2024-07-18
* 说明	: 			速度只是个大概的计算值,正常情况下只要时钟速度符合要求,
					时钟上升沿到来前数据以及稳定的切换了即可保证通讯稳定性
*************************************************************************************************************************/
bool IIC_Init(IIC_CH_Type ch, IIC_SPEED_TYPE Speed, u16 TimeOutUs)
{
	IIC_HANDLE *pHandle;

	switch (ch)
	{
		case IIC_CH0:	//IIC0
		{
			r_TWI_BGR_REG |= BIT0;		//IIC0时钟使能
			r_TWI_BGR_REG &= ~BIT16;	//IIC0复位
			nop; nop; nop; nop;
			r_TWI_BGR_REG |= BIT16;		//IIC0复位结束
		}break;
		case IIC_CH1:	//IIC1
		{
			r_TWI_BGR_REG |= BIT1;		//IIC1时钟使能
			r_TWI_BGR_REG &= ~BIT17;	//IIC1复位
			nop; nop; nop; nop;
			r_TWI_BGR_REG |= BIT17;		//IIC1复位结束
		}break;
		case IIC_CH2:	//IIC2
		{
			r_TWI_BGR_REG |= BIT2;		//IIC2时钟使能
			r_TWI_BGR_REG &= ~BIT18;	//IIC2复位
			nop; nop; nop; nop;
			r_TWI_BGR_REG |= BIT18;		//IIC2复位结束
		}break;
		case IIC_CH3:	//IIC3
		{
			r_TWI_BGR_REG |= BIT3;		//IIC3时钟使能
			r_TWI_BGR_REG &= ~BIT19;	//IIC3复位
			nop; nop; nop; nop;
			r_TWI_BGR_REG |= BIT19;		//IIC3复位结束
		}break;
		default:
		{
			ERROR_S("初始化IIC失败:无效的IIC通道%d\r\n", ch);
			return FALSE;
		}
	}
	pHandle = &sg_IIC_Handle[ch];									//获取相关通道的句柄
	pHandle->IICx = (IIC_TypeDef *)scg_IICx_Base[ch];				//外设指针
	pHandle->Speed = Speed;									//记录速度
	pHandle->ch = ch;										//记录通道
	pHandle->isDebug = FALSE;
	pHandle->IntStatus = pHandle->IICx->STAT;
	
	pHandle->IICx->CNTR = 0;								//总线禁止
	switch (Speed)	//时钟设置
	{
		case IIC_SPEED_200KHz:
		{
			pHandle->IICx->CCR = BIT7 | ((6 - 1) << 3) | (1 << 0);	//CLK_N=1;CLK_M=5,12MHz/60
		}break;
		case IIC_SPEED_300KHz:
		{
			pHandle->IICx->CCR = BIT7 | ((4 - 1) << 3) | (1 << 0);	//CLK_N=1;CLK_M=5,12MHz/40
		}break;
		case IIC_SPEED_400KHz:
		{
			pHandle->IICx->CCR = BIT7 | ((3 - 1) << 3) | (1 << 0);	//CLK_N=1;CLK_M=5,12MHz/30
		}break;
		default: //100KHz
		{
			pHandle->IICx->CCR = BIT7 | ((12 - 1) << 3) | (1 << 0);	//CLK_N=1;CLK_M=5,12MHz/120
		}break;
	}

	pHandle->IICx->LCR = 0;
	pHandle->IICx->CNTR = BIT6;								//使能IIC
	IIC_SoftReset(pHandle);	//进行软复位
	memset(&pHandle->TranTask, 0, sizeof(IIC_TRAN_TASK));	//任务缓冲区清零
#if(_IIC_INT_ENABLE) //使用中断模式
	GIC_SetIrqPriority(scg_IICIrqType[ch], 3);	                    		//GIC设置一个中断的优先级
	GIC_SetIrqEdgeTriggered(scg_IICIrqType[ch], TRUE);              		//GIC设置一个中断为边沿触发
	GIC_RegisterIRQHandler(scg_IICIrqType[ch], (void (*)(void))scg_pIICIrqHandle[ch]);   		//注册中断服务程序
	GIC_IrqEnable(scg_IICIrqType[ch], TRUE);	                    		//GIC中断使能-中断使能
#else //查询模式

#endif //_IIC_INT_ENABLE



	
	return TRUE;
}




/*************************************************************************************************************************
* 函数		:	static IIC_ERROR IIC_WaitCompletion(IIC_HANDLE* pHandle)
* 功能		:	等待IIC通讯完成
* 参数		:	pHandle:句柄
* 返回		:	IIC_ERROR
* 依赖		:	底层宏定义
* 作者		:	cp1300@139.com
* 时间		:	2024-07-18
* 最后修改时间: 	2024-07-18
* 说明		: 	
*************************************************************************************************************************/
static IIC_ERROR IIC_WaitCompletion(IIC_HANDLE* pHandle)
{
	IIC_ERROR Error = IIC_OK;
	u32 TimeOutMs = (pHandle->TranTask.NeedCount+5)*10 / 100;
	if (TimeOutMs < 2) TimeOutMs = 2;


#if(_IIC_INT_ENABLE) //使用中断模式
	u32 i;

	if (pHandle->isDebug)	//如果开启了调试模式,多给超时时间
	{
		TimeOutMs += pHandle->TranTask.NeedCount + 50;
	}

	for (i = 0; i < TimeOutMs; i++)
	{
		SYS_DelayMS(1);	//延时1ms等待结果
		if (pHandle->OperState != IIC_OPER_ING)	//结束了
		{
			IIC_SendStop(pHandle);		//发送停止
			switch (pHandle->OperState)
			{
				case IIC_OPER_NACK:	//未收到ACK,异常结束
				{
					Error = IIC_NACK;
					goto end_loop;
				}
				case IIC_OPER_ERROR:	//总线错误,异常结束
				{
					Error = IIC_HAL_ERROR;
					goto end_loop;
				}
				case IIC_OPER_ARB_ERROR:	//总线仲裁错误,异常结束
				{
					Error = IIC_HAL_ERROR;
					goto end_loop;
				}
				case IIC_OPER_END:	//传输完成了
				{
					if (pHandle->TranTask.TranCount == pHandle->TranTask.NeedCount) //数据读取完成了
					{
						Error = IIC_OK;
						goto end_loop;
					}
					else
					{
						ERROR_S("IIC%d超时,传输完成,但是数据不对:%d!=!d\r\n", pHandle->ch, pHandle->TranTask.TranCount, pHandle->TranTask.NeedCount);
						Error = IIC_STOP_ERROR;
						goto end_loop;
					}
				}
				default:
				{
					Error = IIC_STOP_ERROR; break;
					goto end_loop;
				}
			}
		}
	}
	//超时了
	ERROR_S("IIC%d超时,中断状态:0x%02X 状态机:%d\r\n", pHandle->ch, pHandle->IICx->STAT, pHandle->TranTask.NextOperate);
	IIC_SendStop(pHandle);		//发送停止
	Error = IIC_TIMEOUT;
	goto end_loop;

#else //查询模式
	u64 RunTime;

	if (pHandle->isDebug)	//如果开启了调试模式,多给超时时间
	{
		TimeOutMs += pHandle->TranTask.NeedCount + 50;
	}
	RunTime = SYS_GetOSRunTime() + TimeOutMs;		//计算超时时间


	while (1)
	{

		while (((pHandle->IICx->CNTR & BIT3) == 0 || pHandle->IICx->STAT == 0) && (pHandle->OperState == IIC_OPER_ING))	//等待中断,没有错误或结束的前提下
		{
			if (SYS_GetOSRunTime() > RunTime)
			{
				ERROR_S("IIC%d超时,中断状态:0x%02X 状态机:%d\r\n", pHandle->ch, pHandle->IICx->STAT, pHandle->TranTask.NextOperate);
				IIC_SendStop(pHandle);		//发送停止
				Error = IIC_TIMEOUT;
				goto end_loop;
			}
		}

		if (pHandle->OperState == IIC_OPER_ING)
		{
			IIC_IntCallBack(pHandle->ch);		//执行中断
		}
		else //报错或结束了
		{
			IIC_SendStop(pHandle);		//发送停止
			switch (pHandle->OperState)
			{
				case IIC_OPER_NACK:	//未收到ACK,异常结束
				{
					Error = IIC_NACK;
					goto end_loop;
				}
				case IIC_OPER_ERROR:	//总线错误,异常结束
				{
					Error = IIC_HAL_ERROR;
					goto end_loop;
				}
				case IIC_OPER_ARB_ERROR:	//总线仲裁错误,异常结束
				{
					Error = IIC_HAL_ERROR;
					goto end_loop;
				}
				case IIC_OPER_END:	//传输完成了
				{
					if (pHandle->TranTask.TranCount == pHandle->TranTask.NeedCount) //数据读取完成了
					{
						Error = IIC_OK;
						goto end_loop;
					}
					else
					{
						ERROR_S("IIC%d超时,传输完成,但是数据不对:%d!=!d\r\n", pHandle->ch, pHandle->TranTask.TranCount, pHandle->TranTask.NeedCount);
						Error = IIC_STOP_ERROR;
						goto end_loop;
					}
				}
				default:
				{
					Error = IIC_STOP_ERROR; break;
					goto end_loop;
				}
			}
		}

		if (SYS_GetOSRunTime() > RunTime)
		{
			ERROR_S("IIC%d超时,中断状态:0x%02X 状态机:%d\r\n", pHandle->ch, pHandle->IICx->STAT, pHandle->TranTask.NextOperate);
			IIC_SendStop(pHandle);		//发送停止
			Error = IIC_TIMEOUT;
			goto end_loop;
		}



	}
#endif //_IIC_INT_ENABLE
end_loop:

	return Error;
}




/*************************************************************************************************************************
* 函数	:			IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
						u8 *pDataBuff, u16 ReadByteNum)
* 功能	:			IIC读取寄存器(可以读取1个或者多个寄存器)
* 参数	:			ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要读取的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;
						pDataBuff:接收的字节数据缓冲区;ReadByteNum:要读取的寄存器数量;
* 返回	:			IIC_ERROR
* 依赖	:			底层宏定义
* 作者	:			cp1300@139.com
* 时间	:			2024-07-20
* 最后修改时间 : 	2024-07-20
* 说明	: 			测试发现HYM8563会异常,出现中断状态0xF9 SCL=1 SDA=0,复位芯片都不行,SDA一直为0
*************************************************************************************************************************/
IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8* pDataBuff, u16 ReadByteNum)
{
	IIC_ERROR Error = IIC_OK;
	IIC_HANDLE* pHandle;
	

	if (ch > (IIC_CH_COUNT - 1) || pDataBuff == NULL || ReadByteNum == 0)
	{
		DEBUG("IIC错误:无效的参数\r\n");
		return IIC_PARAMETER_ERROR;
	}
	pHandle = &sg_IIC_Handle[ch];					//获取相关通道的句柄

	pHandle->IICx->CNTR |= BIT3;					//清除中断标志
	if (pHandle->IICx->CNTR & BIT4)					//如果停止位还没发送完成,等待一下
	{
		INFO_S("IIC%d上次停止位还未发送完成\r\n", pHandle->ch);
		SYS_DelayMS(1);
	}

	//获取总线状态
	if (pHandle->IICx->STAT != IIC_STAT_NOT_STATUS)
	{
		INFO_S("IIC%d总线故障,进行复位\r\n", pHandle->ch);
		IIC_SoftReset(pHandle);
		SYS_DelayMS(1);
	}

	if (TRUE == pHandle->TranTask.isBusy)
	{
		ERROR_S("IIC%d任务忙,无法进行发送操作\r\n", pHandle->ch);
		return IIC_BUSY;
	}
	//准备好任务
	pHandle->TranTask.isBusy = TRUE;			//忙
	pHandle->TranTask.SlaveAddr = SlaveAddr;			//从设备地址,7bit或者10bit
	pHandle->TranTask.is10BitSlaveAddr = (SlaveAddr & IIC_10BIT_ADD_MASK) ? TRUE : FALSE;	//是否为10bit地址,否则为7bit
	pHandle->TranTask.RegAddr = RegAddr;			//寄存器地址
	pHandle->TranTask.is8bitRegAddr = is8bitRegAddr;	//是否为8bit寄存器地址,否则为16bit
	pHandle->TranTask.NeedCount = ReadByteNum;			//要传输的数据数量
	pHandle->TranTask.pDataBuff = pDataBuff;			//要传输的数据缓冲区
	pHandle->TranTask.TranCount = 0;			//已经传输的数据计数
	pHandle->TranTask.isRead = TRUE;			//是否为读取数据,否则为写入数据
	pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_START;	//下一个状态为,等待起始信号发送完成
	pHandle->OperState = IIC_OPER_ING;			//通讯中
	
	pHandle->IICx->EFR = 0;
	if (pHandle->TranTask.NeedCount > 1)		//需要读取多个字节,则使能自动ACK
	{
		IIC_EnableACK(pHandle);						//使能读取数据后需要发送ACK
	}
	else
	{
		IIC_DisableACK(pHandle);					//读取一个字节,不需要发送ACK
	}


	pHandle->IntStatus = pHandle->IICx->STAT;		//获取中断状态
	pHandle->IICx->CNTR |= BIT3;					//清除中断标志

#if(_IIC_INT_ENABLE) //使用中断模式
	pHandle->IICx->CNTR |= BIT7;					//使能中断
#else //查询模式
	pHandle->IICx->CNTR &= ~BIT7;					//关闭中断
#endif //_IIC_INT_ENABLE


	if (pHandle->IICx->STAT != IIC_STAT_NOT_STATUS)
	{
		INFO_S("IIC%d中断状态:0x%02X SCL=%d,SDA=%d\r\n", pHandle->ch, pHandle->IntStatus,
			(pHandle->IICx->LCR & BIT5) ? 1 : 0, (pHandle->IICx->LCR & BIT4) ? 1 : 0);
	}
	
	IIC_SendStart(pHandle);							//发送开始
	Error = IIC_WaitCompletion(pHandle);			//等待IIC通讯完成
#if(_IIC_INT_ENABLE) //使用中断模式
	pHandle->IICx->CNTR &= ~BIT7;					//关闭中断
#endif //_IIC_INT_ENABLE

	pHandle->TranTask.isBusy = FALSE;			//空闲

	return Error;
}










/*************************************************************************************************************************
* 函数	:			IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
						u8 *pDataBuff, u16 WriteByteNum)
* 功能	:			IIC写寄存器(可以写1个或者多个寄存器)
* 参数	:			ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要写入的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;
						pDataBuff:写入的字节数据缓冲区;WriteByteNum:要写入的寄存器数量;
* 返回	:			IIC_ERROR
* 依赖	:			底层宏定义
* 作者	:			cp1300@139.com
* 时间	:			2024-07-20
* 最后修改时间 : 	2024-07-20
* 说明	: 			写入的数据都是小端模式,如果是16bit的寄存器,请写入偶数个数据,并且需要提前进行高低字节对调最后组成高字节在前的数据buff
*************************************************************************************************************************/
IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8* pDataBuff, u16 WriteByteNum)
{
	IIC_ERROR Error = IIC_OK;
	IIC_HANDLE* pHandle;

	if (ch > (IIC_CH_COUNT - 1) || pDataBuff == NULL || WriteByteNum == 0)
	{
		DEBUG("IIC错误:无效的参数\r\n");
		return IIC_PARAMETER_ERROR;
	}
	pHandle = &sg_IIC_Handle[ch];					//获取相关通道的句柄


	if (pHandle->IICx->CNTR & BIT4)					//如果停止位还没发送完成,等待一下
	{
		INFO_S("IIC%d上次停止位还未发送完成\r\n", pHandle->ch);
		SYS_DelayMS(1);
	}

	pHandle->IICx->CNTR |= BIT3;					//清除中断标志
	//获取总线状态
	if (pHandle->IICx->STAT != IIC_STAT_NOT_STATUS)
	{
		INFO_S("IIC%d总线故障,进行复位\r\n", pHandle->ch);
		IIC_SoftReset(pHandle);
		SYS_DelayMS(1);
	}

	if (TRUE == pHandle->TranTask.isBusy)
	{
		ERROR_S("IIC%d任务忙,无法进行发送操作\r\n", pHandle->ch);
		return IIC_BUSY;
	}
	//准备好任务
	pHandle->TranTask.isBusy = TRUE;			//忙
	pHandle->TranTask.SlaveAddr = SlaveAddr;			//从设备地址,7bit或者10bit
	pHandle->TranTask.is10BitSlaveAddr = (SlaveAddr & IIC_10BIT_ADD_MASK) ? TRUE : FALSE;	//是否为10bit地址,否则为7bit
	pHandle->TranTask.RegAddr = RegAddr;			//寄存器地址
	pHandle->TranTask.is8bitRegAddr = is8bitRegAddr;	//是否为8bit寄存器地址,否则为16bit
	pHandle->TranTask.NeedCount = WriteByteNum;			//要传输的数据数量
	pHandle->TranTask.pDataBuff = pDataBuff;			//要传输的数据缓冲区
	pHandle->TranTask.TranCount = 0;			//已经传输的数据计数
	pHandle->TranTask.isRead = FALSE;			//是否为读取数据,否则为写入数据
	pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_START;	//下一个状态为,等待起始信号发送完成
	pHandle->OperState = IIC_OPER_ING;			//通讯中
	
	pHandle->IICx->EFR = 0;
	if (pHandle->TranTask.NeedCount > 1)		//需要读取多个字节,则使能自动ACK
	{
		IIC_EnableACK(pHandle);						//使能读取数据后需要发送ACK
	}
	else
	{
		IIC_DisableACK(pHandle);					//读取一个字节,不需要发送ACK
	}

	pHandle->IntStatus = pHandle->IICx->STAT;		//获取中断状态
	pHandle->IICx->CNTR |= BIT3;					//清除中断标志

#if(_IIC_INT_ENABLE) //使用中断模式
	pHandle->IICx->CNTR |= BIT7;					//使能中断
#else //查询模式
	pHandle->IICx->CNTR &= ~BIT7;					//关闭中断
#endif //_IIC_INT_ENABLE
	if (pHandle->IICx->STAT != IIC_STAT_NOT_STATUS)
	{
		INFO_S("IIC%d中断状态:0x%02X SCL=%d,SDA=%d\r\n", pHandle->ch, pHandle->IntStatus,
			(pHandle->IICx->LCR & BIT5) ? 1 : 0, (pHandle->IICx->LCR & BIT4) ? 1 : 0);
	}
	
	IIC_SendStart(pHandle);							//发送开始
	Error = IIC_WaitCompletion(pHandle);			//等待IIC通讯完成
#if(_IIC_INT_ENABLE) //使用中断模式
	pHandle->IICx->CNTR &= ~BIT7;					//关闭中断
#endif //_IIC_INT_ENABLE

	pHandle->TranTask.isBusy = FALSE;				//空闲

	return Error;
}








/*************************************************************************************************************************
* 函数	:			IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
						u8 *pDataBuff, u16 ReadByteNum)
* 功能	:			IIC读取寄存器(可以读取1个或者多个寄存器)
* 参数	:			ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要读取的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;
						pDataBuff:接收的字节数据缓冲区;ReadByteNum:要读取的寄存器数量;
* 返回	:			IIC_ERROR
* 依赖	:			底层宏定义
* 作者	:			cp1300@139.com
* 时间	:			2020-11-03
* 最后修改时间 : 	2020-11-03
* 说明	: 			测试发现HYM8563会异常,出现中断状态0xF9 SCL=1 SDA=0,复位芯片都不行,SDA一直为0
*************************************************************************************************************************/
void IIC_IntCallBack(IIC_CH_Type ch)
{
	IIC_HANDLE* pHandle;
	u8 data;

	if (ch > (IIC_CH_COUNT - 1))
	{
		return;
	}
	pHandle = &sg_IIC_Handle[ch];					//获取相关通道的句柄

	pHandle->IntStatus = pHandle->IICx->STAT;			//获取中断状态
	switch (pHandle->IntStatus)
	{
		case IIC_STAT_BUSS_ERR :// 0x00,		//总线错误
		{
			pHandle->OperState = IIC_OPER_ERROR;	//总线错误,可以结束了
		}break;
		case IIC_STAT_START:// 0x08,			//START条件已传输
		{
			//写入地址,如果是10bit,就先发送高地址
			if (pHandle->TranTask.is10BitSlaveAddr)
			{
				data = pHandle->TranTask.SlaveAddr >> 8;	//写高2bit地址
				data <<= 1;									//最低位为0,写信号
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d发送高位从机地址(写):0x%02X\r\n", pHandle->ch, data);
				pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_10BIT_ADDR_H;	//等待10bit从机高地址发送完成-写入
			}
			else //直接发送7bit地址
			{
				data = ((pHandle->TranTask.SlaveAddr & 0x7F) << 1) | 0;	//写7bit地址
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d发送7bit从机地址(写):0x%02X\r\n", pHandle->ch, data);
				pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_7BIT_ADDR;	//等待7bit从机地址发送完成-写入
			}
		}break;
		case IIC_STAT_RSTART:// 0x10,			//发送重复START条件,后面发送从机地址,10bit就发送高2bit,7bit就发送低7bit,并且最低bit为1,代表读取
		{
			if (pHandle->TranTask.is10BitSlaveAddr) //如果是10bti地址就是发送高2bit
			{
				data = pHandle->TranTask.SlaveAddr >> 8;
				data <<= 1;
				data |= BIT0;		//读信号
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d重复发送高2bit从机地址(读):0x%02X\r\n", pHandle->ch, data);

			}
			else //7bit地址,直接发送
			{
				data = ((pHandle->TranTask.SlaveAddr & 0x7F) << 1) | BIT0;	//7bit地址
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d重复发送7bit从机地址(读):0x%02X\r\n", pHandle->ch, data);
			}
			pHandle->TranTask.NextOperate = IIC_NEXT_TASK_READ_DATA; //后面开始读取数据了

			if (pHandle->TranTask.TranCount < (pHandle->TranTask.NeedCount - 1))
			{
				IIC_EnableACK(pHandle);		//读取数据后需要发送ACK
			}
			else
			{
				IIC_DisableACK(pHandle);	//当前是最后一个字节,读取完成后发送NACK
			}
		}break;
		case IIC_STAT_AW_ACK:// 0x18,			//发送地址 + 写入位,收到ACK
		{
			if (pHandle->TranTask.is10BitSlaveAddr)	//如果是10bit地址,则写低8bit地址
			{
				data = pHandle->TranTask.SlaveAddr;	//低8bit地址
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d发送低8bit从机地址:0x%02X\r\n", pHandle->ch, data);
				pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_7BIT_ADDR;	//等待7bit从机地址发送完成-写入
			}
			else //否则开始写入寄存器地址,寄存器地址又分为16bit还是8bit
			{
				if (pHandle->TranTask.is8bitRegAddr) //8bit寄存器地址,只需要发一次即可
				{
					data = pHandle->TranTask.RegAddr;
					pHandle->IICx->DATA = data;	//发送数据
					if (pHandle->isDebug) INFO_S("IIC%d发送8bit寄存器地址:0x%02X\r\n", pHandle->ch, data);
					pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_8BIT_REG;	//等待发送8bit寄存器地址
						
				}
				else //需要先发送高8bit地址
				{
					data = pHandle->TranTask.RegAddr>>8;
					pHandle->IICx->DATA = data;	//发送数据
					if (pHandle->isDebug) INFO_S("IIC%d发送16bit寄存器地址高8bit:0x%02X\r\n", pHandle->ch, data);
					pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_16BIT_REG_H;	//等待发送16bit寄存器地址高位
				}
			}
		}break;
		case IIC_STAT_AW_NACK:// 0x20,		//发送地址 + 写入位,未收到ACK
		{
			pHandle->OperState = IIC_OPER_NACK;	//没有收到ACK,可以结束了
		}break;
		case IIC_STAT_WDATA_ACK:// 0x28,		//主模式下发送的数据字节,收到ACK
		{
			switch (pHandle->TranTask.NextOperate)
			{
				case IIC_NEXT_TASK_WAIT_16BIT_REG_H:	//等待发送16bit寄存器地址高位-发完了,就要开始发低8bit寄存器地址了
				{
					data = pHandle->TranTask.RegAddr;
					pHandle->IICx->DATA = data;	//发送数据
					if (pHandle->isDebug) INFO_S("IIC%d发送低8bit寄存器地址:0x%02X\r\n", pHandle->ch, data);
					pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_8BIT_REG;	//等待发送8bit寄存器地址
				}break;
				case IIC_NEXT_TASK_WAIT_8BIT_REG:	//等待低8bit地址发送完成,发送完成了就要根据读写来决定下一步操作了
				{
					if (pHandle->TranTask.isRead)	//读取数据,那么就还要发送一次开始信号
					{
						IIC_SendStart(pHandle);		//发送重复的开始信号
						if (pHandle->isDebug) INFO_S("IIC%d重复发送开始信号\r\n", pHandle->ch);
						pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_RSTART;		//等待重复开始信号
					}
					else //是写入数据,则直接可以开始写入第一个字节啦
					{
						data = pHandle->TranTask.pDataBuff[pHandle->TranTask.TranCount++];
						pHandle->IICx->DATA = data;
						if (pHandle->isDebug) INFO_S("IIC%d写入数据:0x%02X(%d)\r\n", pHandle->ch, data, pHandle->TranTask.TranCount);

						pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_WRITE_DATA;	//等待发送完成,正常会收到ACK,收到ACK后发送下一个字节
					}
				}break;
				case IIC_NEXT_TASK_WAIT_WRITE_DATA:	//发送数据收到ACK了
				{
					if (pHandle->TranTask.TranCount < pHandle->TranTask.NeedCount) //还要继续写入
					{
						data = pHandle->TranTask.pDataBuff[pHandle->TranTask.TranCount++];
						pHandle->IICx->DATA = data;
						if (pHandle->isDebug) INFO_S("IIC%d写入数据:0x%02X(%d)\r\n", pHandle->ch, data, pHandle->TranTask.TranCount);

						pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_WRITE_DATA;	//等待发送完成,正常会收到ACK,收到ACK后发送下一个字节
					}
					else //发送完成了,发送stop
					{
						pHandle->TranTask.NextOperate = IIC_NEXT_TASK_END;
						IIC_SendStop(pHandle);		//发送停止
						pHandle->OperState = IIC_OPER_END;	//传输完成了
						if (pHandle->isDebug) INFO_S("IIC%d写入数据完成,发送停止位\r\n");
					}
				}break;
				default: break;	//正常不应该执行到此处
			}
		}break;
		case IIC_STAT_WDATA_NACK:// 0x30,		//主模式下传输的数据字节,未收到ACK
		{
			pHandle->OperState = IIC_OPER_NACK;	//没有收到ACK,可以结束了
		}break;
		case IIC_STAT_ARB_ERR:// 0x38,		//仲裁在地址或数据字节中丢失
		{
			pHandle->OperState = IIC_OPER_ARB_ERROR;	//总线仲裁错误,可以结束了
		}break;
		case IIC_STAT_AR_ACK:// 0x40,			//发送地址 + 读取位,收到ACK
		{
			//开始准备读取数据了,这一步是正常的,啥都不用干,后面清除中断, 之后等待下次中断,就可以读取数据了
		}break;
		case IIC_STAT_AR_NACK:// 0x48,		//发送地址 + 读取位,未收到ACK
		{
			pHandle->OperState = IIC_OPER_NACK;	//没有收到ACK,可以结束了
		}break;
		case IIC_STAT_RDATA_ACK:// 0x50,		//主模式下接收到数据字节,发送ACK
		{
			data = pHandle->IICx->DATA;
			pHandle->TranTask.pDataBuff[pHandle->TranTask.TranCount++] = data;
			if (pHandle->isDebug) INFO_S("IIC%d读取数据:0x%02X(%d)\r\n", pHandle->ch, data, pHandle->TranTask.TranCount);
			if (pHandle->TranTask.TranCount < (pHandle->TranTask.NeedCount - 1))
			{
				IIC_EnableACK(pHandle);	//读取数据后需要发送ACK
			}
			else
			{
				IIC_DisableACK(pHandle);	//当前是最后一个字节,读取完成后发送NACK
			}
			pHandle->TranTask.NextOperate = IIC_NEXT_TASK_READ_DATA;
		}break;
		case IIC_STAT_RDATA_NACK:// 0x58,		//主模式下接收到数据字节,未发送ACK
		{
			data = pHandle->IICx->DATA;
			pHandle->TranTask.pDataBuff[pHandle->TranTask.TranCount++] = data;
			if (pHandle->isDebug) INFO_S("IIC%d读取最后数据:0x%02X(%d)\r\n", pHandle->ch, data, pHandle->TranTask.TranCount);
			pHandle->TranTask.NextOperate = IIC_NEXT_TASK_END;
			IIC_SendStop(pHandle);		//发送停止
			pHandle->OperState = IIC_OPER_END;	//传输完成了

		}break;
			
		case IIC_STAT_A2W_ACK:// 0xD0,		//第二地址字节 + 发送写入位,收到ACK
		{
			//写入寄存器地址,分为16bit还是8bit寄存器地址
			if (pHandle->TranTask.is8bitRegAddr) //8bit寄存器地址,只需要发一次即可
			{
				data = pHandle->TranTask.RegAddr;
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d发送8bit寄存器地址:0x%02X\r\n", pHandle->ch, data);
				pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_8BIT_REG;	//等待发送8bit寄存器地址

			}
			else //需要先发送高8bit地址
			{
				data = pHandle->TranTask.RegAddr >> 8;
				pHandle->IICx->DATA = data;	//发送数据
				if (pHandle->isDebug) INFO_S("IIC%d发送16bit寄存器地址高8bit:0x%02X\r\n", pHandle->ch, data);
				pHandle->TranTask.NextOperate = IIC_NEXT_TASK_WAIT_16BIT_REG_H;	//等待发送16bit寄存器地址高位
			}
		}break;
		case IIC_STAT_A2W_NACK:// 0xD8,		//第二个地址字节 + 写入位已发送,ACK未发送收到
		{
			pHandle->OperState = IIC_OPER_NACK;	//没有收到ACK,可以结束了
		}break;
		case IIC_STAT_NOT_STATUS:// 0xF8,		//无相关状态信息,INT_FLAG = 0
		{

		}break;
		case IIC_STAT_IIC_ERROR:// 0xF9,	//实测的时候出现F9状态,就是SCL=1,SDA=0,总线出现了异常,IIC从机死机不断电总线不可恢复
		{
			pHandle->OperState = IIC_OPER_ERROR;	//总线错误,可以结束了
		}break;
		default:
		{
			
		}break;
	}

	pHandle->IICx->CNTR |= BIT3;				//清除中断标志
}

然后是测试代码


//T113-S3 IIC测试
void IIC_Test(void)
{
	IIC_ERROR iic_error;
	u8 buff[32];

	IIC_Init(IIC_CH2, IIC_SPEED_400KHz, 500);//硬件IIC初始化

	SYS_GPIOx_OneInit(GPIOG, 14, AF_FUN, 3, IO_LEVEL0); //PG14 IIC2 SCL
	SYS_GPIOx_OneInit(GPIOG, 15, AF_FUN, 3, IO_LEVEL0); //PG15 IIC2 SDA

	buff[0] = 0;	//测试写入HYM8563寄存器0
	iic_error = IIC_MasterWriteReg(IIC_CH2, 0x51, 0X00, TRUE, buff, 1);	//IIC写入取寄存器(可以写入1个或者多个寄存器)
	if (iic_error == IIC_OK)
	{
		INFO_S("IIC2写入:0x%02X 完成\r\n", buff[0]);
	}
	else
	{
		INFO_S("IIC2写入失败,错误:%d\r\n", iic_error);
	}


	buff[0] = 0;	//测试写入HYM8563寄存器0x0D
	iic_error = IIC_MasterWriteReg(IIC_CH2, 0x51, 0X0D, TRUE, buff, 1);	//IIC写入取寄存器(可以写入1个或者多个寄存器)
	if (iic_error == IIC_OK)
	{
		INFO_S("IIC2写入:0x%02X 完成\r\n", buff[0]);
	}
	else
	{
		INFO_S("IIC2写入失败,错误:%d\r\n", iic_error);
	}

	buff[0] = 0;	//清除数据

	iic_error = IIC_MasterReadReg(IIC_CH2, 0x51, 0X00, TRUE, buff, 1);	//IIC读取寄存器(可以读取1个或者多个寄存器)
	if (iic_error == IIC_OK)
	{
		INFO_S("IIC2读取成功:0x%02X\r\n", buff[0]);
	}
	else
	{
		INFO_S("IIC2读取失败,错误:%d\r\n", iic_error);
	}

	while (1)
	{
		iic_error = IIC_MasterReadReg(IIC_CH2, 0x51, 0X02, TRUE, buff, 3);	//IIC读取寄存器(可以读取1个或者多个寄存器)
		if (iic_error == IIC_OK)
		{
			INFO_S("IIC2读取成功:0x%02X 0x%02X 0x%02X\r\n", buff[0], buff[1], buff[2]);
		}
		else
		{
			INFO_S("IIC2读取失败,错误:%d\r\n", iic_error);
		}

		SYS_DelayMS(1000);
	}

}

测试是能正常读取数据,有正常的ACK,但是时间没有走,怀疑是RTC芯片挑晶振,之前使用linux的时候也是硬件RTC时间不走,最后换了芯片才解决。

GICC->->IIDR:0x202143B
[     2.713414]  [INFO] IIC2写入:0x00 完成
[     2.713677]  [INFO] IIC2写入:0x00 完成
[     2.713993]  [INFO] IIC2读取成功:0x00
[     2.714359]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     3.714503]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     4.714502]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     5.714503]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     6.714504]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     7.714502]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     8.714502]  [INFO] IIC2读取成功:0x00 0x00 0x01
[     9.714502]  [INFO] IIC2读取成功:0x00 0x00 0x01
[    10.714501]  [INFO] IIC2读取成功:0x00 0x00 0x01
[    11.714503]  [INFO] IIC2读取成功:0x00 0x00 0x01

如果需要详细的调试信息,可以开启调试

pHandle->isDebug = FALSE;								//调试开关

相关推荐

  1. 裸机、应用、驱动

    2024-07-21 13:32:04       27 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 13:32:04       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 13:32:04       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 13:32:04       45 阅读
  4. Python语言-面向对象

    2024-07-21 13:32:04       55 阅读

热门阅读

  1. linux的shell的date命令的加号“+“的作用

    2024-07-21 13:32:04       20 阅读
  2. 【Python大写字符串中每一个单词的首字母】

    2024-07-21 13:32:04       17 阅读
  3. 主页目录导航

    2024-07-21 13:32:04       20 阅读
  4. Mechanize:自动化Web交互的利器

    2024-07-21 13:32:04       19 阅读
  5. 增量预训练和微调的区别

    2024-07-21 13:32:04       19 阅读
  6. Allure 和 JUnit 4结合学习

    2024-07-21 13:32:04       18 阅读
  7. vue3 学习笔记17 -- echarts的使用

    2024-07-21 13:32:04       22 阅读