搜索
bottom↓
回复: 19

ATmega8 TWI读写AT24C64终于调通,程序共享

[复制链接]

出0入0汤圆

发表于 2007-12-17 19:08:40 | 显示全部楼层 |阅读模式
#ifndef __TWI_H__
#define __TWI_H__

#define TWI_SLA_RW 0XA0
#define TWI_CHECK 1


#ifdef __TWI_C__

void twi_init(void);
#ifdef TWI_SLA_RW
uint8 TWI_WriteNByte(uint16 addr,uint8 *pdata, uint8  size);
uint8 TWI_WriteByte(uint16 addr ,uint8 data);
#else
uint8 TWI_WriteNByte(uint8 TWI_SLA_RW, uint16 addr ,uint8 *pdata, uint8 size);
uint8 TWI_WriteByte(uint8 TWI_SLA_RW, uint16 addr ,uint8 data);
#endif


#ifdef TWI_SLA_RW
uint8 TWI_ReadNByte(uint16 addr,uint8 *pdata, uint8 size) ;
uint8 TWI_ReadByte(uint16 addr, uint8 *pdata) ;
#else
uint8 TWI_ReadNByte(uint8 TWI_SLA_RW,  uint16 addr, uint8 *pdata, uint8 size) ;
uint8 TWI_ReadByte(uint8 TWI_SLA_RW,  uint16 addr, uint8 *pdata) ;
#endif

#endif   //__TWI_C__


#ifndef __TWI_C__
extern void twi_init(void);
#ifdef TWI_SLA_RW
extern uint8 TWI_WriteNByte(uint16 addr,uint8 *pdata, uint8 size);
extern uint8 TWI_WriteByte(uint16 addr ,uint8 data);
#else
extern uint8 TWI_WriteNByte(uint8 TWI_SLA_RW, uint16 addr ,uint8 *pdata, uint8 size);
extern uint8 TWI_WriteByte(uint8 TWI_SLA_RW, uint16 addr ,uint8 data);
#endif


#ifdef TWI_SLA_RW
extern uint8 TWI_ReadNByte(uint16 addr,uint8 *pdata, uint8 size) ;
extern uint8 TWI_ReadByte(uint16 addr, uint8 *pdata) ;
#else
extern uint8 TWI_ReadNByte(uint8 TWI_SLA_RW,  uint16 addr, uint8 *pdata, uint8 size) ;
extern uint8 TWI_ReadByte(uint8 TWI_SLA_RW,  uint16 addr, uint8 *pdata) ;
#endif

#endif   //__TWI_C__


#endif  // __TWI_H__




#define __TWI_C__

#include  "config.h"

#define F_SCL    100000
#if  F_SCL*36>F_CPU
  #define TWBR_INIT    10
  #warning "比特率达不到F_SCL"
#else
  #define TWBR_INIT    ((F_CPU/F_SCL-16)/2)
#endif
   
  
#define TWI_START()            (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define TWI_RESTART()          (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define TWI_STATUS()           (TWSR&0xf8)
#define TWI_LOADDATA(x)        do{TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}while(0)
#define TWI_STOP()             TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
#define TWI_WAIT()             do{while(!(TWCR&(1<<TWINT)));}while(0)  
   
   
   

void twi_init(void)  
{  
    TWCR= 0X00;
    TWBR= TWBR_INIT;
    TWSR= 0;  
    TWCR= _BV(TWEN);
}

#define TWI_ReStart() TWI_Start()

uint8 TWI_Start(void)
{
  TWI_START();
  TWI_WAIT();
  return TWI_STATUS();  
}

void TWI_Stop()
{
   TWI_STOP();
}


uint8 TWI_SendData(uint8 data)
{
  TWI_LOADDATA(data);
  TWI_WAIT();
  return TWI_STATUS();  
}

uint8 TWI_ReceiveData(uint8 *pdata,uint8 ack)
{
  uint8 temp=_BV(TWINT)|_BV(TWEN);
  if(ack)
  {
    temp|=_BV(TWEA);
  }
  TWCR=temp;
  TWI_WAIT();
  pdata[0]=TWDR;
  return TWI_STATUS();
}


#if TWI_CHECK==1 //校验读写是否成功

/******************************************
               TWI总线写1个字节
               返回1:写成功
               返回0:写失败
*******************************************/

#ifdef TWI_SLA_RW
uint8 TWI_WriteByte(uint16 addr ,uint8 data)
#else
uint8 TWI_WriteByte(uint8 TWI_SLA_RW, uint16 addr ,uint8 data)
#endif
{
          if(TWI_Start()!=TW_START) return 0;
          if(TWI_SendData(TWI_SLA_RW&0XFE)!=TW_MT_SLA_ACK) return 0;
          if(TWI_SendData(addr>>8)!=TW_MT_DATA_ACK) return 0;
          if(TWI_SendData(addr)!=TW_MT_DATA_ACK) return 0;
          if(TWI_SendData(data)!=TW_MT_DATA_ACK) return 0;        
          TWI_Stop();
          return 1;
}




/******************************************
               TWI总线写N(N>=1)个字节
               返回1:写成功
               返回0:写失败
*******************************************/

#ifdef TWI_SLA_RW
uint8 TWI_WriteNByte(uint16 addr,uint8 *pdata, uint8 size)
#else
uint8 TWI_WriteNByte(uint8 TWI_SLAW, uint16 addr ,uint8 *pdata, uint8 size)
#endif
{         uint8 i;
          if(TWI_Start()!=TW_START) return 0;
          if(TWI_SendData(TWI_SLA_RW&0xFE)!=TW_MT_SLA_ACK) return 0;
          if(TWI_SendData(addr>>8)!=TW_MT_DATA_ACK) return 0;
          if(TWI_SendData(addr)!=TW_MT_DATA_ACK) return 0;
         
          for(i=0;i<size;i++)
            {
             if(TWI_SendData(pdata)!=TW_MT_DATA_ACK) return 0;        
            }
          TWI_Stop();
          return 1;
}


/******************************************
               TWI总线读1个字节
               返回1:读成功
               返回0:读失败
*******************************************/
#ifdef TWI_SLA_RW
uint8 TWI_ReadByte(uint16 addr, uint8 *pdata)
#else
uint8 TWI_ReadByte(uint8 TWI_SLAR,  uint16 addr, uint8 *pdata)
#endif

      {
          if(TWI_Start()!=TW_START) return 0;
          if(TWI_SendData(TWI_SLA_RW&0xFE)!=TW_MT_SLA_ACK) return 0;
          if(TWI_SendData(addr>>8)!=TW_MT_DATA_ACK) return 0;
          if(TWI_SendData(addr)!=TW_MT_DATA_ACK) return 0;
          if(TWI_ReStart()!=TW_REP_START)return 0;
          if(TWI_SendData(TWI_SLA_RW|0X01)!=TW_MR_SLA_ACK) return 0;
          if(TWI_ReceiveData(&pdata[0],0)!=TW_MR_DATA_NACK) return 0;           
          TWI_Stop();
          return 1;
      }




/******************************************
               TWI总线读N(N>=1)个字节
               返回1:读成功
               返回0:读失败
*******************************************/

#ifdef TWI_SLA_RW
uint8 TWI_ReadNByte(uint16 addr,uint8 *pdata, uint8 size)
#else
uint8 TWI_ReadNByte(uint8 TWI_SLAR,  uint16 addr, uint8 *pdata, uint8 size)
#endif
     {
          uint8 i;
          if(TWI_Start()!=TW_START) return 0;
          if(TWI_SendData(TWI_SLA_RW&0XFE)!=TW_MT_SLA_ACK) return 0;
          if(TWI_SendData(addr>>8)!=TW_MT_DATA_ACK) return 0;
          if(TWI_SendData(addr)!=TW_MT_DATA_ACK) return 0;
          if(TWI_ReStart()!=TW_REP_START)return 0;
          if(TWI_SendData(TWI_SLA_RW|0X01)!=TW_MR_SLA_ACK) return 0;
         
          for(i=0;i<size-1;i++)
            {
             if(TWI_ReceiveData(&pdata,1)!=TW_MR_DATA_ACK) return 0;        
            }
          if(TWI_ReceiveData(&pdata,0)!=TW_MR_DATA_NACK) return 0;
         
          TWI_Stop();
          return 1;
      }


#else  //TWI_CHECK==0  不校验读写是否成功


/******************************************
               TWI总线写1个字节
               不校验读写是否成功
*******************************************/
#ifdef TWI_SLA_RW
uint8 TWI_WriteByte(uint16 addr ,uint8 data)
#else
uint8 TWI_WriteByte(uint8 TWI_SLA_RW, uint16 addr ,uint8 data)
#endif
{
          TWI_Start();
          TWI_SendData(TWI_SLA_RW&0XFE);
          TWI_SendData(addr>>8);
          TWI_SendData(addr);
          TWI_SendData(data);   
          TWI_Stop();
          return 1;
}




/******************************************
               TWI总线写N(N>=1)个字节
               不校验读写是否成功
*******************************************/

#ifdef TWI_SLA_RW
uint8 TWI_WriteNByte(uint16 addr,uint8 *pdata, uint8 size)
#else
uint8 TWI_WriteNByte(uint8 TWI_SLAW, uint16 addr ,uint8 *pdata, uint8 size)
#endif
{         uint8 i;
          TWI_Start();
          TWI_SendData(TWI_SLA_RW&0xFE);
          TWI_SendData(addr>>8);
          TWI_SendData(addr);
         
          for(i=0;i<size;i++)
            {
            TWI_SendData(pdata);      
            }
          TWI_Stop();
          return 1;
}



/******************************************
               TWI总线读1个字节
               不校验读写是否成功
*******************************************/
#ifdef TWI_SLA_RW
uint8 TWI_ReadByte(uint16 addr, uint8 *pdata)
#else
uint8 TWI_ReadByte(uint8 TWI_SLAR,  uint16 addr, uint8 *pdata)
#endif

      {
          TWI_Start();
          TWI_SendData(TWI_SLA_RW&0xFE);
          TWI_SendData(addr>>8);
          TWI_SendData(addr);
          TWI_ReStart();
          TWI_SendData(TWI_SLA_RW|0X01);
          TWI_ReceiveData(&pdata[0],0);           
          TWI_Stop();
          return 1;
      }




/******************************************
               TWI总线读N(N>=1)个字节
               不校验读写是否成功
*******************************************/
#ifdef TWI_SLA_RW
uint8 TWI_ReadNByte(uint16 addr,uint8 *pdata, uint8 size)
#else
uint8 TWI_ReadNByte(uint8 TWI_SLAR,  uint16 addr, uint8 *pdata, uint8 size)
#endif
     {
          uint8 i;
          TWI_Start();
          TWI_SendData(TWI_SLA_RW&0XFE);
          TWI_SendData(addr>>8);
          TWI_SendData(addr);
          TWI_ReStart();
          TWI_SendData(TWI_SLA_RW|0X01);
         
          for(i=0;i<size-1;i++)
            {
             TWI_ReceiveData(&pdata,1);        
            }
          TWI_ReceiveData(&pdata,0);
         
          TWI_Stop();
          return 1;
      }


#endif //TWI_CHECK==0

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2007-12-18 10:19:54 | 显示全部楼层
进来支持一下~
:)

出0入0汤圆

发表于 2007-12-18 20:31:31 | 显示全部楼层
do{TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}while(0)
请问,为什么要加上do{}while(0)呢,有用吗?

还是有点迷糊

你能不能帮我解释一下我的问题:http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=873372&bbs_page_no=1&search_mode=3&search_text=feitian215&bbs_id=9999

出0入0汤圆

发表于 2007-12-18 21:01:26 | 显示全部楼层
我觉得你写的和我的差不多~~~~~没有什么本质上的区别

你用几V系统我用的是3.6V,24C16和电压应当也没有关系吧

出0入0汤圆

发表于 2007-12-18 21:12:12 | 显示全部楼层
收藏哈~~

出0入0汤圆

发表于 2007-12-19 11:22:34 | 显示全部楼层
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=873758&bbs_id=9999
请各位帮我看看我的问题!

出0入0汤圆

发表于 2007-12-20 14:40:48 | 显示全部楼层
ATmega32 cortex-m3
真是个大好人,很喜欢乐于助人

出0入0汤圆

发表于 2007-12-24 11:02:05 | 显示全部楼层
回楼主:
1.我觉得你这个计算是不是有点问题#define TWBR_INIT    ((F_CPU/F_SCL-16)/2),2最小应该是8才对吧
  手册上的最小分频值是1,按照公式就应该是除以8
2.你的读写NByte,不能实现按页连续读写吧.
3.问如果总线上有两片EEPROM,是不是应该写两函数来实现呢??

出0入0汤圆

 楼主| 发表于 2007-12-24 11:16:42 | 显示全部楼层
1.我初始TWPS=0;
F_SCL=F_CPU/(16+(TWBR)*2*4^TWPS)=F_CPU/(16+2*TWBR)

TWBR=((F_CPU/F_SCL-16)/2)

2.只能读取一页的N字节,不能翻页。

3.如果只有一个器件,用“#define TWI_SLA_RW   器件物理地址”,TWI_SLA_RW作为全局常量专递,
如果总线上有多个器件,把“#define TWI_SLA_RW”注释掉,程序中把TWI_SLA_RW作为参数专递。
此项还没验证过,我实验中只一片AT24C64。

出0入0汤圆

发表于 2007-12-24 11:34:11 | 显示全部楼层
回楼主:
1.TWPS =0 的分频值就是1呀而不是0吧
2.总线上有两片EEPROM,除了用参数传递还有其他方法吗

出0入0汤圆

发表于 2008-5-23 10:23:53 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2009-3-23 17:17:25 | 显示全部楼层
记号

出0入0汤圆

发表于 2009-5-8 17:33:31 | 显示全部楼层
请问一下具体的流程是什么呢?
我是一个新手,程序还是不了解的
谢谢

出0入0汤圆

发表于 2009-6-4 15:20:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-6-24 21:21:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-12 01:19:31 | 显示全部楼层
good

出0入0汤圆

发表于 2010-8-11 17:30:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-1 16:25:08 | 显示全部楼层
谢谢,能够用

出0入0汤圆

发表于 2011-6-2 10:07:12 | 显示全部楼层
刚学。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-10-3 16:55

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

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