单片机之间的多机通信

2020-01-27 11:24发布

本帖最后由 qq511153186 于 2013-8-20 09:12 编辑

哪位大侠能提供一下简单的电路吗?谢谢了!!
当主机发送0xff命令时会有操作?
我的仿真效果是将 tbuf[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};数据给从机,从机再输出给流水灯,
现在出了点问题,流水灯是全亮的

主机代码:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define address 0x02           //从机的地址
uchar rbuf[8];
uchar code tbuf[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

void UART_init()
{
        TMOD = 0x20;    //计时计数器1工作方式2      
        TH1 = 0xfd;          //串口的波特率为9600b/s      
        TL1 = 0xfd;               
        TR1 = 1;                  //开定时计数器
        SCON = 0xf8;    //1101 1000    工作方式3   
}
void err(void)
{
        SBUF=0xff;                        //复位信号,命令各从机复位
        while(TI!=1);            //发送过程中TI一直保持低电平,发完一帧后,硬件置1
        TI=0;
}

uchar master(uchar addr,uchar command)
{
        uchar aa,i,p;
        while(1)
        {
                SBUF=addr;      //发呼叫地址
                while(TI!=1);
                TI=0;
                while(RI!=1);           //从机比较地址后,等待从机把本机的地址发回主机
                RI=0;
                if(SBUF!=addr)
                        err();
                else
                {
                        TB8=0;          //清地址标志
                        SBUF=command;            //发命令
                        while(TI!=1);
                        TI=0;
                        while(RI!=1);          //从机应答
                        RI=0;
                        aa=SBUF ;                  //接收状态
                        if(aa&0x08==0x08)    //若命令未被接收,发复位信号
                        {
                                TB8=1;            
                                err();
                        }
                        else
                        {
                                if(command==0x01)          //主机发送数据命令
                                {
                                        if((aa&0x01)==0x01)      //从机准备好接收数据
                                        {
                                                do
                                                {
                                                        p=0;                          //清检验和
                                                        for(i=0;i<8;i++)
                                                        {
                                                                SBUF=tbuf;
                                                                p+=tbuf;
                                                                while(TI!=1);
                                                                TI=0;
                                                        }
                                                        SBUF=p;
                                                        while(TI!=1);
                                                        TI=0;
                                                        while(RI!=1);
                                                        RI=0;
                                                }
                                                while(SBUF!=0);                  //校验和正确,回送正确信号00H
                                                TB8=1;
                                                return(0);                       
                                        }
                                }
                                //if(command==0x02)        
                                //{
                                else
                                {
                                        if((aa&0x02)==0x02)                //接收命令,从机准备好发送                  
                                        {
                                                while(1)
                                                {
                                                        p=0;              //清校验和
                                                        for(i=0;i<8;i++)                        
                                                        {
                                                                while(RI!=1);           //等待接收完成
                                                                TI=0;
                                                            rbuf=SBUF;
                                                                p+=rbuf;
                                                        }
                                                        while(RI!=1);
                                                        RI=0;
                                                        if(SBUF==p)
                                                        {
                                                                SBUF=0x00;    //校验和相同发00
                                                                while(TI!=1);
                                                                TI=0;
                                                                break;   
                                                        }
                                                        else
                                                        {
                                                                SBUF=0xff;   //校验和不同发ff重新接收
                                                                while(TI!=1);
                                                                TI=0;
                                                        }
                                                }
                                                TB8=1;
                                                return(0);
                                        }
                                }
                        }
                }
        }
}

void main()
{
        UART_init();
        master(address,0x01);
        master(address,0x02);
        while(1);
}

从机代码:

#include<reg52.h>
#define uchar unsigned char
#define address 0x02
uchar tbuf[8];
uchar rbuf[8];
bit tready;
bit rready;
void str(void);
void sre(void);
void delay_ms(int t);
main(void)
{
        uchar i;
        TMOD=0x20;                 //T1方式2
        TL1=0xfd;
        TH1=0xfd;
        //PCON=0x00;
        TR1=1;
        SCON=0xf0;                   //串口为方式3
        ES=1;                           //开串行中断
        EA=1;         
        P1=0xff;       
        while(1)
        {
                tready=1;
                rready=1;
                for(i=0;i<8;i++)
                {
                        P1=rbuf;
                        delay_ms(500);

                }

        }                                          
}

void delay_ms(int t)
{
uchar i;
  while(t--)
    for(i=0; i<120; i++);
       
}

void ssio(void) interrupt 4
{
        uchar a ;
        RI=0;                 //清接收中断标志位
        ES=0;                //关串行中断
        if(SBUF!=address)    //接收到的不自己的地址,直接跳到程序最后
        {
                ES=1;
                goto reti;
        }
        SM2=0;                  //与自己的地址相符,取消监听状态   
        SBUF=address;          //回传地址给主机
        while(TI!=1);
        TI=0;
        while(RI!=1);           //等待主机回
        RI=0;
        if(RB8==1)              //此为地址不符时的情况,主机发来的复位信号
        {
                SM2=1;
                ES=1;
                goto reti;
        }
        a=SBUF;                        //开始检测主机发来的命令
        if(a==0x01)  //主机命令从机接收数据
        {
                if(rready==1)           //接收准备标志
                SBUF=0x01;                 //从机应答,回发命令
                else
                SBUF=0x00;
                while(TI!=1);
                TI=0;
                while(RI!=0);           //等待主机发送数据
                RI=0;
                if(RB8==1)                  //数据出错
                {
                        SM2=1;
                        ES=1;
                        goto reti;

                }
                sre();                  //接收数据
        }
        else
        {
                if(a==0x02)                   //主机命令从机发送数据命令
                {
                        if(tready==1)
                                SBUF=0x02;           //回送命令检验
                        else
                        SBUF=0x00;
                        while(TI!=1);
                        TI=0;
                        while(RI!=0);
                        RI=0;
                        if(RB8==1)                    //数据出错
                        {
                                SM2=1;
                                ES=1;
                                goto reti;

                        }
                        str();                   //发送数据
                }
                else                            //非法命令
                {
                        SBUF=0x80;           //命令非法,发状态  
                        while(TI!=1);
                        TI=0;
                        SM2=1;
                        ES=1;                   //恢复监听
                }
        }
        reti:;
}

void str(void)                          //发数据
{
        uchar p,i;
        tready=0;
        do
        {
                p=0;
                for(i=0;i<8;i++)
                {               
                        SBUF=tbuf;
                        p+=tbuf;
                        while(TI!=1);
                        TI=0;
                }
                SBUF=p;                        //发送校验和
                while(TI!=1);
                TI=0;                       
                while(RI!=0);
                RI=0;               
        }                
        while(SBUF!=0);          //校验和正确,主机会发磅正确信号00H
        SM2=1;
        ES=1;                         //恢复监听

}

void sre(void)                          //接收数据
{
        uchar p,i;
        rready=0;
        while(1)
        {
                p=0;                        //清校验和
                for(i=0;i<8;i++)  
                {
                        while(RI!=1);         //等待接收数据完成
                        RI=0;
                        rbuf=SBUF;         //存接收到的数据
                        p+=rbuf;
                       
                }
                while(RI!=1);       //接收主机发来的校验和p
                RI=0;
                if(SBUF==p)                    //校验和正确
                {
                        SBUF=0x00;                //校验和正确回送正确信号00H
                        break;                        //跳了while(1)
                }
                else
                {
                        SBUF=0xff;                //校验和错误,回送0ffH,         重新接收
                        while(TI==0);
                        TI=0;
                }
        }
        SM2=1;                 //回到监听状态
        ES=1;                 //开串行中断
}       
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
22条回答
颖风
1楼-- · 2020-01-27 16:08
你应该说说你是用怎么通信的,比如主机发送。分机一直等待接收。
qq511153186
2楼-- · 2020-01-27 16:55
 精彩回答 2  元偷偷看……
颖风
3楼-- · 2020-01-27 20:27
SCON你根据寄存器的说明来设置就没得问题。多机通信,应该需要电平隔离吧。你可以用485来做!
qq511153186
4楼-- · 2020-01-28 00:02
颖风 发表于 2013-8-19 11:09
SCON你根据寄存器的说明来设置就没得问题。多机通信,应该需要电平隔离吧。你可以用485来做! ...

我不和PC机通信的话应该不用电平转换吧?现在做的就是简单的一个主单片机一个从单片机
颖风
5楼-- · 2020-01-28 02:43
你不是说一个和多个通信吗?一对一 通信,那不就是串口通信吗?
qq511153186
6楼-- · 2020-01-28 03:22
颖风 发表于 2013-8-19 13:38
你不是说一个和多个通信吗?一对一 通信,那不就是串口通信吗?

一对一跟一对多都是串口通信吧?不是通过它们的地址不同来的吗

一周热门 更多>