最近准备智能车比赛,收到指导老师启发,准备做一个模块,实现手机和单片机之间通过WIFi通信修改参数,并存在EEPROM中的功能.由于WIFI模块没到,所以先解决EEPROM的读写.
EEPROM选的AT24C02,也是比较常见的储存器了,由于32和51都有例程,所以开始的时候根据逐飞的库照着例程写程序,想着能方便点.结果碰到了问题,写不进数据也读不了,又没有标准例程,就只好看看库函数找问题,最后发现问题出在库函数对地址的处理上.
下面是地址说明:
先看51例程的读写函数:
/*******************************************************************************
* 函数名 : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能 : 往24c02的一个地址写入一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2cStart();
I2cSendByte(0xa0);//发送写器件地址
I2cSendByte(addr);//发送要写入内存地址
I2cSendByte(dat); //发送数据
I2cStop();
}
/*******************************************************************************
* 函数名 : unsigned char At24c02Read(unsigned char addr)
* 函数功能 : 读取24c02的一个地址的一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2cStart();
I2cSendByte(0xa0); //发送写器件地址
I2cSendByte(addr); //发送要读取的地址
I2cStart();
I2cSendByte(0xa1); //发送读器件地址
num=I2cReadByte(); //读取数据
I2cStop();
return num;
}
由于三个地址位都接了地,AT24C02的地址前7位是0101000,所以写地址就是01010000(即0xA0),读地址就是01010001(即0xA1)
再看到逐飞的库函数:
//-------------------------------------------------------------------------------------------------------------------
// @brief 模拟IIC写数据到设备寄存器函数
// @param dev_add 设备地址(低七位地址)
// @param reg 寄存器地址
// @param dat 写入的数据
// @return void
// @since v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void simiic_write_reg(uint8 dev_add, uint8 reg, uint8 dat)
{
simiic_start();
send_ch( (dev_add<<1) | 0x00); // 发送器件地址加写位
send_ch( reg ); // 发送从机寄存器地址
send_ch( dat ); // 发送需要写入的数据
simiic_stop();
}
//-------------------------------------------------------------------------------------------------------------------
// @brief 模拟IIC从设备寄存器读取数据
// @param dev_add 设备地址(低七位地址)
// @param reg 寄存器地址
// @param type 选择通信方式是IIC 还是 SCCB
// @return uint8 返回寄存器的数据
// @since v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
uint8 simiic_read_reg(uint8 dev_add, uint8 reg, IIC_type type)
{
uint8 dat;
simiic_start();
send_ch( (dev_add<<1) | 0x00); // 发送器件地址加写位
send_ch( reg ); // 发送从机寄存器地址
if(type == SCCB)simiic_stop();
simiic_start();
send_ch( (dev_add<<1) | 0x01); // 发送器件地址加读位
dat = read_ch(SEEKFREE_NACK); // 读取数据
simiic_stop();
return dat;
}
虽然写地址还是0xA0,读地址还是0xA1,但是可以看到在读写函数里都进行了(地址左移一位+读/写位)的操作,所以我们应该填的地址不是0xA0或者0xA1,而是01010000,即0x50.
最近准备智能车比赛,收到指导老师启发,准备做一个模块,实现手机和单片机之间通过WIFi通信修改参数,并存在EEPROM中的功能.由于WIFI模块没到,所以先解决EEPROM的读写.
EEPROM选的AT24C02,也是比较常见的储存器了,由于32和51都有例程,所以开始的时候根据逐飞的库照着例程写程序,想着能方便点.结果碰到了问题,写不进数据也读不了,又没有标准例程,就只好看看库函数找问题,最后发现问题出在库函数对地址的处理上.
下面是地址说明:
先看51例程的读写函数:
/*******************************************************************************
* 函数名 : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能 : 往24c02的一个地址写入一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2cStart();
I2cSendByte(0xa0);//发送写器件地址
I2cSendByte(addr);//发送要写入内存地址
I2cSendByte(dat); //发送数据
I2cStop();
}
/*******************************************************************************
* 函数名 : unsigned char At24c02Read(unsigned char addr)
* 函数功能 : 读取24c02的一个地址的一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2cStart();
I2cSendByte(0xa0); //发送写器件地址
I2cSendByte(addr); //发送要读取的地址
I2cStart();
I2cSendByte(0xa1); //发送读器件地址
num=I2cReadByte(); //读取数据
I2cStop();
return num;
}
由于三个地址位都接了地,AT24C02的地址前7位是0101000,所以写地址就是01010000(即0xA0),读地址就是01010001(即0xA1)
再看到逐飞的库函数:
//-------------------------------------------------------------------------------------------------------------------
// @brief 模拟IIC写数据到设备寄存器函数
// @param dev_add 设备地址(低七位地址)
// @param reg 寄存器地址
// @param dat 写入的数据
// @return void
// @since v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void simiic_write_reg(uint8 dev_add, uint8 reg, uint8 dat)
{
simiic_start();
send_ch( (dev_add<<1) | 0x00); // 发送器件地址加写位
send_ch( reg ); // 发送从机寄存器地址
send_ch( dat ); // 发送需要写入的数据
simiic_stop();
}
//-------------------------------------------------------------------------------------------------------------------
// @brief 模拟IIC从设备寄存器读取数据
// @param dev_add 设备地址(低七位地址)
// @param reg 寄存器地址
// @param type 选择通信方式是IIC 还是 SCCB
// @return uint8 返回寄存器的数据
// @since v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
uint8 simiic_read_reg(uint8 dev_add, uint8 reg, IIC_type type)
{
uint8 dat;
simiic_start();
send_ch( (dev_add<<1) | 0x00); // 发送器件地址加写位
send_ch( reg ); // 发送从机寄存器地址
if(type == SCCB)simiic_stop();
simiic_start();
send_ch( (dev_add<<1) | 0x01); // 发送器件地址加读位
dat = read_ch(SEEKFREE_NACK); // 读取数据
simiic_stop();
return dat;
}
虽然写地址还是0xA0,读地址还是0xA1,但是可以看到在读写函数里都进行了(地址左移一位+读/写位)的操作,所以我们应该填的地址不是0xA0或者0xA1,而是01010000,即0x50.
举报