模拟IIC驱动(DSP) Am4096

使用模拟IIC驱动编码器芯片AM4096 ,使用IIC驱动的目的主要是想要读取电机的绝对角度,下图为AM4096的寄存器地址图;

使用的芯片是DSP的28035:

模拟IIC驱动(DSP) Am4096_第1张图片

 

 模拟IIC代码如下,实测可以使用:

#define IIC_SDA_H		   (GpioDataRegs.GPASET.bit.GPIO18   = 1)
#define IIC_SDA_L		   (GpioDataRegs.GPACLEAR.bit.GPIO18 = 1)
#define READ_IICSDA	       (GpioDataRegs.GPADAT.bit.GPIO18)
#define IIC_SCL_H		   (GpioDataRegs.AIOSET.bit.AIO14    = 1)
#define IIC_SCL_L		   (GpioDataRegs.AIOCLEAR.bit.AIO14  = 1)

Uint16 wIICDELAY = 5;  //延时  us 5
Uint8  bySla_ADDr = 0x00;
void SDA_SET_INPUT(void)
{
     EALLOW;
     GpioCtrlRegs.GPADIR.bit.GPIO18  = 0;// 1=OUTput,  0=INput
     EDIS;
}

void SDA_SET_OUTPUT(void)
{
     EALLOW;
     GpioCtrlRegs.GPADIR.bit.GPIO18  = 1;// 1=OUTput,  0=INput
     EDIS;
}


/*******************************************************************************
* Function Name  : IIC_Init
* Description    : I2C 初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_Init(void)
{
	SDA_SET_OUTPUT();

	IIC_SDA_H;
	IIC_SCL_H;
}

/*******************************************************************************
* Function Name  : IIC_Start
* Description    : I2C 起始信号
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_Start()
{
	SDA_SET_OUTPUT();

	IIC_SCL_H;
	IIC_SDA_H;
	DSP28x_usDelay(wIICDELAY*2);
	IIC_SDA_L;
	DSP28x_usDelay(wIICDELAY);
	IIC_SCL_L;
}

/*******************************************************************************
* Function Name  : IIC_Stop
* Description    : I2C 停止信号
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_Stop()
{
	SDA_SET_OUTPUT();

	IIC_SCL_L;
	IIC_SDA_L;
	DSP28x_usDelay(wIICDELAY);
	IIC_SCL_H;
	DSP28x_usDelay(wIICDELAY);
	IIC_SDA_H;
	DSP28x_usDelay(wIICDELAY);
}

/*******************************************************************************
* Function Name  : IIC_Wait_Ack
* Description    : I2C 等待数据接收方反馈ACK
* Input          : None
* Output         : None
* Return         : 1,接收应答失败
*                  0,接收应答成功
*******************************************************************************/
Uint8 IIC_Wait_Ack(void)
{
	Uint16 ErrTime = 0;
	SDA_SET_INPUT();
	IIC_SDA_H;
	DSP28x_usDelay(1);

	IIC_SCL_H;
	DSP28x_usDelay(1);
	while(READ_IICSDA == 1)
	{
		ErrTime++;
		if(ErrTime>5000)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL_L;
	return 0;
}

/*******************************************************************************
* Function Name  : IIC_Set_Ack
* Description    : I2C 产生ACK应答
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_Set_Ack(void)
{
	IIC_SCL_L;

	SDA_SET_OUTPUT();
	IIC_SDA_L;
	DSP28x_usDelay(wIICDELAY);
	IIC_SCL_H;
	DSP28x_usDelay(wIICDELAY*2);
	IIC_SCL_L;
}

/*******************************************************************************
* Function Name  : IIC_No_Ack
* Description    : I2C 不产生ACK应答
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_No_Ack(void)
{
	IIC_SCL_L;

	SDA_SET_OUTPUT();
	IIC_SDA_H;
	DSP28x_usDelay(wIICDELAY);
	IIC_SCL_H;
	DSP28x_usDelay(wIICDELAY*2);
	IIC_SCL_L;
}

/*******************************************************************************
* Function Name  : IIC_Send_Byte
* Description    : I2C 发送一个字节
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_Send_Byte(Uint8 val)
{
	Uint8 i;
	SDA_SET_OUTPUT();

	IIC_SCL_L;
	for(i=0; i<8; i++)
	{
		if((val & 0x80))
		{
			IIC_SDA_H;
		}
		else
		{
			IIC_SDA_L;
		}
		DSP28x_usDelay(wIICDELAY);

		val <<= 1;
		IIC_SCL_H;
		DSP28x_usDelay(wIICDELAY);

		IIC_SCL_L;
	}
}

/*******************************************************************************
* Function Name  : IIC_Read_Byte
* Description    : I2C 读1个字节
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
Uint8 IIC_Read_Byte(void)
{
	Uint8 i = 0;
	Uint8 val = 0;
	SDA_SET_INPUT();

	for (i=0; i<8; i++)
	{
		IIC_SCL_L;
		DSP28x_usDelay(wIICDELAY*2);//延时等待SDA数据稳定

		IIC_SCL_H;
		val = val << 1;
		//读取SDA状态
		if(READ_IICSDA == 1)
		{
			val++;
		}
		DSP28x_usDelay(wIICDELAY);

	}

	IIC_SCL_L;
	DSP28x_usDelay(wIICDELAY/2);
	return val;
}

/*******************************************************************************
* Function Name  : IIC_Write_Data
* Description    : I2C 写数据
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void IIC_Write_Data(Uint8 i2c_addr,Uint8 *data,Uint8 len)
{
	Uint8 j;

	IIC_Start();
	IIC_Send_Byte(i2c_addr);
    IIC_Wait_Ack();
    for (j=0; j> 15) & 0x01)//数据不准确时
	{
		res_Rpos = 0xFFFF;
	}
	return res_Rpos;
}
/*******************************************************************************
* Function Name  : IIC_Read_AM4096_APos
* Description    : 获取编码器绝对位置
* Input          : None
* Output         : None
* Return         : 位置信息0-4096(0-360度)
*******************************************************************************/
Uint16 IIC_Read_AM4096_APos(void)
{
	Uint8  Apos_Addr = 33;//寄存器地址 绝对位置
	Uint8  buf[2];
	Uint16 res_Apos = 0xFFFF;

	DINT;
	if(IIC_Read_AM4096_data(Apos_Addr,buf,2) == SUCCESS)
	{
		res_Apos = ((Uint16)((buf[0]<<8) + (buf[1])));
		if((res_Apos >> 15) & 0x01)//数据不准确时  判断标志位SRCH
		{
			res_Apos = 0xFFFF;
		}
	}
	EINT;

	return res_Apos;
}
Uint16 Get_Motor_Apos(void)//获取电机绝对位置  0~4096
{
	Uint16 ReadCnt = 0;
	Uint16 val_apos = 0xFFFF;

	while(ReadCnt <10)//最多读十次
	{
		ReadCnt ++;
		val_apos = IIC_Read_AM4096_APos();
		if(val_apos != 0xFFFF)
		{
			return val_apos;
		}
	}
	return val_apos;
}
/*******************************************************************************
* Function Name  : SSI_ReadData
* Description    : SSI 读数据函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SSI_ReadData(Uint16 data)
{
	Uint16 cnt = 0;
	SDA_SET_OUTPUT();
	IIC_SDA_H;
	IIC_SCL_H;//初始时钟为高
	DSP28x_usDelay(10);

	IIC_SCL_L;//第一次时钟拉低
	DSP28x_usDelay(10);
	for(cnt =0; cnt<12; cnt++)//只读取12位的数据
	{
		IIC_SCL_H;//拉高读取数据
		SDA_SET_INPUT();
		data += (READ_IICSDA<<(12-cnt));
		DSP28x_usDelay(10);

		IIC_SCL_L;//时钟拉低,准备下一次读取
		DSP28x_usDelay(10);
	}
	SDA_SET_OUTPUT();
	IIC_SDA_L;
	IIC_SCL_H;//结束时钟为高
	DSP28x_usDelay(10);
	IIC_SDA_H;
}

 

你可能感兴趣的:(嵌入式,编程)