打印
[AVR单片机]

请教高人指点 mega16的MAX485通信

[复制链接]
4472|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lhwaizhu|  楼主 | 2012-3-13 20:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
三个m16通过MAX485通信 1个主机 两个从机 现在情况是两个从机可以正常收到主机的数据,但是主机不能正常接受从机1的返回数据,从机2不返回数据,我在protues仿真中发现,主机接收完从机1的数据后,还会每隔1ms进入接受中断,这里很不理解,我只发送了一次数据,主机怎么会不停地进入中断啊?请高人指教 憋了好几个晚上了 感激不尽 下面程序:

主机:

/*******************************************************************************
                  485多机通讯
--------------------------------------------------------------------------------
通讯规则:
1:时钟 4 MHz/波特率9600/9个数据位/无校验/1个停止位/硬件多机通讯功能/
2:通讯连接采用硬件MAX485,双向单工
3:每个上行/下行的数据包的字节个数都是一样的(通讯数据量)
5:数据接收采用中断+查询的方式
6:总是由主机向从机发送一个数据包,从机收到数据包后向主机回复一个数据包
8:从机之间不能相互通讯,必须通过主机才能交换数据
9:无效地址是0,主机地址是1,从机地址是2.3.4......广播地址是255
********************************************************************************/

#include <mega16.h>
#include <delay.h>

#define BAUD   9600         //波特率采用9600bps
#define CRYSTAL 4000000         //系统时钟4MHz
//计算和定义波特率设置参数
#define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)
#define BAUD_H (unsigned char)(BAUD_SETTING>>8)
#define BAUD_L (unsigned char)(BAUD_SETTING)

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<PE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define amount 10 //设定通讯数量

unsigned char send[amount];   //发件箱
unsigned char inbox[amount]; //收件箱
unsigned char n=0; //**中断次数
unsigned char flag_me=0; //个人数据标志
unsigned char flag_all; //广播地址标志 所有从机均接受
unsigned char data_ok=0;

//波特率9600/9个数据位/1个停止位/无校验/收发开启/接收中断
void Usart_Init(void)
{
    UCSRA=0x01;//多机模式(主机还是0x00)
    UCSRB=0x9c;
    UCSRC=0x86;
    UBRRH=BAUD_H;
    UBRRL=BAUD_L;           
    PORTD&=~(1<<2); //PD2接max485控制发送接收 默认接收状态
    DDRD|=(1<<2);
}
//从数组datas[]的首地址开始发送amount个数据,其中第0个数据是地址帧,其他是数据帧
void Usart_Out(unsigned char *datas,unsigned char m)
{
    unsigned char i=0;
    PORTD|=(1<<2); //MAX485发送状态
    delay_ms(2);
    while(i<m) //一共发送amount个数据
    {
          if(i==0)
            UCSRB|=0x01;//i=0 第一个数据为地址
          else
            UCSRB&=0xfe; //其他发送的为数据
          UDR=*(datas+i);//装载数据发送
          while(!(UCSRA&DATA_REGISTER_EMPTY)); //等待
          UCSRA|=0x40;//清除发送标志
          i++;
          delay_ms(2);           
    }
    PORTD&=~(1<<2); //max485置于接受状态     

}
interrupt [USART_RXC] void usart_rx_isr(void)
{
      unsigned char status;
      while(!(UCSRA&(1<<RXC)));   //有数据
      status=UCSRA;
      if((status&(FRAMING_ERROR|PARITY_ERROR|DATA_OVERRUN))==0)
      {
          inbox[n]=UDR;
          n++;               
      }


    if(n==10)
    {
          n=0;
          PORTA=inbox[9]; //证明数据无措     
    }


}


void main(void)
{
// Declare your local variables here
unsigned char Data_Slave1[10]={0x02,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08};
unsigned char Data_Slave2[10]={0x03,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09};
PORTA=0xFF;
DDRA=0xFF;
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;
DDRC=0x00;
PORTD=0x03;
DDRD=0x02; //RXD输入 上拉有效

Usart_Init();

UCSRA=0x00;//主机不要设为0x01

#asm("sei");
Usart_Out(Data_Slave1,10);
delay_ms(2000);
Usart_Out(Data_Slave2,10);
delay_ms(2000);
while (1)
    {

    };
}




从机1:




#include <mega16.h>
#include <delay.h>

flash unsigned char led_7[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

#define BAUD   9600         //波特率采用9600bps
#define CRYSTAL 4000000         //系统时钟4MHz
//计算和定义波特率设置参数
#define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)
#define BAUD_H (unsigned char)(BAUD_SETTING>>8)
#define BAUD_L (unsigned char)(BAUD_SETTING)

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<PE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)

#define amount 10 //设定通讯数量
#define addr 2 //这是第一个从机
unsigned char send[amount];   //发件箱
unsigned char inbox[amount]; //收件箱
unsigned char n=0; //**中断次数
unsigned char flag_me=0; //个人数据标志
unsigned char flag_all; //广播地址标志 所有从机均接受
unsigned char data_ok=0; //接收一组数据完成

//波特率9600/9个数据位/1个停止位/无校验/收发开启/接收中断
void Usart_Init(void)
{
    UCSRA=0x01;//多机模式(主机还是0x00)
    UCSRB=0x9c;
    UCSRC=0x86;
    UBRRH=BAUD_H;
    UBRRL=BAUD_L;           
    PORTD&=~(1<<2); //PD2接max485控制发送接收 默认接收状态
    DDRD|=(1<<2);
}

void Usart_Out(unsigned char *datas,unsigned char m)
{
    unsigned char i=0;
    PORTD|=(1<<2); //MAX485发送状态
    delay_ms(2);
    while(i<m) //一共发送amount个数据
    {     


          if(i==0)
            UCSRB|=0x01;//i=0 第一个数据位地址
          else
            UCSRB&=0xfe; //其他发送的为数据


          UDR=*(datas+i);//装载数据发送
          while(!(UCSRA&DATA_REGISTER_EMPTY)); //等待
          UCSRA|=0x40;//清除发送标志
          i++;
          delay_ms(2);           
    }
    PORTD&=~(1<<2); //max485置于接受状态     

}
interrupt [USART_RXC] void usart_rx_isr(void)
{
      unsigned char status;
      while(!(UCSRA&(1<<RXC)));   //有数据
      status=UCSRA;
      if((status&(FRAMING_ERROR|PARITY_ERROR|DATA_OVERRUN))==0)
      {
          inbox[n]=UDR;
          n++;               
      }
    //如果地址匹配本机或者是广播地址就关闭地址筛选(多机通讯)功能
    //(关闭是为了保证后面的数据全部接收到)
      if((inbox[0]==addr)||(inbox[0]==0xff))
          UCSRA&=~0x01;
      else
          n=0;


      if(n==10)
      {
          n=0;
          UCSRA|=0x01; //数据接收完后 重新打开接收器地址筛选功能
          PORTA=inbox[9]; //证明数据无措
          data_ok=1;


      }   


}


void main(void)
{
// Declare your local variables here
unsigned char Data_Main[]={0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02};
PORTA=0x00;
DDRA=0xFF;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0x03;
DDRD=0x02; //RXD输入 上拉有效

Usart_Init();
#asm("sei");
while (1)
    {
    // Place your code here


        if(data_ok)
      {
            data_ok=0;
            Usart_Out(Data_Main,10);


      }   


    };
}
从机2的程序和从机1基本一样 就是地址不同,protues中用的MAX487正常接线,PD2控制487的发送接受

相关帖子

沙发
lhwaizhu|  楼主 | 2012-3-14 16:37 | 只看该作者
跪谢了....

使用特权

评论回复
板凳
dong_abc| | 2012-3-14 17:20 | 只看该作者
我只能说protues不一定靠谱!

使用特权

评论回复
地板
airwill| | 2012-3-16 15:29 | 只看该作者
论坛里已经有很多人说到 protues 仿真软件的缺陷了. 不要太迷信 仿真软件. 特别是这类带协议的复杂通信系统.

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
dong_abc + 1
5
wpz0768| | 2013-1-11 17:10 | 只看该作者
PORTD=0x03;
DDRD=0x02; //RXD输入 上拉有效

端口初始化有问题,没有初始化Pd2

使用特权

评论回复
6
joyme| | 2013-1-12 10:48 | 只看该作者
硬件不做好,不调程序,从来不用仿真软件,呵呵

使用特权

评论回复
7
wkatt1002| | 2013-5-27 15:17 | 只看该作者
mark

使用特权

评论回复
8
huangxz| | 2013-5-28 10:57 | 只看该作者
看起来像是仿真软件的问题,楼主可以用avrstudio仿真试一下。

使用特权

评论回复
9
张瑜明| | 2016-11-16 10:40 | 只看该作者
请问楼主这个问题解决了吗?

使用特权

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

本版积分规则

24

主题

79

帖子

2

粉丝