i2c.c 4.51 KB

#include "HW_MCUIO.h"//#include "stm32f4xx_hal.h"
#include "platform.h"
#include "function.h"

#define I2C_PORT  	    GPIOB
#define I2C_SCK         GPIO_PIN_8// GPIO_PIN_6
#define I2C_SDA         GPIO_PIN_9// GPIO_PIN_7

/*
This i2c driver from stm32F1xx; we should add delay when operation io, 
because the stm32F4 much fast (The main frequency of stm32F4xx is 168M) !!
F4系列速度太快,需要加延时,读写才正常!!!*/
static void i2c_delay(unsigned short dy)
{
	unsigned short i;	
	for(i=0;i<dy;i++);
}


#define 	I2C_IO_DY		5//1//

#define		SDA_1		    {HW_GPIO_SetPin(I2C_PORT, I2C_SDA);i2c_delay(I2C_IO_DY);}
#define		SDA_0			{HW_GPIO_ResetPin(I2C_PORT, I2C_SDA);i2c_delay(I2C_IO_DY);}
#define		SCK_1			{HW_GPIO_SetPin(I2C_PORT, I2C_SCK);i2c_delay(I2C_IO_DY);}
#define		SCK_0			{HW_GPIO_ResetPin(I2C_PORT, I2C_SCK);i2c_delay(I2C_IO_DY);}
#define		READ_SDA	    HW_GPIO_ReadPin(I2C_PORT, I2C_SDA)



void i2c_init( void )
{
	HW_GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = I2C_SDA |I2C_SCK;
    GPIO_InitStruct.Mode = HW_GPIO_MODE_OUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = HW_GPIO_SPEED_HIGH;
    HW_GPIO_Init(I2C_PORT, &GPIO_InitStruct);	
}


void SET_SDA_IN(void){
    HW_GPIO_InitTypeDef GPIO_InitStruct = {0};	
    GPIO_InitStruct.Pin = I2C_SDA;
    GPIO_InitStruct.Mode = HW_GPIO_MODE_IPU;//GPIO_MODE_OUTPUT_PP
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = HW_GPIO_SPEED_HIGH;
    HW_GPIO_Init(I2C_PORT, &GPIO_InitStruct);	
}

void SET_SDA_OUT(void){
    HW_GPIO_InitTypeDef GPIO_InitStruct = {0};	
    GPIO_InitStruct.Pin = I2C_SDA;
    GPIO_InitStruct.Mode = HW_GPIO_MODE_OUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    GPIO_InitStruct.Speed = HW_GPIO_SPEED_HIGH;
    HW_GPIO_Init(I2C_PORT, &GPIO_InitStruct);	
}



void i2c_start(void)
{
    SDA_1
    SCK_1
    SDA_0
    SCK_0
}


void i2c_stop(void)
{
    SDA_0
    SCK_1
    SDA_1
    SCK_0
}


unsigned char i2c_send_byte(unsigned char byt)
{
	unsigned char i;
	
	SET_SDA_OUT();
	for(i=0;i<8;i++){
		if((byt<<i)&0x80)	SDA_1
		else 	SDA_0
			
		SCK_1
		SCK_0								
	}//for
	
	//2,
	SET_SDA_IN();
	SCK_1 
	for(i=0;i<100;i++){	
		if(READ_SDA==0){
			SCK_0
			SET_SDA_OUT();
			return 1;//ok
		}
	}//for
	SCK_0		
	SET_SDA_OUT();

	return 0;	//fail
}


unsigned char i2c_read_byte(void)
{
	
	unsigned char i;
	unsigned char byt=0;
	SET_SDA_IN();
	for(i=0;i<8;i++){
		byt <<=1;
		SCK_1
		if(READ_SDA)	byt |=1;
		SCK_0;										
	}//for
	
	SET_SDA_OUT();	
	SDA_0//must
	SCK_1
	SCK_0	
	return byt;
}

#define     EE_PAGE_SIZE    32
//---------------------------------- E2prom application --------------------------------------------
void EE_WriteBytes(unsigned int addr,const unsigned char *pdata,unsigned char len)
{
    #if 0
		unsigned char i;	
		i2c_start();
		i2c_send_byte(0xA0);
		i2c_send_byte(addr>>8);
		i2c_send_byte(addr);	
		for(i=0;i<len;i++){
			i2c_send_byte(pdata[i]);			
		}			
		i2c_stop();
		//return 1;
		basic_delay_ms(10);//		delay_Nms(10);//HAL_Delay(10);//多次写入时必须延时!!
    #else

        unsigned char i;
        unsigned char cur_len;
        unsigned char offset=0;
        // unsigned char remain_len;
        // unsigned int cur_addr;
        do{
            //cur_addr = addr+offset;
            //remain_len = len-offset;
            //当前page可写入的字节个数;
            if( (cur_len = EE_PAGE_SIZE - ( (addr+offset)%EE_PAGE_SIZE) ) >= (len-offset) ){
                cur_len = len-offset;        
            }
						else{
							cur_len = cur_len; 
						}

            i2c_start();
            i2c_send_byte(0xA0);
            i2c_send_byte((addr+offset)>>8);
            i2c_send_byte(addr+offset);	
            for(i=0;i<cur_len;i++){
                i2c_send_byte(pdata[offset+i]);			
            }			
            i2c_stop();
            //return 1;
            basic_delay_ms(10);//		delay_Nms(10);//HAL_Delay(10);//多次写入时必须延时!!

            offset +=cur_len;
            if(offset >=len)    break;
        }while(1);


    #endif
}

/*
*/
unsigned char EE_ReadBytes(unsigned int addr,unsigned char *pdata,unsigned char len)
{
		unsigned char i;
		i2c_start();
		i2c_send_byte(0xA0);//write
		i2c_send_byte(addr>>8);	
		i2c_send_byte(addr);

		i2c_start();
		i2c_send_byte(0xA1);//read		
		for(i=0;i<len;i++)
			pdata[i]=i2c_read_byte();	
		i2c_stop();
		
		return 1;
}


void i2c_test_basic(void)
{
	unsigned char tmp[2]= {0xaa,0};
	EE_WriteBytes(0xff,tmp,1);
	
	EE_ReadBytes(0xff,tmp+1,1);
	
	if( tmp[1] !=tmp[0]){
		tmp[1] =tmp[1];
	}
	else{
		tmp[1] =tmp[1];
	}
}