打印
[AVR单片机]

急。。。求教!ATmega16的TWI接口程序问题

[复制链接]
4254|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sea1105|  楼主 | 2011-9-8 14:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
正在做的一个产品需要用TWI口读写24c16,直接copy了 AVR学习笔记上的一个使用查询方式读写24c16的程序,可是加进我的测试程序以后却怎么也不行???//AT24C16地址声明
#define EEPROM_BUS_ADDRESS  0xa0         //器件地址
//主机发送模式时各状态字的后续动作
#define TW_START            0x08        //开始信号已发出
#define TW_REP_START        0x10        //重复开始信号已发出
#define TW_MT_SLA_ACK       0x18        //写字节已发出并收到ACK信号  
#define TW_MT_SLA_NACK      0x20        //写字节已发出并收到NACK信号  
#define TW_MT_DATA_ACK      0x28        //数据已发出并收到ACK 信号
#define TW_MT_DATA_NACK     0x30        //数据已发出并收到NACK 信号
#define TW_MT_ARB_LOST      0x38        //丢失总线控制权
//主机接收模式时各状态字的后续动作
#define TW_MR_ARB_LOST      0x38        //丢失总线控制权,未收到应答信号
#define TW_MR_SLA_ACK       0x40        //读命令已发出并收到ACK
#define TW_MR_SLA_NACK      0x48        //读命令已发出并收到NACK
#define TW_MR_DATA_ACK      0x50        //数据已收到,ACK已发出
#define TW_MR_DATA_NACK     0x58        //数据已收到,NACK已发出

unsigned long E1_data=0,E2_data=0;            //E1_data:机车牵引消耗电量,E2_data:机车再生制动电量
uchar count,count_1,count_2,flag;             //标志位   

void Initial_MCU(void);                       //Atmega16初始化程序
void Write_7219(uchar address,uchar data);    //MAX7219地址、数据发送子程序
void Initial_7219(void);                      //MAX7219初始化程序
void Show_7219(unsigned long data);           //计算8个数码管分别显示的数字

void I2C_Init(void);                                           //I2C端口初始化
uchar I2C_Start(void);                                         //发送起始信号
void I2C_Stop(void);                                           //发送结束信号
uchar I2C_WriteByte(uchar data);            //写一个字节
uchar I2C_ReadByte(uchar ack);             //读一个字节
uchar EEPROM_ReadByte(uint add);                                  //从固定地址读一字节
void EEPROM_WriteByte(uint add,uchar data);                       //向固定地址写一字节
void EEPROM_ReadPage(uint add,uchar n,uchar *data);               //多字节读操作
void EEPROM_WritePage(uint add,uchar n,uchar *data);              //多字节写操作

//I2C初始化函数
void I2C_Init(void)
{

TWSR = 0x00;    //不分频

TWBR = 0x20;    //波特率f(scl)=100kHz

TWAR = 0x00;    //被控器地址寄存器

TWCR = (1 << TWEA) | (1 << TWEN);         //允许ACK,使能I2C,PC0、PC1转换成SCL、SDA引脚
}
//I2C起始条件
uchar I2C_Start(void)
{

TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);   //清零中断标志位,发送START信号

while(!(TWCR & (1 << TWINT)));         //检测中断标志,为1表明完成发送开始信号


return 1;
}
//I2C结束条件
void I2C_Stop(void)
{

TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);   //清零中断标志位,发送STOP信号

}
//向I2C写一个字节
uchar I2C_WriteByte(uchar data)
{

uchar ack;


TWDR = data;                           //发送数据写入I2C数据寄存器

TWCR = (1 << TWINT) | (1 << TWEN);     //清零中断标志位,开始发送

while(!(TWCR & (1 << TWINT)));         //等待发送完成

if((TWSR &0xf8) != TW_MT_SLA_ACK)      //读取ACK信号

{

ack = 0;            //没有返回ACK

}

else

{

ack = 1;        //返回ACK


}

return ack;
}
//从I2C读一个字节 ACK时,应答,NACK时,不应答
uchar I2C_ReadByte(uchar ack)
{


if (ack)
       TWCR = (1<<TWINT) | (1<<TWEA) | (1 << TWEN);   // 读数据,并回送ACK
  else
       TWCR = (1<<TWINT) | (1 << TWEN);               //读数据,并回送NACK
  while (!(TWCR & (1 << TWINT)));    //等待操作完成


return (TWDR);     //返回读到的数据
}
//从固定地址读一字节
uchar EEPROM_ReadByte(uint add)
{

uchar data;


I2C_Start();
// 发起始信号
  I2C_WriteByte(EEPROM_BUS_ADDRESS | ((add >> 8) << 1));
   //发器件地址和页地址高三位

I2C_WriteByte(add);
// 发页地址低4位和页地址偏移量
  I2C_Start();   
// 发起始信号
  I2C_WriteByte(EEPROM_BUS_ADDRESS | 0x01);
// 发从机读寻址字节   
  data = I2C_ReadByte(0);         //读数据,并发送NACK
  I2C_Stop();
// 发停止信号

return data;
}
//向固定地址写一字节
void EEPROM_WriteByte(uint add,uchar data)
{

I2C_Start();
// 发起始信号
   I2C_WriteByte(EEPROM_BUS_ADDRESS | ((add >> 8) << 1));
                          // 发器件地址和页地址高三位
   

I2C_WriteByte(add);
// 发页地址低4位和页地址偏移量
   I2C_WriteByte(data);
// 写一个字节数据到24C16
   I2C_Stop();
// 发停止信号
   delay_nms(10);
// 等待10ms,保证24C16内部写操作完成再进行新操作
}
//多字节读操作
void EEPROM_ReadPage(uint add,uchar n,uchar *data)
{
  uchar i;

I2C_Start();
// 发起始信号
  I2C_WriteByte(EEPROM_BUS_ADDRESS | ((add >> 8) << 1));
    //发器件地址和页地址高三位

I2C_WriteByte(add);
// 发页地址低4位和页地址偏移量

I2C_Start();   
// 发起始信号
  I2C_WriteByte(EEPROM_BUS_ADDRESS | 0x01);
// 发从机读寻址字节   
  for(i = 0;i < n-1;i++)              //读n-1个数据

{

*data = I2C_ReadByte(1);         //读数据,并发送ACK

data++;

}

*data = I2C_ReadByte(0);         //读 最后一个数据,并发送NACK
  I2C_Stop();
// 发停止信号

}
//多字节写操作
void EEPROM_WritePage(uint add,uchar n,uchar *data)  
{

uchar i;


I2C_Start();
// 发起始信号
  I2C_WriteByte(EEPROM_BUS_ADDRESS | ((add >> 8) << 1));
   // 发器件地址和页地址高三位

I2C_WriteByte(add);
// 发页地址低4位和页地址偏移量
  for(i = 0;i <= n-1;i++)

{

I2C_WriteByte(*data++);
// 写一个字节数据到24C16

   }

I2C_Stop();
// 发停止信号
  delay_nms(10);
// 等待10ms,保证24C16内部写操作完成再进行新操作
}


主程序里加了:  
I2C_Init();
  EEPROM_WriteByte(0x01aa,0x5a);
  E1_data=EEPROM_ReadByte(0x01aa);

我的测试程序原先一直运行正常,加了这个读写的程序以后好像就一直不停复位。。。。。查了好久查不出问题,求高手帮忙,急急急!

相关帖子

沙发
NE5532| | 2011-9-8 20:42 | 只看该作者
COPY别人看不懂的程序=自杀,楼主自己动手吧。

使用特权

评论回复
板凳
sea1105|  楼主 | 2011-9-11 21:21 | 只看该作者
3# 928315 谢谢,找到原因了,不是copy的程序的原因,呵呵,多谢你的指点

使用特权

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

本版积分规则

个人签名:25岁的我——年轻无极限! 30岁之前——实现梦想!

6

主题

54

帖子

0

粉丝