用ATmega8的TWI(I2C)对一片24C02的读写

I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。CPU发出的控制信号分为地址码和控制量两部分,地址码用来选址,即接通需要控制的电路,确定控制的种类;控制量决定该调整的类别(如对比度、亮度等)及需要调整的量。这样,各控制电路虽然挂在同一条总线上,却彼此独立,互不相关。

  I2C总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。

  开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

  结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

  应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

  这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。

     

 

/***********************************

*实验目的:用ATmega8的TWI(I2C)对一片24C02的读写

*设    计:杨楚鵾

*日    期:2009-2-22

************************************/


#include <iom8v.h>
#include <macros.h>

/*I2C总线主机模式错误处理*/
void error(unsigned char type) {

 switch (type & 0xF8) {
  case 0x20:     /*址址写失败*/
   /*stop 停止*/
   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
   break;
  case 0x30:     /*数据写失败*/
   /*stop 停止*/
   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
   break;
  case 0x38:     /*仲裁失败*/
   break;
  case 0x48:     /*址址读失败*/
   /*stop 停止*/
   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
   break;
  }
}

/*I2C总线单字节写入*/
unsigned char twi_write(unsigned char addr, unsigned char dd) {

 TWBR = 2;

 /*start 启动*/
 TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x08) {
  error(TWSR);
  return 0;
  }

 /*SLA_W 芯片地址*/
 TWDR = 0xA0;
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x18) {
  error(TWSR);
  return 0;
  }

 /*addr 操作地址*/
 TWDR = addr;
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x28) {
  error(TWSR);
  return 0;
  }
 
 /*dd 写入数据*/
 TWDR = dd;
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x28) {
  error(TWSR);
  return 0;
  }
 
 /*stop 停止*/
 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
 return 1;
}

/*I2C总线单字节读取*/
unsigned char twi_read(unsigned char addr, unsigned char *dd) {

 TWBR = 2;
 /*start 启动*/
 TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
 while(!(TWCR&(1<<TWINT)));
 if ((TWSR & 0xF8) != 0x08) {
  error(TWSR);
  return 0;
  }

 /*SLA_W 芯片地址*/
 TWDR = 0xA0;
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x18) {
  error(TWSR);
  return 0;
  }

 /*addr 操作地址*/
 TWDR = addr;
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x28) {
  error(TWSR);
  return 0;
  }
  
 /*start 启动*/
 TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x10) {
  error(TWSR);
  return 0;
  }
 
 /*SLA_R 芯片地址*/
 TWDR = 0xA1;
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x40) {
  error(TWSR);
  return 0;
  }

 /*读取数据*/
 TWCR = (1 << TWINT) | (1 << TWEN);
 while (!(TWCR & (1 << TWINT)));
 if ((TWSR & 0xF8) != 0x58) {
  error(TWSR);
  return 0;
  }
 *dd = TWDR; 
 /*stop 停止*/
 TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
 return 1;
}


/*延时函数*/
void delay_ms(unsigned char i) {

 unsigned char a, b;
 for (a = 1; a < i; a++) {
  for (b = 1; b; b++) {
   ;
   }
  }
}

void main(void) {

 unsigned char temp;
 PORTB = 0xFF;    /*电平设置*/
 DDRB = 0xFF;    /*方向输入*/
 PORTC = 0xFF;
 DDRC = 0x00;
 PORTD = 0xFF;
 DDRD = 0x00;
 
 twi_read(0x08, &temp);
 PORTB = ~temp;
 temp ++;
 twi_write(0x08, temp);

 while (1) {
  ;
  }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值