
怎么说呢,官方承认在某种情况下,硬件I2C是存在不足的地方,但是官方给出了解决方法。
STM32F10x_硬件I2C读写EEPROM(标准外设圆告罩库版本):
http://blog.csdn.net/ybhuangfugui/article/details/52175621
写程序的时候,多注意一下芯片的资料。24C01的资料里面写的很清楚。读写必须按要求的波形来处理。我发一段我用在ST芯片的程序给你。由于IIC接口采用模拟的方式。所以,与什么和渣闭芯片没有关系。你把这段程序看一下。相信你可以看懂。使用这段程序的产品已经出货几十万套产品。不会有问题。ST芯片的端口输入输出设定比较麻烦。所以有单独的子程序来处理。
单片机IIC的SDA端口在向EEPROM(24C01)发数据时,设为输出
在读取EEPROM数据的时候则设为输入。
//-------------------------------------------
//-程序名称: Eestart
//-入口参数:无
//-出口参数:无
//-功能说明: IIC的START信号生成
//-------------------------------------------
void Eestart(void) //启动I2C总线//
{
SETSDA
DelayNOP(STARTNOP)
SETSCL
DelayNOP(STARTNOP)
CLRSDA
DelayNOP(STARTNOP)
CLRSCL --注意此处,很重要。总线只有SCL为低时,才允许SDA变化。
DelayNOP(STARTNOP)
}
//-------------------------------------------
//-程序名称: Eestop
//-入口参数:无
//-出口参数:无
//-功能说明: IIC的STOP信号生成
//-------------------------------------------
void Eestop(void )/*停止I2C总线*/
{
i2csdaoutput()
CLRSCL
DelayNOP(STARTNOP)
CLRSDA
DelayNOP(STARTNOP)
SETSCL
DelayNOP(STARTNOP)
SETSDA
}
//-------------------------------------------
//-程序名称: read_byte_eeprom
//-入口参数:ackstate
//-出口参数:返回值(读取到的数梁源据)
//-功能说明: 读取1byte的EEPROM数据
//-------------------------------------------
UI08 read_byte_eeprom(UI08 ackstate) //-read
{
UI08 j,data
i2csdainput() //-SDA端口设为输入状态
data = 0 //-将接收缓冲清空
//DelayNOP(NOP1US) //-2011-7-21 新增延时
for(j=0j<8j++)
{
//-
data <<= 1 //-将接收缓冲左移,保证高位先发
SETSCL
DelayNOP(NOP2US)//-延时
if(p_eepsdain != 0) //-此处的p_eepsdain 就是SDA端口,ST芯片输入输出端口不是同一名字
{
//-检测到数据为1时,将接收缓冲0BIT置1
data++
}
CLRSCL
DelayNOP(NOP1P5US)
}
if(ackstate == ACKREAD)
{
//-有要求发送ACK信号的则发送ACK信号
i2csdaoutput()//-将SDA端口设为输出
CLRSDA
DelayNOP(NOP2US)
SETSCL
DelayNOP(NOP2US)
CLRSCL
}
return(data)
}
//-------------------------------------------
//-程序名称: write_byte_eeprom
//-入口参数:wrdata
//-出口参数:返唤裂回值,FALSE(写入失败),TRUE(写入成功)
//-功能说明: 将wrdata写入EEPROM
//-------------------------------------------
bool write_byte_eeprom(UI08 wrdata)
{
bool j=FALSE //-返回值,默认为失败
UI08 i
//DelayNOP(NOP1US)//-2011-7-21 新增延时
for(i=0i<8i++)
{
//-总共移位8次
if((0x80 &wrdata) != 0)
{
//-最高位为1时,SDA置1
SETSDA
}
else
{
//-最高位为0时,SDA置0
CLRSDA
}
wrdata <<= 1//-将发送数据左移,实现高位先发
//DelayNOP(NOP1US)//-2011-7-21 新增延时
SETSCL
DelayNOP(NOP2US)
CLRSCL
DelayNOP(NOP1P5US)
}
//--read ACK signal--{
i2csdainput() //-将SDA设为输入状态
DelayNOP(NOP1US)
SETSCL
if(p_eepsdain == 0)
{
//-读取到正确的ACK信号,则返回写入成功
j = TRUE
}
DelayNOP(NOP1P5US)
CLRSCL
i2csdaoutput()//-将SDA端口设为输出
//--read ACK signal--}
return(j)
}
//-------------------------------------------
//-程序名称: DelayNOP
//-入口参数:cntnop
//-出口参数:无
//-功能说明: 进行cntnop个延时
//-------------------------------------------
void DelayNOP(UI08 cntnop)
{
UI08 i
for(i=0i<cntnopi++)
}
//-------------------------------------------
//-程序名称: i2csdainput
//-入口参数:无
//-出口参数:无
//-功能说明: 将SDA端口设为输入
//-------------------------------------------
void i2csdainput(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU
GPIO_Init(GPIOB, &GPIO_InitStructure)
*/
}
//-------------------------------------------
//-程序名称: i2csdaoutput
//-入口参数:无
//-出口参数:无
//-功能说明: 将SDA端口设为输出
//-------------------------------------------
void i2csdaoutput(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 //SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD
GPIO_Init(GPIOB, &GPIO_InitStructure)
*/
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)