Chinaunix首页 | 论坛 | 博客
  • 博客访问: 401692
  • 博文数量: 29
  • 博客积分: 2091
  • 博客等级: 大尉
  • 技术积分: 463
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-05 10:53
文章分类
文章存档

2012年(2)

2011年(6)

2010年(12)

2009年(9)

我的朋友

分类: 嵌入式

2010-11-25 15:04:37

最近在弄一个简单的ATMEGA8项目,其中有用到使用硬件TWI(兼容I2C)接口读写24LC512。在网上搜了一下,读写24C02的例子不少,不过,都不能正常读写24LC512。其原因主要因为24C02的字节地址是一个字节的,24C512的字节地址是两个字节的。这是两者最大的区别。注意到这个细节,你应该就可以在24c02程序的基础上写出24C512的程序了。不过,这又存在一个新的问题,那就是24C02的读写是按字节进行的。且每写一个字节,都需延时几毫秒,才能正常写入,这在写24C512时,就会耗费大量的时间。实际上,24C512,24C256这样的芯片,还提供了页写和连续读方式。即可以一次写入多个字节(分别是128,64字节),可以一次读出全部字节,中间是不需延时的,极大提高读写速度。网上能找到的读写24c512的例子,都是用字节读写的,效率较低。我自已写了一个以页写和连续读的方式来读写24C512,24C256的例子。在此放出,以供大家参考。
 
说明一下,例子中是用查询方式来操作I2C的,这种方式易于理解不易出错。但会过多占用CPU时间,如对CPU时间占用敏感,可改用中断方式。
 
TWI_I2C.C
 
#include
#include
#include
#include "TWI_I2C.h"

/*********************************************
I2C 总线读多个字节,使用24C512连续读方式,一次可读完全部数据,这里限定一次读255字节
返回0:读成功
返回1:读失败
**********************************************/
unsigned char I2C_Read_Bytes(unsigned int address,unsigned char *databuf,unsigned char len)
{
 unsigned char posi;
 
 I2C_Start();//I2C 启动
 //Delay_1ms();
 I2C_Wait();
 
 if (I2C_TestAck()!=I2C_START)
  return 1; //ACK
 
 I2C_Write8Bit(WD_DEVICE_ADDR); //写I2C 从器件地址和写方式
 I2C_Wait();
 if (I2C_TestAck()!=MT_SLA_ACK)
  return 1; //ACK
 I2C_Write8Bit(address>>8); //写器件相应寄存器地址
 I2C_Wait();
 if (I2C_TestAck()!=MT_DATA_ACK)
  return 1;
 I2C_Write8Bit(address&0x00ff); //写器件相应寄存器地址
 I2C_Wait();
 if (I2C_TestAck()!=MT_DATA_ACK)
  return 1;
 I2C_Start(); //I2C 重新启动
 I2C_Wait();
 if (I2C_TestAck()!=I2C_RESTART)
  return 1;
 I2C_Write8Bit(RD_DEVICE_ADDR); //写I2C 从器件地址和读方式
 I2C_Wait();
 if(I2C_TestAck()!=MR_SLA_ACK)
  return 1; //ACK
 
 for(posi=0;posi {
  I2C_Twi_Ack(); //启动主I2C 读方式
  I2C_Wait();
  if(I2C_TestAck()!=MR_DATA_ACK)
   return 1; //ACK
  *(databuf+posi)=TWDR;//读取I2C 接收数据
 }
 I2C_Twi_NoAck(); //启动主I2C 读方式
 I2C_Wait();
 if(I2C_TestAck()!=MR_DATA_NOACK)
  return 1; //ACK
 *(databuf+posi)=TWDR;//读取I2C 接收数据

 I2C_Stop();//I2C 停止
 PORTB|=(1< return 0;
}
/*********************************************
I2C 总线写多个字节,使用页写模式,对于24C512,一次最多写128字节
返回0:写成功
返回1:写失败
**********************************************/
unsigned char I2C_Write_Bytes(unsigned int address,unsigned char *databuf,unsigned char len)
{
 unsigned char posi;
 I2C_Start(); //I2C 启动
 I2C_Wait();
 if(I2C_TestAck()!=I2C_START)
 return 1; //ACK
 
 I2C_Write8Bit(WD_DEVICE_ADDR); //写I2C 从器件地址和写方式
 
 I2C_Wait();
 
 if(I2C_TestAck()!=MT_SLA_ACK)
  return 1; //ACK
  
 I2C_Write8Bit(address>>8); //写器件相应寄存器地址
 I2C_Wait();
 if(I2C_TestAck()!=MT_DATA_ACK)
  return 1; //ACK
 I2C_Write8Bit(address&0x00ff); //写器件相应寄存器地址
 I2C_Wait();
 if(I2C_TestAck()!=MT_DATA_ACK)
  return 1; //ACK
    for(posi=0;posi {
  I2C_Write8Bit(*(databuf+posi)); //写数据到器件相应寄存器
  I2C_Wait();
  if(I2C_TestAck()!=MT_DATA_ACK)
   return 1; //ACK
 }
 I2C_Stop(); //I2C 停止
 _delay_ms(10); //延时
 return 0;
}
void TWI_Init(void)
{
 TWBR=0x03; //I2C 初始化,400kbps
 TWSR|=(1<}
TWI_I2C.h
 
#ifndef TWI_I2C_H
#define TWI_I2C_H
/*TWI_I2C.h*/
//I2C 状态定义
//MT 主方式传输;MR 主方式接收
#define I2C_START 0x08
#define I2C_RESTART 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
//常用TWI 操作(主模式写和读)
#define I2C_Start() (TWCR=(1<#define I2C_Stop() (TWCR=(1<#define I2C_Wait() {while(!(TWCR&(1<#define I2C_TestAck() (TWSR&0xf8) //观察返回状态
#define I2C_SetAck (TWCR|=(1<#define I2C_SetNoAck (TWCR&=~(1<#define I2C_Twi_NoAck() (TWCR=(1<#define I2C_Twi_Ack() (TWCR=(1<#define I2C_Write8Bit(x) {TWDR=(x);TWCR=(1<#define RD_DEVICE_ADDR 0xA1 //前4 位器件固定,后三位看连线,最后1 位是读写指令位
#define WD_DEVICE_ADDR 0xA0
extern void TWI_Init(void);
extern unsigned char I2C_Read_Bytes(unsigned int address,unsigned char *databuf,unsigned char len);
extern unsigned char I2C_Write_Bytes(unsigned int address,unsigned char *databuf,unsigned char len);
#endif
 
上述例子用winavr20100110编译通过,读写正常。
阅读(8342) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~