打印
[Atmel]

ATmega16 TWI 主发从接小程序请教

[复制链接]
939|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dapollo2014|  楼主 | 2014-9-29 16:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 dapollo2014 于 2014-9-30 10:33 编辑

小弟正在学习AVR,这两天在看TWI,用两个ATmega16板,编了一个主发从接,然后同步闪烁LED的小程序,可是从机怎么都没反应,看Error函数貌似主机没有收到发送地址的反馈,论坛里的高手能否指教一下,问题出在哪里,不胜感激!

主机

#include <util/delay.h>
#include <compat/twi.h>

unsigned char runlight[7]={0x10,0x30,0x70,0xf0,0x70,0x30,0x10};
unsigned char status;

#define ADDRESS                0X33

void TWI_IO_Initial()
{
        DDRA=0XF0;//set IO port PA4~7 to light on LED
        PORTA=0XF0;
        _delay_ms(300);
}

void TWI_Initial()
{
        DDRC&=~((1<<0)|(1<<1));//set TWI port PC0~1
        PORTC|=(1<<0)|(1<<1);
        TWBR=0X64;
        TWSR=0X00;
}

void TWI_Error1()
{
        while(1)
        {
                PORTA=0X10;
                _delay_ms(1000);
                PORTA=0X00;
                _delay_ms(1000);        
        }

}

void TWI_Error2()
{
        while(1)
        {
                PORTA=0X20;
                _delay_ms(1000);
                PORTA=0X00;
                _delay_ms(1000);        
        }

}

void TWI_Error3()
{
        while(1)
        {
                PORTA=0X40;
                _delay_ms(1000);
                PORTA=0X00;
                _delay_ms(1000);        
        }

}

unsigned char TWI_Start()
{
        TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
        while(!(TWCR&(1<<TWINT)))
        ;
        status=TWSR&0XF8;
        TWCR&=~(1<<TWSTA);//TWSTA清零
}

void TWI_SendByte(unsigned char data)
{
        TWDR=data;
        TWCR|=(1<<TWINT)|(1<<TWEN);
        while(!(TWCR&(1<<TWINT)))
        ;
        status=TWSR&0XF8;
}

void TWI_Stop()
{
        TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

int main(void)
{
        TWI_Initial();
        TWI_IO_Initial();
        while(1)
        {
                TWI_Start();
                if(status!=TW_START)
                TWI_Error1();
                TWI_SendByte((ADDRESS<<1)|TW_WRITE);
                if(status!=TW_MT_SLA_ACK)
                TWI_Error2();
                unsigned char i;
                for(i=0;i<7;i++)
                {
                        TWI_SendByte(runlight);
                        if(status!=TW_MT_DATA_ACK)
                        TWI_Error3();
                        PORTA=runlight;
                        _delay_ms(1000);
                }
                TWI_Stop();
        }
}


从机

#include <util/delay.h>
#include <compat/twi.h>

#define ADDRESS                0X33

void TWI_IO_Initial()
{
        DDRA=0XF0;//set IO port
PA4~7to light on LED
        PORTA=0XF0;
}

void TWI_Initial()
{
        DDRC&=~((1<<0)|(1<<1));//set TWI port PC0~1
        PORTC|=(1<<0)|(1<<1);
        TWCR=0X00;
        TWBR=0X64;
        TWAR=ADDRESS<<1;
        TWCR|=(1<<TWEN)|(1<<TWEA)|(1<<TWIE);
}


int main(void)
{
        TWI_Initial();
        TWI_IO_Initial();
        while(1)
        {
                TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
                while(!(TWCR&(1<<TWINT)))
                ;
                unsigned char status=TWSR&0XF8;
                switch(status)
                {
                        case TW_SR_SLA_ACK:
                        break;
                        case TW_SR_DATA_ACK:
                        PORTA=TWDR;
                        break;
                        break;
                        case TW_SR_STOP:
                        break;
                        default:break;
                }

        }
}


相关帖子

沙发
ddllxxrr| | 2014-9-30 19:48 | 只看该作者
通讯过程好像少了很多的状态判断,给你个例程,你看看,我觉得你的好像协议没有搞全的样子。
下面是主从都用一个的程序:

#include <iom16v.h>
#include <macros.h>
#define  uchar unsigned   char
#define  uint  unsigned   int
#define  ulong unsigned   long
//MASTER SEND MODE
#define  START            0X08//主机START已发送
#define  REPEATED_START   0X10//主机RESTART已发送
#define  MT_SLA_ACK       0X18//主机发送地址已应答WRITE
#define  MT_SLA_NACK      0X20//主机发送地址非应答WRITE
#define  MT_DATA_ACK      0X28//主机发送数据已应答
#define  MT_DATA_NACK     0X30//主机发送数据非应答
#define  MT_SLA_FAIL      0X38//主机寻址仲裁失败WRITE OR READ
//MASTER RECEIVE MODE
#define  MR_SLA_ACK       0X40//主机发送地址已应答READ
#define  MR_SLA_NACK      0X48//主机发送地址非应答READ
#define  MR_DATA_ACK      0X50//主机接收数据已应答
#define  MR_DATA_NACK     0X58//主机接收数据非应答
//SLAVE RECEIVE MODE
#define  SR_SLA_ACK       0X60//从机接收地址响应
#define  SR_SLA_FAIL      0X68//作为主机仲裁失败,自己的ALT+W被接收
#define  SR_GCA_ACK       0X70//从机接收广播响应
#define  SR_GCA_FAIL      0X78//作为主机仲裁失败,接收到广播地址
#define  SR_DATA_ACK      0X80//从机接收数据响应
#define  SR_DATA_NACK     0X88//从机接收数据非应答
#define  SR_GCA_DATA_ACK  0X90//从机接收广播数据应答
#define  SR_GCA_DATA_NACK 0X98//从机接收广播数据非应答
#define  SR_STOP_RESTART  0xA0//从机工作时收到STOP或RESTART
//SLAVE SEND MODE
#define  ST_SLA_ACK       0XA8//从机发送地址应答
#define  ST_SLA_FAIL      0XB0//作为主机仲裁失败,自己的ALT+R被接收
#define  ST_DATA_ACK      0XB8//从机发送数据应答
#define  ST_DATA_NACK     0XC0//从机发送数据非应答
#define  ST_BYTE_ACK      0XC8//数据已发送,接收到ACK
//ELSE
#define  NA               0XF8//没有相关状态信息
#define  ILLEGAL          0X00//由于非法的START或STOP引起的总线错误

#define  START_SIGNAL()   (TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN))           //开始信号
#define  WAIT_TWINT()     while(!(TWCR & (1<<TWINT)))                            //等待发送结束TWINT置位
#define  TEST_ACK()       (TWSR & 0XF8)                                          //察看状态
#define  SET_ACK()        (TWCR |= (1<<TWEA))                                    //ACK使能
#define  SET_NACK()       (TWCR &= ~(1<<TWEA))                                   //ACK禁止
#define  TWI_M_E()        (TWCR = (1<<TWINT) | (1<<TWEN))                        //主机启动一次接收
#define  TWI_S_E()        (TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN) | (1<<TWIE))//从机启动一次接收
#define  TWI_SEND(data)   {TWDR = data; TWI_M_E();}                              //主机模式发送一字节并启动一次接收
#define  STOP()           (TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN))           //停止信号
#define  MASTER()         (TWCR = (1<<TWEN))                                     //主机模式初始
#define  SLAVE()          (TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE))             //从机模式初始

#define  No1              0x01//一号机
#define  No2              0x02//二号机
#define  WRITE            0X00//写
#define  READ             0X01//读

uchar flag=0,//从机模式时收到一字节
      Data_R,//从机模式时收到的数据
  Data_T;//从机模式时将要发送的数据
/**********DELAY***************************************************************/
void delay_1us(void)                 //1us delay
  {
   asm("nop");
  }

void delay_nus(unsigned int n)       //N us delay
  {
   unsigned int i=0;
   for (i=0;i<n;i++)
   delay_1us();
  }

void delay_1ms(void)                 //1ms delay
  {
   unsigned int i;
   for (i=0;i<1140;i++);
  }

void delay_nms(unsigned int n)       //N ms delay
  {
   unsigned int i=0;
   for (i=0;i<n;i++)
   delay_1ms();
  }
////////////////////////////////////////////////////////////////////////////////
void Port_Init()
{
     DDRA = 0XFF;
//DDRC = 0X00; //输入
//PORTC = 0X03;//片内上拉
}

void Twi_Init()
{
     TWAR = (No1<<1) | (BIT(0));//主机地址,广播开
//TWAR = (No2<<1) | (BIT(0));  //从机地址,广播开
TWBR = 0X20;
SLAVE();                     //开始时进入从机模式,要发送数据时再变成主机
TWSR = 0X00;
}

void Error()
{
     //DDRA = 0XFF;

PORTA = TEST_ACK();
STOP();
//main();
while(1);
}

void MT(uchar add, uchar dat)              //主机发送一字节
{
add = (add<<1) | (WRITE);
START_SIGNAL();                       //发送开始信号
WAIT_TWINT();
if(TEST_ACK() != START)Error();
TWI_SEND(add);                        //发送地址
WAIT_TWINT();
if(TEST_ACK() != MT_SLA_ACK)Error();
TWI_SEND(dat);                        //发送数据
WAIT_TWINT();
if(TEST_ACK() != MT_DATA_ACK)Error();
STOP();                               //发送停止信号
delay_nms(1);
SLAVE();                              //变回从机
}

uchar MR(uchar add)                        //主机接收一字节
{
uchar temp;
add = (add<<1) | (READ);
START_SIGNAL();                       //发送开始信号
WAIT_TWINT();
if(TEST_ACK() != START)Error();
TWI_SEND(add);                        //发送地址
WAIT_TWINT();
if(TEST_ACK() != MR_SLA_ACK)Error();
TWI_M_E();                            //接收数据
WAIT_TWINT();
if(TEST_ACK() != MR_DATA_NACK)Error();
temp = TWDR;
STOP();                               //发送停止信号
delay_nms(1);
SLAVE();                              //变回从机
return temp;
}

#pragma interrupt_handler S:18             //从机接收或发送一字节
void S()
{
switch(TEST_ACK())
{//SLAVE RECEIVE MODE
      case SR_SLA_ACK:      //从机接收地址响应
  TWI_S_E();
  break;
  case SR_SLA_FAIL:     //作为主机仲裁失败,自己的ALT+W被接收
  TWI_S_E();
  break;
  case SR_GCA_ACK:      //从机接收广播响应
  TWI_S_E();
  break;
  case SR_GCA_FAIL:     //作为主机仲裁失败,接收到广播地址
  TWI_S_E();
  break;
  case SR_DATA_ACK:     //从机接收数据响应
  Data_R = TWDR;
  TWI_S_E();
  flag = 1;
  break;
  case SR_DATA_NACK:    //从机接收数据非应答
  Data_R = TWDR;
  TWI_S_E();
  flag = 1;
  break;
  case SR_GCA_DATA_ACK: //从机接收广播数据应答
  Data_R = TWDR;
  TWI_S_E();
  flag = 1;
  break;
  case SR_GCA_DATA_NACK://从机接收广播数据非应答  
  Data_R = TWDR;
  TWI_S_E();
  flag = 1;
  break;
  case SR_STOP_RESTART: //从机工作时收到STOP或RESTART
  TWI_S_E();
  break;
      //SLAVE SEND MODE
      case ST_SLA_ACK:      //从机发送地址应答
  TWDR = Data_T;
  TWI_S_E();
  break;
  case ST_SLA_FAIL:     //作为主机仲裁失败,自己的ALT+R被接收
  TWDR = Data_T;
  TWI_S_E();
  break;
  case ST_DATA_ACK:     //从机发送数据应答
  TWDR = Data_T;
  TWI_S_E();
  break;
  case ST_DATA_NACK:    //从机发送数据非应答
  TWI_S_E();
  break;
  case ST_BYTE_ACK:     //数据已发送,接收到ACK
  TWI_S_E();
  break;
      //ELSE
      case NA:              //没有相关状态信息

  break;
  case ILLEGAL:         //由于非法的START或STOP引起的总线错误
  TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
  break;
  default:
  TWI_S_E();
  break;
}
}
/////////////No1///////////////////////
void main()
{
Port_Init();
Twi_Init();
SEI();
delay_nms(100);
CLI();
MT(No2,0X44);
SEI();
delay_nms(100);
CLI();
PORTA = MR(No2);
while(1);
}

/////////////No2////////////////////////
/*void main()
{
     Port_Init();
Twi_Init();
SEI();

while(flag != 1);
Data_T = Data_R;
while(1);
}*/

使用特权

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

本版积分规则

1

主题

1

帖子

0

粉丝