打印
[AVR单片机]

AVR的IIC总线编程遇到一个问题

[复制链接]
1366|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zl101lz|  楼主 | 2015-8-9 17:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zl101lz 于 2015-8-9 19:49 编辑

以下代码是运行OK的 atmega16接了一个eeprom(AT240C02A)
会记录开机的次数
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int


//I2C 状态定义
//MT 主方式传输 MR 主方式接受
///////////////////////////////////////////////////
#define START    0x08
#define RE_START   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  

#define RD_DEVICE_ADDR 0xA1   //前4位器件固定,后三位看连线,最后1位是读写指令位
#define WD_DEVICE_ADDR 0xA0

//常用TWI操作(主模式写和读)
#define Start()                    (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))           //启动I2C
#define Stop()                    (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))           //停止I2C
#define Wait()                    {while(!(TWCR&(1<<TWINT)));}                                             //等待中断发生
#define TestAck()           (TWSR&0xf8)                                                                                                  //观察返回状态
#define SetAck                    (TWCR|=(1<<TWEA))                                                                                //做出ACK应答
#define SetNoAck                   (TWCR&=~(1<<TWEA))                                                                        //做出Not Ack应答
#define Twi()                            (TWCR=(1<<TWINT)|(1<<TWEN))                                        //启动I2C
#define Write8Bit(x)         {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}           //写数

unsigned char smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
unsigned char smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};

uchar table[8]={0,0,0,0,0,0,0,0};

void init(void)
{
DDRB=0xff;
PORTB=0;

DDRC=0x78;//01111000
PORTC=0;
}

void delay(void)
{
uint a;
for(a=0;a<300;a++);
}

void display(uchar *p)
{
uchar i;
for(i=0;i<8;i++)
{
  PORTB=smg_du[*p];
  p++;
  PORTC=smg_we[i];
  delay();
}

}

void twi_init(void)
{
TWBR=0x20;
TWCR=0x04;
TWSR=0;
}

uchar IIC_Write(uchar wdata,uchar addr)
{
Start();
Wait();
if(TestAck()!=START)
return 1;

Write8Bit(WD_DEVICE_ADDR);
Wait();
if(TestAck()!=MT_SLA_ACK)
return 1;

Write8Bit(addr);
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1;

Write8Bit(wdata);
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1;

Stop();
return 0;

}

uchar IIC_Read(uchar addr)
{
uchar temp;

Start();
Wait();
if(TestAck()!=START)
return 1;

Write8Bit(WD_DEVICE_ADDR);
Wait();
if(TestAck()!=MT_SLA_ACK)
return 1;

Write8Bit(addr);
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1;

Start();
Wait();
if(TestAck()!=RE_START)
return 1;

Write8Bit(RD_DEVICE_ADDR);
Wait();
if(TestAck()!=MR_SLA_ACK)
return 1;

Twi();
Wait();
if(TestAck()!=MR_DATA_NOACK)
return 1;

temp=TWDR;
Stop();
return temp;

}

void main(void)
{
uchar i;
init();
twi_init();
i=IIC_Read(0x03);
table[1]=i;
i++;
i=i%10;
IIC_Write(i,0x03);
table[0]=i;

我修改成以下的样子,其实就是加了两行代码,原来是IIC_READ→IIC_WRITE,现在改成IIC_READ→IIC_WRITE→IIC_READ结果就不行了

#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int


//I2C 状态定义
//MT 主方式传输 MR 主方式接受
///////////////////////////////////////////////////
#define START    0x08
#define RE_START   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  

#define RD_DEVICE_ADDR 0xA1   //前4位器件固定,后三位看连线,最后1位是读写指令位
#define WD_DEVICE_ADDR 0xA0

//常用TWI操作(主模式写和读)
#define Start()                    (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))           //启动I2C
#define Stop()                    (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))           //停止I2C
#define Wait()                    {while(!(TWCR&(1<<TWINT)));}                                             //等待中断发生
#define TestAck()           (TWSR&0xf8)                                                                                                  //观察返回状态
#define SetAck                    (TWCR|=(1<<TWEA))                                                                                //做出ACK应答
#define SetNoAck                   (TWCR&=~(1<<TWEA))                                                                        //做出Not Ack应答
#define Twi()                            (TWCR=(1<<TWINT)|(1<<TWEN))                                        //启动I2C
#define Write8Bit(x)         {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}           //写数

unsigned char smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
unsigned char smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};

uchar table[8]={0,0,0,0,0,0,0,0};

void init(void)
{
DDRB=0xff;
PORTB=0;

DDRC=0x78;//01111000
PORTC=0;
}

void delay(void)
{
uint a;
for(a=0;a<300;a++);
}

void display(uchar *p)
{
uchar i;
for(i=0;i<8;i++)
{
  PORTB=smg_du[*p];
  p++;
  PORTC=smg_we[i];
  delay();
}

}

void twi_init(void)
{
TWBR=0x20;
TWCR=0x04;
TWSR=0;
}

uchar IIC_Write(uchar wdata,uchar addr)
{
Start();
Wait();
if(TestAck()!=START)
return 1;

Write8Bit(WD_DEVICE_ADDR);
Wait();
if(TestAck()!=MT_SLA_ACK)
return 1;

Write8Bit(addr);
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1;

Write8Bit(wdata);
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1;

Stop();
return 0;

}

uchar IIC_Read(uchar addr)
{
uchar temp;

Start();
Wait();
if(TestAck()!=START)
return 9;

Write8Bit(WD_DEVICE_ADDR);
Wait();
if(TestAck()!=MT_SLA_ACK)
return 8;

Write8Bit(addr);
Wait();
if(TestAck()!=MT_DATA_ACK)
return 7;

Start();
Wait();
if(TestAck()!=RE_START)
return 6;

Write8Bit(RD_DEVICE_ADDR);
Wait();
if(TestAck()!=MR_SLA_ACK)
return 5;

Twi();
Wait();
if(TestAck()!=MR_DATA_NOACK)
return 4;

temp=TWDR;
Stop();
return temp;

}

void main(void)
{
uchar i;
init();
twi_init();
i=IIC_Read(0x03);
table[1]=i;
i++;
i=i%10;
IIC_Write(i,0x03);
table[0]=i;

i=IIC_Read(0x03);                   ☆
table[2]=i;                                ☆



while(1)
{
  display(table);
}

}
就是五角星的那两行,从返回的代码上看是第二次IIC_READ函数里的(TestAck()!=START)返回错误,
是不是IIC当前非空闲所以不能再读啊?

求解决方法

相关帖子

沙发
badbud| | 2015-8-21 14:50 | 只看该作者
加长延迟看看,这种读写大不分都是延迟时间不够

使用特权

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

本版积分规则

4

主题

6

帖子

0

粉丝