打印
[ZLG-ARM]

CAT1161古怪的问题 可以应用吗 串行E2PROM带WatchDog监控芯片

[复制链接]
3201|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cahu|  楼主 | 2010-10-2 21:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这段时间我在尝试使用CAT1161,碰到的问题特别古怪,耗了不少时间。

    我是使用模拟的I2C程序,一个老模块,在多个I2C器件中应用过。

    首先是应答问题:
    发送完从机地址等待应答时,从机始终无应答。
    更换了3个新的CAT1161,均是如此。换下来的器件,都能在编程器中正常操作,说明器件正常,而我的I2C程序模块,有问题。
    因为是相信老的应用过模块,怎么也找不出问题。无论是单步,或断点,都无法收到应答信号。
    后来将断点放到,SLC高电平,接收应答信号后面,发现已经正常收到应答信号。但是SDA却是高电平,没有应答信号。感到很奇怪。
    于是,通过记录SDA信号,发现在看门狗输出复位后,SDA应答信号消失了。
    原来,看门狗部分,并不独立于串行E2PROM,看门狗输出复位,也将串行E2PROM复位。
    因此单步调试,或不恰当的断点,由于看门狗的干扰,将无法收到正常的应答信号。


    连续读操作等待时序问题:
    连续读操作时,刚开始,发现间隔一个地址,读操作出错一次。
    读出的不对的数据,但是CAT1161应答正常。
    开始以为读操作需要延时。
    后来发现,由于书写错误,主机应答信号有误。
    随机读时序为:起始位    从机地址   (从机应答) 字节地址   (从机应答)  起始位  从机地址 (从机应答) 数据  (主机不应答) 停止位。
    最后的(主机不应答),应该SDA输出高电平。错误的应答,SDA低电平,将导致连续读写出错。
    正确的应答电平,就可以连续读写的。
    这样说明,CAT1161设计上有问题,起始信号、还是停止信号,都不能初始化串行E2PROM。

    以前带串行E2ROM监控看门狗芯片有用过,X5045、X4045。
   
    X5045、X4045,看门狗独立,可控启动关闭看门狗,修改看门狗周期,应用更灵活,至今感觉存储数据可靠性很不错,没发现丢失数据的。
    缺点是,单一的复位电平,若需要低电平复位的话,须选择 X5043、X4043,麻烦些。
    I2C接口的是X4045、X4043,芯片不错,可很难买到,价格也比X5045高。几个编程器都不支持是X4045、X4043,不放心继续应用。

    由于希望节省单片机端口使用,I2C总线级联多个器件,于是选择了CAT1161。

    对CAT1161的担心主要是:
    1、呆板的看门狗设计,固定1.6秒的复位周期,不可关闭。不可关闭,在ISP在线编程应用,肯定有麻烦,须作特殊处理。
    2、串行E2PROM,起始信号、停止信号,都不能真正置位串行E2PROM。
          不知道有没有这种情况,使用过程中,串行E2PROM出错不响应了,非得复位信号才能正常。
          这样,真是没意思,单片机需要监控就算了,串行E2PROM也要监控操作。
          针对这样情况,那么,设计上得做更多特殊处理。
         比如,发现串行E2PROM出错了,等待MCU空闲,可以复位操作了;强制MCU死机,然后,看门狗动作。串行E2PROM正常了,恢复MCU工作环境,继续记录数据MCU。
         真的挺麻烦的。
    3、最后一个问题,CAT1161数据稳定性怎样,不会跟其它功能这么菜吧。没有信心。用的时间较长的,有信心吗?







转贴 貳馬de筆記
http://blog.21ic.com/user1/4663/archives/2009/59114.html
CAT1161应用小结
         CAT1161是一款i2c接口的内置EEPROM和看门狗的复位芯片,E2PROM大小为16Kb(2KB),看门狗监听SDA总线上电平变化,1.6s无变化时自动复位,理论上使用很方便,但由于本人第一次使用,而且对i2c总线也不是很了解,故还是应用中遇到了点问题,还好最终解决,对出现的问题简单总结下。
         MCU使用的是C8051F120,内置1路I2C接口,这个芯片内设口线不是固定的,需要配置,这个就不多说了,看手册。很多人喜欢用IO口模拟I2C总线,反正我不太喜欢,还是用芯片自带的吧。
        遇到的第一个问题是:I2C程序运行到发送完从机地址等待应答时,从机始终无应答,反复检查程序没看出端倪,浪费大量时间,遂怀疑芯片,更换之,果然换了后最起码有了应答。真恨这些奸商,拿些过期芯片糊弄人,后来检查这些芯片大部分都有问题,就两片暂时能用。
        第二问题:连续写三个字节到三个不同地址里,紧接着读出,发现读错误,或读出的数据是其他地址里的,最终解决,原因是,每次读写时两次操作之间必须间隔约10ms,写时要时间间隔可以理解,因为EEPROM是在总线时序结束后才开始写,未写完前是不会接收下次操作的,所以写的太快可能第二次的就没写进去,但读时发现似乎也要时间间隔,感觉没道理,因为每次读操作时都会等待读时序结束后才会退出的,不知道什么原因。
       /*纠正*/  经论证: 写操作若不是每次等时序结束才退出的,那么两次写之间必须得延时,读操作因为是时序结束后才退出的,所以可以连续读,中间不需要延时。
       第三个问题:关于选择性读操作,就是给个地址读个数据那种操作,手册里时序为:起始位    从机地址   (从机应答) 字节地址   (从机应答)  起始位  从机地址 (从机应答) 数据  (主机不应答) 停止位   。我就是栽在第二个起始位那里,最后用示波器才发现时序错的太离谱了,所以一定好处理好时序,这个很重要。
      总之,会用之后就很简单了,最主要就是注意:延时、时序 。
      当然,对新手而言,还要学会用示波器看时序,这个也很重要。

相关帖子

沙发
cahu|  楼主 | 2010-10-2 21:31 | 只看该作者
测试代码:

    //CAT1161测试
    {
        extern int rand();
        
        uint ui_Test1;
        uchar uc_Test2;
        uchar uc_Test3;
        
        ui_Test1 = 0;
        
        //循环
        while (1)
        {
            uc_Test2 = rand();
            
            //CAT1161写操作
            {
                g_CAT1161_Write(ui_Test1, uc_Test2);    //CAT1161写操作
               
                //正常写入
                if (gb_Slave_Busy == 0)
                    acc ++ ;  //断点测试
               
                //写入失败
                else
                {
                    acc ++ ;  //断点测试
                    continue;
                } //写入失败
            } //CAT1161写操作
            
            //CAT1161读操作
            {
                uc_Test3 = guc_CAT1161_Read(ui_Test1);    //CAT1161读操作
               
                //正常读出
                if (gb_Slave_Busy == 0)
                {
                    //读出匹配
                    if (uc_Test2 == uc_Test3)
                        acc ++;
                        
                    //读出错误
                    else
                    {
                        acc ++ ;  //断点测试
                        continue;
                    } //读出错误
                } //正常读出
               
                //读出失败
                else
                {
                    acc ++ ;  //断点测试
                    continue;
                } //读出失败
            } //CAT1161读操作
            
            ui_Test1 ++;
            ui_Test1 &=0x07ff;
            if (ui_Test1 == 0)
                acc ++ ;  //断点测试
        } //循环
    } //CAT1161测试


I2C驱动模块

//##################################################################
//I2C总线起始位
//入口;
//出口:
//通讯池:
//功能:
//用法:
void I2cBus_Start(void) reentrant    //I2C总线起始位
{
    gb_Slave_Busy = 0;    //从器件忙标志 复位
   
    io_SDA = 1;
        DELAY_50ns;        //延时0.05us
    io_SCL = 1;
        DELAY_600ns;    //延时0.6us
    io_SDA = 0;
        DELAY_600ns;    //延时0.6us
    io_SCL = 0;
        DELAY_1200ns;    //延时1.2us
} //I2C总线起始位


//##################################################################
//I2C总线终止位
//入口;
//出口:
//通讯池:
//功能:
//用法:
void I2cBus_Stop(void) reentrant    //I2C总线终止位
{
    io_SCL = 0;
        DELAY_1200ns;    //延时1.2us
    io_SDA = 0;
        DELAY_50ns;        //延时0.05us
    io_SCL = 1;
        DELAY_600ns;    //延时0.6us
    io_SDA = 1;
        DELAY_600ns;    //延时0.6us
} //I2C总线终止位


//##################################################################
//I2C总线应答符
//入口; b_Ack = 0 有效应答
//出口:
//通讯池:
//功能:
//用法:
void I2cBus_Ack(void) reentrant    //I2C总线应答符
{
    io_SCL = 1;
        DELAY_600ns;    //延时0.6us
    io_SCL = 0;
        DELAY_1200ns;    //延时1.2us
} //I2C总线应答符


//##################################################################
//I2C总线写入字符
//入口; uc_Data 须写入的8位字节
//出口: 收到应答符, 返回0; 未收到应答符, 返回1
//通讯池:
//功能: 将字符写入从器件, 然后接受应答
//用法:
void I2cBus_CharWr(uchar uc_Data) reentrant    //I2C总线写入字符
{
    uchar uc1;
   
    //写入8个字节
    for (uc1 = 0; uc1 < 8; uc1 ++ )
    {
        io_SDA = uc_Data & 0x80;
            DELAY_50ns;    //延时0.05us
        io_SCL = 1;
        uc_Data <<= 1;
            DELAY_600ns;    //延时0.6us
        io_SCL = 0;
            DELAY_1200ns;    //延时1.2us
    } //写入8个字节
   
    io_SDA = 1;
    io_SCL = 1;
        DELAY_600ns;    //延时0.6us
    gb_Slave_Busy = io_SDA;    //从器件忙标志 读应答符
    io_SCL = 0;
        DELAY_1200ns;    //延时1.2us
} //I2C总线写入字符


//##################################################################
//I2C总线读出字符
//入口; uc_Data 须读出的8位字节
//出口:
//通讯池:
//功能: 向从器件读取数据
//用法:
uchar uc_I2cBus_CharRd(void) reentrant    //I2C总线读出字符
{
    uchar uc1, uc2;
   
    io_SDA = 1;
   
    //读出8个字节
    for (uc1 = 0; uc1 < 8; uc1 ++ )
    {
        uc2 <<= 1;
        io_SCL = 1;
        //读入一位
        if (io_SDA == 1)
            uc2 ++;
        io_SCL = 0;
            DELAY_1200ns;    //延时1.2us
    } //读出8个字节
   
    return (uc2);
} //I2C总线读出字符





//##################################################################
//CAT1161看门狗
//入口; 对应的寄存器数据
//出口:
//通讯池:
//功能:
//用法:
void g_CAT1161_WatchDog(void) reentrant    //CAT1161看门狗
{
    io_SCL = 0;
    io_SDA = 0;
        DELAY_50ns;    //延时0.05us
        DELAY_600ns;    //延时0.6us
    io_SDA = 1;
} //CAT1161看门狗




//##################################################################
//CAT1161读操作
//入口; ui_Adr 扇区地址
//出口: 读出的数据
//通讯池:
//功能: 读出一个数据
//用法:
uchar guc_CAT1161_Read(uint ui_Adr) reentrant    //CAT1161读操作
{
    uchar uc1, uc2;
   
    //读操作
    //    操作时间限制在10ms
    for (uc1 = 0; uc1 < 250; uc1 ++)
    {
        //起始位
            I2cBus_Start();    //I2C总线起始位
            
        //I2C总线写入字符
        //                寻址码写操作                    高位地址   
            I2cBus_CharWr(b10100000 + ( ( * ( (uchar * ) & ui_Adr + 0) & b00000111) << 1) );    //I2C总线写入字符
            //从器件忙 操作失败
            if (gb_Slave_Busy == 1)
                continue;
            
        //低位地址
            I2cBus_CharWr( * ( (uchar * ) & ui_Adr + 1) );    //I2C总线写入字符
            //从器件忙 操作失败
            if (gb_Slave_Busy == 1)
                continue;
               
        //重新起始位
            I2cBus_Start();    //I2C总线起始位
        
        //CAT1161寻址
            I2cBus_CharWr(b10100001);    //I2C总线写入字符
            //从器件忙 操作失败
            if (gb_Slave_Busy == 1)
                continue;
            
        //读出指定数据
             uc2 = uc_I2cBus_CharRd();    //I2C总线读出字符
            
        //不作应答
            io_SDA = 1;
                DELAY_50ns;    //延时0.05us
            I2cBus_Ack();    //I2C总线应答符
        
        I2cBus_Stop();    //I2C总线终止位
        break;
    } //读操作
   
    return (uc2);
} //CAT1161读操作





//##################################################################
//CAT1161写操作
//入口; ui_Adr 地址
//        ucp_Data 需写入的数据
//出口:
//通讯池:
//功能: 写入一个数据
//用法:
void g_CAT1161_Write(uint ui_Adr, uchar uc_Data) reentrant    //CAT1161写操作
{
    uchar uc1;
   
    //扇区写操作
    //    操作时间限制在10ms
    for (uc1 = 0; uc1 < 250; uc1 ++)
    {
        //起始位
            I2cBus_Start();    //I2C总线起始位
        
        //I2C总线写入字符
        //                寻址码写操作                    高位地址   
            I2cBus_CharWr(b10100000 + ( ( * ( (uchar * ) & ui_Adr + 0) & b00000111) << 1) );    //I2C总线写入字符
            //从器件忙 操作失败
            if (gb_Slave_Busy == 1)
                continue;
            
        //存储低位地址
            I2cBus_CharWr( * ( (uchar * ) & ui_Adr + 1) );    //I2C总线写入字符
            //从器件忙 操作失败
            if (gb_Slave_Busy == 1)
                continue;
            
        I2cBus_CharWr(uc_Data);    //I2C总线写入字符
        //从器件忙 操作失败
        if (gb_Slave_Busy == 1)
            continue;
        
        I2cBus_Stop();    //I2C总线终止位
        break;
    } //扇区写操作
} //CAT1161写操作

使用特权

评论回复
板凳
FVJFIFE| | 2010-10-7 14:28 | 只看该作者
好长啊,帮顶

使用特权

评论回复
地板
cahu|  楼主 | 2010-11-12 02:22 | 只看该作者
自顶

使用特权

评论回复
5
hotpower| | 2010-11-13 23:23 | 只看该作者
不错,但为何不用硬件模块呢?

使用特权

评论回复
6
foreverly| | 2010-12-3 14:05 | 只看该作者
帮顶吧。

使用特权

评论回复
7
七叶一枝花| | 2010-12-5 09:31 | 只看该作者
看得我眼都花了。继续看ING

使用特权

评论回复
8
思行合一| | 2010-12-11 15:41 | 只看该作者
不知道EPROM为何物的菜鸟飘过

使用特权

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

本版积分规则

4

主题

21

帖子

1

粉丝