单片机学习小组
直播中

李秀珍

7年用户 1010经验值
私信 关注

如何用逐飞库实现单片机的IIC通信?

如何用逐飞库实现单片机的IIC通信

回帖(1)

陈自萤

2022-1-19 09:29:19
最近准备智能车比赛,收到指导老师启发,准备做一个模块,实现手机和单片机之间通过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.
举报

更多回帖

发帖
×
20
完善资料,
赚取积分