三个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的发送接受 |
|