打印
[PIC®/AVR®/dsPIC®产品]

【CuriosityNano测评报告】+模拟I2C驱动AT24C32EEPROM

[复制链接]
1215|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hu9jj|  楼主 | 2020-11-28 15:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
    上篇完成了模拟I2C驱动DS1307日历模块后,因我购买的日历模块上同时还带有一块AT24C32EEPROM,所以顺带完成I2C驱动AT24C32的测试,这块EEPROM芯片是32K容量,其储存地址超过了8位,要用到16位地址,也就是说在读写操作时发送的是两个字节的地址,其他过程与驱动DS1307相同。
    16位数据的定义通常使用uint16_t作为符号,而MCC生成的代码中似乎没有对这种符号作定义,起先我也没有注意,结果在编译出错,提示uint16_t未定义。因为我是在i2c.h文件中进行过定义,当时我没有考虑作用范围,还弄不清楚出错的原因,只是想我已经定义过,为什么还会说未定义,而且我在文件开始处包含了i2C.h头文件,同时定义过16位的变量,编译都已经通过,百思不得其解,只好将16位地址拆解成高8位和低8位分别传送参数。后来冷静下来思考,才发现应该是作用范围的问题,于是我将这个定义移到mcc.h文件中,这才解决了问题。
    我的测试是每秒生成一次16位的时期和时间数据的字符串,作为测试数据进行读写操作,每次写一个页面,从1到10页面轮流写入。每次先读出上次写入数据显示在LCD屏幕上,然后将即时的数据写入下一个页面内,如此循环。下面是测试过程的照片:


    下面是逻辑分析仪抓取的读数据时的时序截图:


    从截图的右下窗口可以清楚的看到读出了D2020112...字符数据。
    下面是模拟I2C的单字节、单个和多个数据的读写操作函数,以及双字节、单个和多个数据的读写操作函数。按说EEPROM的多字节读写有特殊的要求,即不能跨页操作,但在我的代码中没有对这个要求进行处理,也就是说在使用这段代码时要注意这个问题。
/****************************************************************************************** 
* 函数名称: I2C_8bitByteRead()
* 功能说明: 从指定地址addr开始获取1个字节的数据
* 输    入: uint8_t I2Caddr 器件地址
*           uint8_t addr        数据地址
* 输    出: uint8_t 返回读取的数值
* 备    注:
******************************************************************************************/
uint8_t SI2C_8bitByteRead(uint8_t I2Caddr,uint8_t addr)
{
    uint8_t dat;

    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr);             //发送器件地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
                return 2;
    }
    SI2C_Send(addr);                //发送读取数据的起始地址
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                    //产生停止信号
        return 3;
    }

    SI2C_Start();                   //产生Repeated Start
    SI2C_Send(I2Caddr|1);           //发送从设备芯片地址及读写位,1表示读
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 4;
    }

    dat = SI2C_Receive();
    SI2CDoAck();

    SI2CNoAck();                    //从设备要求必须使用NOAck来结束数据读取

    SI2C_Stop();                    //产生停止信号

        return dat;
}

/******************************************************************************************
* 函数名称: I2C_8bitByteWrite()
* 功能说明: 从指定地址addr开始写入1个字节的数据
* 输    入: uint8_t I2Caddr 器件地址
*           uint8_t addr        数据地址
* 输    出: uint8_t 返回读取的数值
* 备    注:
******************************************************************************************/
uint8_t SI2C_8bitByteWrite(uint8_t I2Caddr,uint8_t addr,uint8_t dat)
{
    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr|0);           //发送从设备芯片地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 1;
        }

    SI2C_Send(addr);                //发送数据要写入的地址
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 2;
    }

    SI2C_Send(dat);
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 3;
    }

    SI2C_Stop();                    //产生停止信号
   
    return 0;

}


/******************************************************************************************
* 函数名称: I2C_8bitBuffRead()
* 功能说明: 从指定地址addr开始获取size个字节的数据,获取的数据存储在全局变量数组I2C_Buff中
* 输    入: uint8_t I2Caddr 器件地址
*           uint8_t addr        获取数据从addr开始
*                        uint8_t size        要获取的数据个数(1~8)
* 输    出: uint8_t 操作状态
* 备    注:长度不得超过16个字节
******************************************************************************************/
uint8_t SI2C_8bitBuffRead(uint8_t I2Caddr,uint8_t addr,uint8_t size,uint8_t *buff)
{
    uint8_t i;

    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr);             //发送器件地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
                return 2;
    }
    SI2C_Send(addr);                //发送读取数据的起始地址
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                    //产生停止信号
        return 3;
    }

    SI2C_Start();                   //产生Repeated Start
    SI2C_Send(I2Caddr|1);           //发送从设备芯片地址及读写位,1表示读
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 4;
    }

    for(i=0;i<size;i++)             //从addr处读取size个字节的数据
    {
        buff[i] = SI2C_Receive();
        SI2CDoAck();
    }
    SI2CNoAck();                    //从设备要求必须使用NOAck来结束数据读取

    SI2C_Stop();                    //产生停止信号
   
    return *buff;
}

/**********************************************************************************************
* 函数名称:        I2C_8bitBuffWrite()
* 功能说明: 向I2C器件的地址addr开始写入size个字节的数据,将要写入的数据存储在全局变量数组I2C_Buff中
* 输    入: uint8_t addr        数据被写入从addr开始的地址处
*                        uint8_t size        要设置的数据个数(1~8)
* 输    出: uint8_t                0= 成功  1=出现错误
**********************************************************************************************/
uint8_t SI2C_8bitBuffWrite(uint8_t I2Caddr,uint8_t addr,uint8_t size,uint8_t *buff)
{
    uint8_t i = 0;
       
    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr|0);           //发送从设备芯片地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 1;
        }

    SI2C_Send(addr);                //发送数据要写入的地址
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 2;
    }

    for(i=0;i<size;i++)
    {
        SI2C_Send(buff[i]);
        if(SI2CIsAck())             //检测从设备是否有响应
        {
            SI2C_Stop();            //产生停止信号
            return 3;
        }
    }

    SI2C_Stop();                    //产生停止信号

    return 0;
}


/******************************************************************************************
* 函数名称: I2C_16bitByteRead()
* 功能说明: 从指定地址addr开始获取1个字节的数据
* 输    入: uint8_t I2Caddr 器件地址
*           uint16_t addr        双字节数据地址
* 输    出: uint8_t 返回读取的数值
* 备    注:
******************************************************************************************/
uint8_t SI2C_16bitByteRead(uint8_t I2Caddr,uint16_t addr)
{
    uint8_t dat;

    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr);             //发送器件地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
                return 2;
    }
    SI2C_Send(addr>>8);             //发送读取数据的起始地址
//    SI2C_Send(addrH);
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                    //产生停止信号
        return 3;
    }
        SI2C_Send(addr|0x0F);           //发送读取数据的起始地址低8位
//        SI2C_Send(addrL);
    if(SI2CIsAck())                 //检测器件是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 3;
    }
   
    SI2C_Start();                   //产生Repeated Start
    SI2C_Send(I2Caddr|1);           //发送从设备芯片地址及读写位,1表示读
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 4;
    }

    dat = SI2C_Receive();
    SI2CDoAck();

    SI2CNoAck();                    //从设备要求必须使用NOAck来结束数据读取

    SI2C_Stop();                    //产生停止信号

        return dat;
}


/******************************************************************************************
* 函数名称: I2C_16bitByteWrite()
* 功能说明: 从指定地址addr开始写入1个字节的数据
* 输    入: uint8_t I2Caddr 器件地址
*           uint16_t addr        双字节数据地址
* 输    出: uint8_t 返回读取的数值
* 备    注:
******************************************************************************************/
uint8_t SI2C_16bitByteWrite(uint8_t I2Caddr,uint16_t addr,uint8_t dat)
{
    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr|0);           //发送从设备芯片地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 1;
        }
    SI2C_Send(addr>>8);             //发送读取数据的起始地址
//    SI2C_Send(addrH);               //发送读取数据的起始地址
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                    //产生停止信号
        return 3;
    }
        SI2C_Send(addr|0x0F);           //发送读取数据的起始地址低8位
//    SI2C_Send(addrL);               //发送读取数据的起始地址低8位
    if(SI2CIsAck())                 //检测器件是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 3;
    }

    SI2C_Send(dat);
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 3;
    }

    SI2C_Stop();                    //产生停止信号
   
    return 0;

}


/******************************************************************************************
* 函数名称: I2C_16bitBuffRead()
* 功能说明: 从指定地址addr开始获取size个字节的数据,获取的数据存储在全局变量数组I2C_Buff中
* 输    入: uint8_t I2Caddr 器件地址
*           uint16_t addr        获取数据从addr开始(16位地址)
*                        uint8_t size        要获取的数据个数(1~8)
* 输    出: uint8_t 操作状态
* 备    注:长度不得超过16个字节
******************************************************************************************/
uint8_t SI2C_16bitBuffRead(uint8_t I2Caddr,uint16_t addr,uint8_t size,uint8_t *buff)
{
    uint8_t i;

    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr);             //发送器件地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
                return 2;
    }
   
    SI2C_Send(addr>>8);             //发送读取数据的起始地址
//    SI2C_Send(addrH);
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                    //产生停止信号
        return 3;
    }
        SI2C_Send(addr|0x0F);           //发送读取数据的起始地址低8位
//    SI2C_Send(addrL);
    if(SI2CIsAck())                 //检测器件是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 3;
    }

    SI2C_Start();                   //产生Repeated Start
    SI2C_Send(I2Caddr|1);           //发送从设备芯片地址及读写位,1表示读
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 4;
    }

    for(i=0;i<size;i++)             //从addr处读取size个字节的数据
    {
        buff[i] = SI2C_Receive();
        SI2CDoAck();
    }
    SI2CNoAck();                    //从设备要求必须使用NOAck来结束数据读取

    SI2C_Stop();                    //产生停止信号
   
    return *buff;
}


/**********************************************************************************************
* 函数名称:        I2C_16bitBuffWrite()
* 功能说明: 向I2C器件的地址addr开始写入size个字节的数据,将要写入的数据存储在全局变量数组I2C_Buff中
* 输    入: uint16_t addr        数据被写入从addr开始的16位地址处
*                        uint8_t size        要设置的数据个数(1~8)
* 输    出: uint8_t                0= 成功  1=出现错误
**********************************************************************************************/
uint8_t SI2C_16bitBuffWrite(uint8_t I2Caddr,uint16_t addr,uint8_t size,uint8_t *buff)
{
    uint8_t i = 0;
       
    SI2C_Start();                   //产生起始信号
    SI2C_Send(I2Caddr|0);           //发送从设备芯片地址及读写位,0表示写
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 1;
        }

    SI2C_Send(addr>>8);             //发送读取数据的起始地址
    if(SI2CIsAck())                 //检测从设备是否有响应
    {
        SI2C_Stop();                    //产生停止信号
        return 3;
    }
        SI2C_Send(addr|0x0F);           //发送读取数据的起始地址低8位
    if(SI2CIsAck())                 //检测器件是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 3;
    }

    for(i=0;i<size;i++)
    {
        SI2C_Send(buff[i]);
        if(SI2CIsAck())             //检测从设备是否有响应
        {
            SI2C_Stop();            //产生停止信号
            return 3;
        }
    }

    SI2C_Stop();                    //产生停止信号

    return 0;
}


使用特权

评论回复
沙发
和下土| | 2020-11-29 12:16 | 只看该作者
又学到了,EEPROM的多字节读写有特殊的要求,不能跨页操作

使用特权

评论回复
板凳
和下土| | 2020-11-29 12:19 | 只看该作者
在使用这段代码时要注意这个问题。

使用特权

评论回复
地板
hu9jj|  楼主 | 2020-11-29 12:44 | 只看该作者
和下土 发表于 2020-11-29 12:19
在使用这段代码时要注意这个问题。

EEPROM的数据手册会有说明的,使用时首先要了解该EEPROM的相关要求。

使用特权

评论回复
5
MianQi| | 2020-12-3 18:21 | 只看该作者
这款逻辑分析仪不错,多少钱买地?

使用特权

评论回复
6
hu9jj|  楼主 | 2020-12-4 08:19 | 只看该作者
MianQi 发表于 2020-12-3 18:21
这款逻辑分析仪不错,多少钱买地?

好象是28元吧,2016年买的。

使用特权

评论回复
评论
MianQi 2020-12-4 08:55 回复TA
给个链接地址。 
7
晓伍| | 2020-12-4 13:04 | 只看该作者
实测iic接口运行稳定吗

使用特权

评论回复
8
磨砂| | 2020-12-4 13:07 | 只看该作者
请问mcc的头文件里边都定义了哪些变量呢

使用特权

评论回复
9
木木guainv| | 2020-12-4 13:10 | 只看该作者
这个逻辑分析仪跟电脑的接口是什么接口

使用特权

评论回复
10
xiaoqizi| | 2020-12-4 13:12 | 只看该作者
非常不错 这是用的硬件iic吧

使用特权

评论回复
11
hu9jj|  楼主 | 2020-12-4 14:05 | 只看该作者
晓伍 发表于 2020-12-4 13:04
实测iic接口运行稳定吗

运行稳定。

使用特权

评论回复
12
hu9jj|  楼主 | 2020-12-4 14:07 | 只看该作者
木木guainv 发表于 2020-12-4 13:10
这个逻辑分析仪跟电脑的接口是什么接口

USB接口,在电脑上运行相应的程序就可以截取引脚的时序。

使用特权

评论回复
13
hu9jj|  楼主 | 2020-12-4 14:08 | 只看该作者
xiaoqizi 发表于 2020-12-4 13:12
非常不错 这是用的硬件iic吧

硬件I2C仍未调通,目前还是使用模拟I2C。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:Microchip
简介:让我们来为您提供帮助。我们可提供各种资源来帮助您解决一切问题。是否需要与我们的客户支持团队联系?您可以通过电话、在线聊天功能或电子邮件与他们联系。

151

主题

1059

帖子

11

粉丝