使用I2C & 写入EEPROM
Angie An

使用I2C & 写入EEPROM

stm32f10x控制HDMI RX子卡,电脑通过HDMI 连接板卡,需要通过HDMI的DDCSDA和DDCCLK读取板卡上的EEPROM获取EDID。

1.MCU控制芯片

初始化IIC
1
2
3
4
5
6
void ITE6805_Init(void)
{
//reset PB5 L -> H
GPIO_Toggle_INIT();
IIC_Init( 100000, 0xA0); //write:0xA0 read:0xA1
}
初始化PB5 RESET引脚

最初将PB5输出模式设置为GPIO_Mode_Out_PP推挽输出时,每次复位后测出输出电压变高(1.8V->2.5V),将RST设为开漏输出之后变为正常。

1
2
3
4
5
6
7
8
9
10
11
12
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //set pin
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //set output open-drain
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //set speed
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIO pin5 map to PB5
PBout(5) = 0;
Delay_Ms(250);
PBout(5) = 1;
}
初始化PB6 PB7为SCL SDA (I2C1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

void IIC_Init( u32 bound, u16 address )
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitTSturcture;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //AF open-drain
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure ); //pin6 map to PB6

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //AF open-drain
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure ); //pin6 map to PB6

//set I2C2 as input mode for PC read the EEPROM
#if 1 //add an.q for add I2C2 as GPIO input
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );
#endif

I2C_InitTSturcture.I2C_ClockSpeed = bound;
I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitTSturcture.I2C_OwnAddress1 = address;
I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init( I2C1, &I2C_InitTSturcture );

I2C_Cmd( I2C1, ENABLE );
I2C_AcknowledgeConfig( I2C1, ENABLE );
}
Write One Byte函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void ITE6805_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( I2C1, ENABLE );

while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C1, SLAVE_ADDR, I2C_Direction_Transmitter );

while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

#if (Address_Lenth == Address_8bit)
I2C_SendData( I2C1, (u8)(WriteAddr&0x00FF) );
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

#elif (Address_Lenth == Address_16bit)
I2C_SendData( I2C1, (u8)(WriteAddr>>8) );
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

I2C_SendData( I2C1, (u8)(WriteAddr&0x00FF) );
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

#endif

if( I2C_GetFlagStatus( I2C1, I2C_FLAG_TXE ) != RESET )
{
I2C_SendData( I2C1, DataToWrite );
}

while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_GenerateSTOP( I2C1, ENABLE );
}
Read One Byte函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
u8 ITE6805_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( I2C1, ENABLE );

//wait for EV5
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );

//send slave address
I2C_Send7bitAddress( I2C1, SLAVE_ADDR, I2C_Direction_Transmitter );

//wait for EV6
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

#if (Address_Lenth == Address_8bit)

I2C_SendData( I2C1, (u8)(ReadAddr&0x00FF) );

//wait for EV8_2
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

#elif (Address_Lenth == Address_16bit)
I2C_SendData( I2C1, (u8)(ReadAddr>>8) );
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );


I2C_SendData( I2C1, (u8)(ReadAddr&0x00FF) );
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

#endif

I2C_GenerateSTART( I2C1, ENABLE );
//wait for EV5
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C1, SLAVE_ADDR, I2C_Direction_Receiver );

//wait for EV6
while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) );

while( I2C_GetFlagStatus( I2C1, I2C_FLAG_RXNE ) == RESET )
I2C_AcknowledgeConfig( I2C1, DISABLE );

temp = I2C_ReceiveData( I2C1 );
I2C_GenerateSTOP( I2C1, ENABLE );

return temp;
}

2.I2C2写EDID到EEPROM

#define I2C_DEV I2C2

#define Address_8bit 0

#define Address_16bit 1

本次使用的EEPROM为BL24C64A-NTRC,时序图与其他EEPROM不同,写Byte时需要START+DVICE ADDRESS+FIRST WORD ADDRESS+SECOND WORD ADDRESS+DATA+STOP,也就是说地址不是8位而是16位。

初始化IIC
1
2
3
4
5
void ITE6805_Init(void)
{
GPIO_Toggle_INIT();
IIC_Init( 10000, 0xA0); //write:0xA0 read:0xA1
}
初始化PB9 拉低
1
2
3
4
5
6
7
8
9
10
11
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//初始化GPIO 9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //PB9拉高=EEPROM写保护 此处拉低
PBout(9) = 0;
}
初始化PB10 PB11 (I2C2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void IIC_Init( u32 bound, u16 address )
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitTSturcture;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C2, ENABLE );
//PB10 开漏复用输出 DDCSCL
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );
//PB11 开漏复用输出 DDCSDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );

I2C_InitTSturcture.I2C_ClockSpeed = bound;
I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitTSturcture.I2C_OwnAddress1 = address;
I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init( I2C_DEV, &I2C_InitTSturcture );

I2C_Cmd( I2C_DEV, ENABLE );
I2C_AcknowledgeConfig( I2C_DEV, ENABLE );

}
初始化EEPROM EDID
1
2
3
4
5
6
7
8
void iTE6805_EDID_EEPROMInitial(void)
{
iTE_u8 *piTE6805EDID;

piTE6805EDID = (iTE_u8 *)&Customer_EDID_test[0][0];
iTE6805_EDID_UpdateEEPROM(piTE6805EDID,0);
iTE6805_EDID_UpdateEEPROM(piTE6805EDID,1);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
iTE_u16 iTE6805_EDID_UpdateEEPROM(iTE_u8 *pEDID,iTE_u8 BlockNUM)
{
iTE_u8 i;
iTE_u16 offset;
iTE_u16 sum =0;
iTE_u16 cnt = 0;
if ( BlockNUM == 0x02 )
{
offset = 0x00+128*0x01;
}
else
{
offset = 0x00+128*BlockNUM;
}

EDID_DEBUG_PRINTF(("block No =%02X offset = %02X\n",(int) BlockNUM,(int) offset));

for( i=0 ; i<0x7F ; i++ )
{
EDID_DEBUG_PRINTF(("%02X ",(int) *(pEDID+offset)));
ITE6805_EEPROM_Write(offset,(pEDID+offset),1);
sum += *(pEDID+offset);
offset ++;
cnt++;
if((i % 16) == 15)
{
EDID_DEBUG_PRINTF(("\n"));
}
}
EDID_DEBUG_PRINTF(("\n"));
sum = 0x00 - sum;
return cnt;
}
1
2
3
4
5
6
7
8
9
10
void ITE6805_EEPROM_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
while(NumToWrite--)
{
ITE6805_EEPROM_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
Delay_Ms(2);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void ITE6805_EEPROM_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
while( I2C_GetFlagStatus( I2C_DEV, I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( I2C_DEV, ENABLE );

while( !I2C_CheckEvent( I2C_DEV, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C_DEV, SLAVE_ADDR, I2C_Direction_Transmitter );

while( !I2C_CheckEvent( I2C_DEV, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

#if (Address_Lenth == Address_8bit)

I2C_SendData( I2C_DEV, (u8)(WriteAddr&0x00FF) );
while( !I2C_CheckEvent( I2C_DEV, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

#elif (Address_Lenth == Address_16bit)

I2C_SendData( I2C_DEV, (u8)(WriteAddr>>8) );
while( !I2C_CheckEvent( I2C_DEV, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

I2C_SendData( I2C_DEV, (u8)(WriteAddr&0x00FF) );
while( !I2C_CheckEvent( I2C_DEV, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

#endif

if( I2C_GetFlagStatus( I2C_DEV, I2C_FLAG_TXE ) != RESET )
{
I2C_SendData( I2C_DEV, DataToWrite );
}

while( !I2C_CheckEvent( I2C_DEV, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_GenerateSTOP( I2C_DEV, ENABLE );
}
 Comments