搜索
bottom↓
回复: 32

(转贴)我用GCC写的AT24C64接口程序,已调试通过,与大家分享

[复制链接]

出0入0汤圆

发表于 2004-10-18 21:54:37 | 显示全部楼层 |阅读模式
我前几天发表了一个贴子,是关于ATMEGA的TWI编程的。

现在转贴一下21icc上mxh0506发表的贴子。我调试了一下,没有错误。

我就基本按照他的程序写的,贴出来与大家共享。

非常感谢mxh0506。支持阿莫。





// AT24C64 support functions using ATMEGA's TWI

// pin-WP is hard-wired to GND

// fuctions work better outside interrupt routines

// by MXH, 2003/07/30



#include "DStruct.h"

#include <avr/twi.h>



// CONSTANTS DEFINITION FOR EEPROM

#define EEADDR        0

#define EEWR        0

#define EERD        1

// TWINT *NOT* set after STOP condition is sent

// check status?

// TWSTO is cleared by hardware

#define TwiStop()    TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO)

#define TwiStart()    TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA)

#define TWI_STATUS    (TWSR & 0xF8)



BYTE byEEWait;



//////////////////////////////////////////////////////////////////////////

// implementation



BOOL EEPStart(BYTE addr, BOOL bWrite)

{

    byEEWait = 10;    // 90~100ms

poll_ack:

    TwiStart();

    while (!(TWCR & (1<<TWINT))){    // wait

        if ( byEEWait == 0 ){

            return FALSE;

        }

    }

    if ((TWI_STATUS != TW_START)&&(TWI_STATUS != TW_REP_START))

        goto poll_ack;

    //byEEWait = 3;    // 20~30ms

    // send SLA+R/W

    TWDR = addr | bWrite;

    TWCR = (1<<TWINT)|(1<<TWEN);

    while (!(TWCR & (1<<TWINT))){

        if( byEEWait == 0 ){

            TwiStop();

            return FALSE;

        }

    }

    if( EEWR == bWrite ){    // MT mode

        //if(TWI_STATUS != TW_MT_SLA_ACK)

        switch(TWI_STATUS){

            case TW_MT_SLA_ACK:

                break;

            case TW_MT_SLA_NACK:

                goto poll_ack;

            default:

                TwiStop();

                return FALSE;

        }

    }else{                    // MR mode

        if(TWI_STATUS != TW_MR_SLA_ACK)

            return FALSE;

    }

    return TRUE;

}



//////////////////////////////////////////////////////////////////////

//

BYTE EEPWrite( WORD uiAddress, WORD uiLen, void *pBuf ) //using 0

{

    unsigned int i,j,uiCnt;

   

    if( uiLen == 0 ) return 0;

    uiCnt = 0;

//    uiEnd = uiAddress + uiLen;

    i = uiAddress;

    do{

        if(!EEPStart(0xA0|EEADDR,EEWR)){    //PollAck() is built-in

            return 0;

        }

        TWDR = (BYTE)((i>>8)&0x00ff);        // MSB of address

        TWCR = (1<<TWINT)|(1<<TWEN);

        byEEWait = 3;    // 20~30ms

        while (!(TWCR & (1<<TWINT))){

            if( byEEWait == 0 )

                return FALSE;

        }

        if(TWI_STATUS != TW_MT_DATA_ACK){

            return FALSE;

        }

        TWDR = (BYTE)(i&0x00ff);            // LSB of address

        TWCR = (1<<TWINT)|(1<<TWEN);

        byEEWait = 3;    // 20~30ms

        while (!(TWCR & (1<<TWINT))){

            if( byEEWait == 0 )

                return FALSE;

        }

        if(TWI_STATUS != TW_MT_DATA_ACK)

            return FALSE;

        // write data

        for( j=0; j<32; j++ ){

            TWDR = ((BYTE*)pBuf)[uiCnt];

            TWCR = (1<<TWINT)|(1<<TWEN);

            byEEWait = 3;    // 20~30ms

            while (!(TWCR & (1<<TWINT))){

                if( byEEWait == 0 )

                    return FALSE;

            }

            if(TWI_STATUS != TW_MT_DATA_ACK){

                return FALSE;

            }

            i++;

            uiCnt++;

            if(( 0 == i%32 )||( uiCnt == uiLen )){

                TwiStop();

                break;

            }

        }

    }while( uiCnt < uiLen );

//    while( !PollAck());

    return 1;

}



//////////////////////////////////////////////////////////////////////

//

BYTE EEPRead( WORD uiAddress, WORD uiLen, void *pBuf )

{

    UINT i;

   

    if ( uiLen == 0 ) return 0;

    if(!EEPStart(0xA0|EEADDR,EEWR)){    //PollAck() is built-in

        return 0;             //↑

    }    // not RD but write device address to the chip

    TWDR = (BYTE)(( uiAddress >> 8) & 0x00ff );    //((BYTE*)(&uiAddress))[1];    // MSB of address

    TWCR = (1<<TWINT)|(1<<TWEN);

    byEEWait = 3;    // 20~30ms

    while (!(TWCR & (1<<TWINT))){

        if( byEEWait == 0 )

            return FALSE;

    }

    if (TWI_STATUS != TW_MT_DATA_ACK)

        return FALSE;

    TWDR = (BYTE)( uiAddress & 0x00ff );    //((BYTE*)(&uiAddress))[0];        // LSB of address

    TWCR = (1<<TWINT)|(1<<TWEN);

    byEEWait = 3;    // 20~30ms

    while (!(TWCR & (1<<TWINT))){

        if( byEEWait == 0 )

            return FALSE;

    }

    if (TWI_STATUS != TW_MT_DATA_ACK)

        return FALSE;

    if(!EEPStart(0xA0+EEADDR,EERD)){    //PollAck()){

        return 0;             //↑

    }// ??? how to read?

    for ( i=0; i<uiLen-1; i++ ){

        TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWEA);

        byEEWait = 3;    // 20~30ms

        while (!(TWCR & (1<<TWINT))){

            if( byEEWait == 0 )

                return FALSE;

        }

        if (TWI_STATUS != TW_MR_DATA_ACK)

            return FALSE;

        ((BYTE*)pBuf) = TWDR;    // EEInByte();

    }

    TWCR = _BV(TWINT) | _BV(TWEN);    // send NACK to indicate final byte

    byEEWait = 3;    // 20~30ms

    while (!(TWCR & (1<<TWINT))){

        if( byEEWait == 0 )

            return FALSE;

    }

    //if (TWI_STATUS != TW_MR_DATA_ACK)

    //    return FALSE;

    ((BYTE*)pBuf) = TWDR;

    TwiStop();

    return 1;

}
头像被屏蔽

出0入0汤圆

发表于 2004-10-18 22:21:23 | 显示全部楼层
能不能将原理图及实物图也上传上来。这样,我就可以将它制作成范例的形式整理到网站了。



谢谢。



本论坛支持10M的压缩包的上传的。

出0入0汤圆

 楼主| 发表于 2004-10-19 21:33:04 | 显示全部楼层
这部分的原理图很简单的,就是M16的SCL(PC0),SDA(PC1)引脚分别和AT24c64的SCL,SDA引脚相连,再分别接一个上拉电阻。AT24c64的地址线多少根据总共连接的芯片数而定。我只接了

AT24c64一个芯片,所以把其A0,A1,A2全部接地了。
头像被屏蔽

出0入0汤圆

发表于 2004-10-19 21:36:01 | 显示全部楼层
如果sltain 画过线路图,能否上传上来? 没有线路图,做不成范例贴呢。
头像被屏蔽

出0入0汤圆

发表于 2004-10-19 21:36:30 | 显示全部楼层
如果sltain 画过线路图,能否上传上来? 没有线路图,做不成范例贴呢。

出0入0汤圆

 楼主| 发表于 2004-10-20 09:06:27 | 显示全部楼层
这是AT24C64接口的线路图,需要说明的是:AT24c64的地址线多少根据总共连接的芯片数而定。我只接了AT24c64一个芯片,所以把其A0,A1,A2全部接地了。

点击此处下载armok011142.rar
头像被屏蔽

出0入0汤圆

发表于 2004-10-20 10:29:39 | 显示全部楼层
谢谢sltian!



能不能将工作原理、可以应用在什么场合、输出结果、及某些注意事项稍为描述一下? 抱歉不断提要求,因为我也经验不足,呵呵。

出0入0汤圆

 楼主| 发表于 2004-10-20 11:06:15 | 显示全部楼层
我很菜的,刚开始学习AVR单片机,我就是想练习一下M16的TWI接口编程,应用的场合有很多,主要是你需要实时的将单片机监测的数据存储起来,等到需要的时候再将数据读出来。然后再分析数据,有点类似于黑匣子的功能。我用的就是监测的功能。这个程序只是一个读写的例子,用的时候可以把它作为子程序调用。

注意的问题就是抗干扰的问题。有可能AT24C64读取或者存取的时候指针受干扰跑飞了。

这个问题不好解决,我也没什莫经验。

为了支持阿莫,我贴出来就是让大家用的时候直接用它做子程序读写AT24C64。

主要的解释已经在程序里面了。
头像被屏蔽

出0入0汤圆

发表于 2004-10-20 11:13:07 | 显示全部楼层
谢谢sltian! 刚才讨论了一下,我们目前的范例应用,都是以实现特定目的作为主题的。



如果只是一个类似子程序的功能,不太符合应用范例的要求----- 我们担心收录了太多这种的内容后,就会影响范例应用的针对性。



所以,先缓一下,等你有空做出一个实际的小应用(那怕是驱动LED灯也算),才好处理。详细的要求,可以到 http://www.ouravr.com/app_index.html 看一下这些应用范例的内容。



又要说不好意思。网站刚成立,很多细节都需要摸索,希望你能支持一体谅。谢谢。

出0入0汤圆

 楼主| 发表于 2004-10-20 11:34:14 | 显示全部楼层
没有关系呀,我知道了。我从网站上学习了好多东西。希望阿莫继续努力
头像被屏蔽

出0入0汤圆

发表于 2004-10-20 12:39:05 | 显示全部楼层
如果你有空,能否将它做成一个小应用? 这么好的代码,浪费了可惜啊。谢谢。

出0入0汤圆

 楼主| 发表于 2004-10-21 08:26:44 | 显示全部楼层
好的。

出0入0汤圆

发表于 2004-12-17 00:05:05 | 显示全部楼层
不够通用,没有抽象出来,新手看了这个还是会头晕的
头像被屏蔽

出0入0汤圆

发表于 2004-12-17 00:12:56 | 显示全部楼层
对。所以,只有整理成应用范例的形式,对其它人才更有参考价值。

出0入0汤圆

发表于 2004-12-17 10:56:38 | 显示全部楼层
程序一大串,应该有个说明文档,再加点必要注释,尤其是用到的

标准C里没有的库函数,简单说明一下,可读性会强很多。方便其

他人应用。

出0入0汤圆

发表于 2005-5-15 16:22:00 | 显示全部楼层
恩人呀!!!就是它了!!!

出10入210汤圆

发表于 2005-8-3 13:05:57 | 显示全部楼层
ERRORS:67    Warnings:24

出0入0汤圆

发表于 2005-8-7 16:41:54 | 显示全部楼层
#include "DStruct.h"

这个库函数 怎样定义的 能把所有代码给出来吗

出0入0汤圆

发表于 2006-11-24 23:21:49 | 显示全部楼层
AT24CXX的资料里,只介绍到24C32 到24C64的分资料写的很模糊.

不知楼主能不能在这里介绍一下.

我找了好多地方,都没有详细介绍的.



我的AT24C04 调试过去了.可是24C64在页写的地方有点错误





请楼主指教

出0入0汤圆

发表于 2007-6-14 15:14:23 | 显示全部楼层
不知道各位大虾们怎么写程序,我写程序都会写注释,不然自己写的程序,一个月后,自己都会看不懂,尤其很大的程序!

出0入0汤圆

发表于 2007-7-12 21:50:49 | 显示全部楼层
void read_sc(uchar ip,uchar * sc)

{

        ReadPage24C32(SC_ADDRESS+((uint)ip<<4),32,sc);

}

int write_sc(uchar ip,uchar * sc)

{

        uchar buf1[32],buf2[32];

        uchar i;

        for(i=0;i<32;i++)buf1=sc;

        WritePage24C32(SC_ADDRESS+((uint)ip<<4),buf1,32);

        read_sc(ip,buf2);

        for(i=0;i<32;i++)

        {

                if(buf1!=buf2)return -1;

        }

        return 0;

}



怎么通过这个读写数据呢

出0入0汤圆

发表于 2007-7-12 21:52:22 | 显示全部楼层
版主教教我啊

出0入0汤圆

发表于 2007-7-12 22:57:51 | 显示全部楼层
可惜不是中断处理

出0入0汤圆

发表于 2008-3-4 11:19:55 | 显示全部楼层
好贴,顶一个,大家多多交流阿!

出0入0汤圆

发表于 2008-3-5 14:14:03 | 显示全部楼层
#include "DStruct.h"
#include <avr/twi.h>
这两个都没有给出,运行不能通过,是怎么回事啊?

出0入0汤圆

发表于 2008-4-25 18:21:44 | 显示全部楼层
怎么这么不好阅读呢

出0入0汤圆

发表于 2009-2-23 21:01:00 | 显示全部楼层
写的太棒了,正是我要的,但有一句有点小问题,也许我没理解:if ((TWI_STATUS != TW_START)&&(TWI_STATUS != TW_REP_START))
似乎当写为:if ((TWI_STATUS != TW_START)||(TWI_STATUS != TW_REP_START))
如不对,请楼主不要生气。
发送程序,芯片资料中可参考,但接收程序及其反回的状态代码,资料中并不详,这里全有了,太好了。
我特别注意到的是:BYTE EEPRead( WORD uiAddress, WORD uiLen, void *pBuf )
{
    UINT i;
     
    if ( uiLen == 0 ) return 0;
    if(!EEPStart(0xA0|EEADDR,EEWR)){    //PollAck() is built-in
        return 0;             //↑
    }    // not RD but write device address to the chi
。。。。。。我原先写的大意是:if(!EEPStart(0xA0|EEADDR,EERD)),老跑不通,明师在这里指点了。盗下来,盗下来,谢谢了,感谢被盗者的幸劳。

出0入0汤圆

发表于 2009-2-23 21:23:01 | 显示全部楼层
#include "DStruct.h"  
#include <avr/twi.h>
兴奋之余,给弟兄们粗略地解释一下:这两个头文件可能是楼主自定义的两个头文件,无非是定义数的结构和给TWI中的寄存器换个名称而已。比如说:#define TWI_STATUS TWSR 再比方说:有一个延时函数必在头文件中,其中有个变量为 byEEWait,也有可能这个变量在某个时间中断里,它在递减。这样如果发送或接收超时的话要报警的,至于各人的需要,要在这个程序上改动的。
还有从程序中看出,一次性最多只可发送32个数据。这些可以看看芯片资料。

说上面的这些废话,主要是报达一下对楼主的一点谢意。我也公开一点自己的想法。不知有没有人谢我。不谢没事,别骂就行,哈哈。

出0入0汤圆

发表于 2009-9-11 22:18:26 | 显示全部楼层
好贴啊

出0入0汤圆

发表于 2009-10-26 15:35:26 | 显示全部楼层
不錯,正在找這方面的,謝謝了!

出0入0汤圆

发表于 2010-6-8 21:34:12 | 显示全部楼层
学些了

出0入0汤圆

发表于 2011-9-15 21:52:53 | 显示全部楼层
MARK

出0入0汤圆

发表于 2013-5-12 16:35:26 | 显示全部楼层
iic程序怎么那么长,看着都郁闷。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 06:04

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表