GPIO模拟I2C

MTK2502平台GPIO模拟I2C实现

 

#include "kal_release.h"
#include "pxs_custom.h"
#include "drv_comm.h"
#include "us_timer.h"
#include "dcl.h"

extern const char gpio_ms_i2c_clk_pin;
extern const char gpio_ms_i2c_data_pin;

#define MS_SCL	gpio_ms_i2c_clk_pin
#define MS_SDA	gpio_ms_i2c_data_pin

/******************************************************
	I2C header (slaver address|W/R)   macro define
*******************************************************/
#define MS_SLAVEADDR_W	((0x33 << 1) + 0)	//0x0001 0110 0x18*2
#define MS_SLAVEADDR_R	((0x33 << 1) + 1)	//0x0001 0111  0x19

/******************************************************
	GPIO macro define for software I2C
*******************************************************/
#define MS_CLK_PIN_GPIO_MODE		GPIO_ModeSetup(MS_SCL,0)
#define MS_DATA_PIN_GPIO_MODE		GPIO_ModeSetup(MS_SDA,0)
#define MS_I2C_CLK_OUTPUT			GPIO_InitIO(OUTPUT,MS_SCL)
#define MS_I2C_DATA_OUTPUT			GPIO_InitIO(OUTPUT,MS_SDA)
#define MS_I2C_DATA_INPUT		   	GPIO_InitIO(INPUT,MS_SDA)
#define MS_I2C_CLK_HIGH				GPIO_WriteIO(1,MS_SCL)
#define MS_I2C_CLK_LOW				GPIO_WriteIO(0,MS_SCL)
#define MS_I2C_DATA_HIGH			GPIO_WriteIO(1,MS_SDA)
#define MS_I2C_DATA_LOW				GPIO_WriteIO(0,MS_SDA)
#define MS_I2C_GET_BIT				GPIO_ReadIO(MS_SDA)

void I2C_DELAY(kal_uint32 delay)
{
	kal_uint32 tick, duration;
	
	tick = drv_get_current_time();
	do{
		duration = drv_get_duration_ms(tick);
	}while(duration < delay);
}

void PAH_i2c_udelay(kal_uint32 delay)
{
	kal_uint32 ust = 0; //ust_get_current_time
	kal_uint32 count = 0;
	kal_uint32 break_count = 0;
	
	ust = ust_get_current_time();
	do{
		if(ust_get_current_time() != ust)
			count++;
		else
			break_count++;
	}while((count < delay) && (break_count < 0xFFFFFF));
}


void PAH_i2c_start(void)
{
	MS_CLK_PIN_GPIO_MODE;
	MS_I2C_CLK_OUTPUT;

	MS_DATA_PIN_GPIO_MODE;
	MS_I2C_DATA_OUTPUT;
	
	MS_I2C_DATA_HIGH;
	MS_I2C_CLK_HIGH;
	PAH_i2c_udelay(40);		//20
	MS_I2C_DATA_LOW;
	PAH_i2c_udelay(20);		//10
	MS_I2C_CLK_LOW;
	PAH_i2c_udelay(20);		//10
}

void PAH_i2c_stop(void)
{
	MS_I2C_CLK_OUTPUT;
	MS_I2C_DATA_OUTPUT;
	
	PAH_i2c_udelay(20);		//10
	MS_I2C_CLK_HIGH;
	PAH_i2c_udelay(20);		//10
	MS_I2C_DATA_HIGH;
}

void PAH_i2c_one_clk(void)
{
	PAH_i2c_udelay(10);		//5
	MS_I2C_CLK_HIGH;
	PAH_i2c_udelay(20);		//10
	MS_I2C_CLK_LOW;
	PAH_i2c_udelay(10);		//5
}

kal_uint8 pah_ReadByteAck(void)
{
	kal_int8 i;
	kal_uint8 data;

	MS_I2C_DATA_INPUT; 
	data = 0; 
	
	for (i=7; i>=0; i--) 
	{
		if (MS_I2C_GET_BIT)
		{
			data |= (0x01<<i);
		}
		PAH_i2c_one_clk();
	}			                                

	MS_I2C_DATA_OUTPUT;                    
	MS_I2C_DATA_LOW;                       
	PAH_i2c_one_clk();                         

	return data;
}

kal_uint8 pah_ReadByteNAck(void)
{
	kal_int8 i;
	kal_uint8 data;

	MS_I2C_DATA_INPUT; 
	data = 0; 
	
	for (i=7; i>=0; i--) 
	{
		if (MS_I2C_GET_BIT)
		{
			data |= (0x01<<i);
		}
		PAH_i2c_one_clk();
	}			                                

	MS_I2C_DATA_OUTPUT;                                           
	MS_I2C_DATA_HIGH;
	PAH_i2c_one_clk();                         
	
	return data;
}

void pah_SendByte(kal_uint8 sData) 
{
	kal_int8 i;
	
	for (i=7; i>=0; i--) 
	{            
		if ((sData>>i)&0x01) 
		{               
			MS_I2C_DATA_HIGH;	              
		} 
		else 
		{ 
			MS_I2C_DATA_LOW;                  
		}
		PAH_i2c_one_clk();                        
	}		
}

kal_bool pah_ChkAck(void)
{
	MS_I2C_DATA_INPUT;
	PAH_i2c_udelay(10);		//5
	MS_I2C_CLK_HIGH;
	PAH_i2c_udelay(10);		//5

	if(MS_I2C_GET_BIT)		//Non-ack
	{
		PAH_i2c_udelay(10);	//5
		MS_I2C_CLK_LOW;
		PAH_i2c_udelay(10);	//5
		MS_I2C_DATA_OUTPUT;
		MS_I2C_DATA_LOW;
		
		return KAL_FALSE;
	}
	else					//Ack
	{
		PAH_i2c_udelay(10);	//5
		MS_I2C_CLK_LOW;
		PAH_i2c_udelay(10);	//5
		MS_I2C_DATA_OUTPUT;
		MS_I2C_DATA_LOW;

		return KAL_TRUE;
	}
}

void pah_Restart(void)
{
	MS_I2C_CLK_OUTPUT;
	MS_I2C_DATA_OUTPUT;

	PAH_i2c_udelay(40);
	MS_I2C_DATA_HIGH;
	PAH_i2c_udelay(20);		//10
	MS_I2C_CLK_HIGH;
	PAH_i2c_udelay(40);
	MS_I2C_DATA_LOW;
	PAH_i2c_udelay(20);		//10
	MS_I2C_CLK_LOW;
	PAH_i2c_udelay(20);		//10
}

void PAH8001ei_DelayMS(kal_uint16 delay)
{
	kal_uint16 i=0;

	for(i=0; i<delay; i++)
	{
		PAH_i2c_udelay(1000);
	}
}

/*
 *	读寄存器
 */
kal_bool pah8001ei_reg_read( kal_uint8 RegAddr,kal_uint8* Data)
{
	PAH_i2c_start();						//start bit
	pah_SendByte(MS_SLAVEADDR_W);		//slave address|write bit
	if(KAL_FALSE == pah_ChkAck())		//check Ack bit
	{
		//TO_DO: display ack check fail when send write id		
		//ms_dbg_print(MOD_AUX, "ack fail when send wid in readbytes");
		//ms_dbg_print_ps("ack fail when send wid in readbytes\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}
		
	pah_SendByte(RegAddr);				//send RegAddr
	if(KAL_FALSE == pah_ChkAck())		//check Ack bit
	{
		//TO_DO: display ack check fail when send RegAddr
		//ms_dbg_print(MOD_AUX, "ack fail when send Reg in readbytes");
		//ms_dbg_print_ps("ack fail when send Reg in readbytes\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	pah_Restart();						//restart bit

	pah_SendByte(MS_SLAVEADDR_R);		//slave address|read bit
	if(KAL_FALSE == pah_ChkAck())
	{
		//TO_DO: display ack check fail when send read id		
		//ms_dbg_print(MOD_AUX, "ack fail when send rid in readbytes");
		//ms_dbg_print_ps("ack fail when send rid in readbytes\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	*Data = pah_ReadByteNAck();

	PAH_i2c_stop();						//stop bit

	//TO_DO: add debug code to display the data received

	return KAL_TRUE;
	
}

/*
 *	连续读寄存器
 */
kal_bool PAH8001ei_ConReadBytes(kal_uint8* Data, kal_uint8 RegAddr, kal_uint16 Length)
{
	kal_uint8* Data_ptr;
	kal_uint16 i;

	Data_ptr = Data;
	
	PAH_i2c_start();						//start bit
	pah_SendByte(MS_SLAVEADDR_W);		//slave address|write bit
	if(KAL_FALSE == pah_ChkAck())		//check Ack bit
	{
		//TO_DO: display ack check fail when send write id		
		//ms_dbg_print(MOD_AUX, "ack fail when send wid in conread");
		//ms_dbg_print_ps("ack fail when send wid in conread\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}
		
	pah_SendByte(RegAddr);				//send RegAddr
	if(KAL_FALSE == pah_ChkAck())		//check Ack bit
	{
		//TO_DO: display ack check fail when send RegAddr		
		//ms_dbg_print(MOD_AUX, "ack fail when send Reg in conread");
		//ms_dbg_print_ps("ack fail when send Reg in conread\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	pah_Restart();						//restart bit

	pah_SendByte(MS_SLAVEADDR_R);		//slave address|read bit
	if(KAL_FALSE == pah_ChkAck())
	{
		//TO_DO: display ack check fail when send read id		
		//ms_dbg_print(MOD_AUX, "ack fail when send rid in conread");
		//ms_dbg_print_ps("ack fail when send rid in conread\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	for(i=Length; i>1; i--)
	{
		*Data_ptr = pah_ReadByteAck();	//read byte with ack
		Data_ptr++;
	}
	
	*Data_ptr = pah_ReadByteNAck();		//read byte with non-ack to stop reading

	PAH_i2c_stop();						//stop bit

	//TO_DO: add debug code to display the data received

	return KAL_TRUE;
}

/*
 *	写寄存器
 */
kal_bool pah8001ei_reg_write(kal_uint8 RegAddr, kal_uint8 Data)
{
	PAH_i2c_start();						//start bit

	pah_SendByte(MS_SLAVEADDR_W);		//slave address|write bit
	if(KAL_FALSE == pah_ChkAck())		//check Ack bit
	{
		//TO_DO: display check ack fail when send write id
		//ms_dbg_print(MOD_AUX, "ack fail when send wid in writebytes");		
		//ms_dbg_print_ps("ack fail when send wid in writebytes\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	pah_SendByte(RegAddr);				//send RegAddr
	if(KAL_FALSE == pah_ChkAck())		//check Ack bit
	{
		//TO_DO: display check ack fail when send RegAddr
		//ms_dbg_print(MOD_AUX, "ack fail when send Reg in wirtebytes");
		//ms_dbg_print_ps("ack fail when send Reg in wirtebytes\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	pah_SendByte(Data);					//send parameter
	if(KAL_FALSE == pah_ChkAck())
	{
		//TO_DO: display check ack fail when send data
		//ms_dbg_print(MOD_AUX, "ack fail when send para in writebytes");
		//ms_dbg_print_ps("ack fail when send para in writebytes\n\r");
		PAH_i2c_stop();
		return KAL_FALSE;
	}

	PAH_i2c_stop();						//stop bit

	return KAL_TRUE;
}


/*
 *	写一个寄存器
 */
void writeRegister(kal_uint8 reg_addr, kal_uint8 value)
{
	kal_bool ret = KAL_FALSE;

	ret = pah8001ei_reg_write(reg_addr, value);
	if(ret == KAL_FALSE) {
		kal_prompt_trace(MOD_MMI, "[LXZ]writeRegister error reg_addr = %x, value = %x", reg_addr, value);
	}
}

/*
 *	读一个寄存器
 */
kal_uint8 readRegister(kal_uint8 reg_addr)
{
	kal_uint8 temp = 0;
	kal_bool ret = KAL_FALSE;

	ret = pah8001ei_reg_read(reg_addr, &temp);

	if (ret == KAL_FALSE) {
		kal_prompt_trace(MOD_MMI, "[LXZ]readRegister error reg_addr = %x value = %x", reg_addr, temp);
	}

	return temp;
}

/*
 *	读多寄存器
 */
void readRegisterCont(kal_uint8 reg_addr, kal_uint8 *buffer, kal_uint8 length)
{
	kal_bool ret = KAL_FALSE;

	ret = PAH8001ei_ConReadBytes(buffer, reg_addr, length);
	if (ret == KAL_FALSE) {
		kal_prompt_trace(MOD_MMI, "[LXZ]readRegisterCont error reg_addr = %x", reg_addr);
	}
}


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值