搜索
bottom↓
回复: 22

单片机之间的多机通信

[复制链接]

出0入0汤圆

发表于 2013-8-19 09:49:30 | 显示全部楼层 |阅读模式
本帖最后由 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;                 //开串行中断
}       

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2013-8-19 10:49:39 | 显示全部楼层
你应该说说你是用怎么通信的,比如主机发送。分机一直等待接收。

出0入0汤圆

 楼主| 发表于 2013-8-19 11:06:20 | 显示全部楼层
颖风 发表于 2013-8-19 10:49
你应该说说你是用怎么通信的,比如主机发送。分机一直等待接收。

大概的工作过程知道,我觉得主机的SCON是不是应该改成0xf0?还有硬件电路不知道怎么设计,查资料上说还要电平转换?

出0入0汤圆

发表于 2013-8-19 11:09:35 | 显示全部楼层
SCON你根据寄存器的说明来设置就没得问题。多机通信,应该需要电平隔离吧。你可以用485来做!

出0入0汤圆

 楼主| 发表于 2013-8-19 11:27:57 | 显示全部楼层
颖风 发表于 2013-8-19 11:09
SCON你根据寄存器的说明来设置就没得问题。多机通信,应该需要电平隔离吧。你可以用485来做! ...

我不和PC机通信的话应该不用电平转换吧?现在做的就是简单的一个主单片机一个从单片机

出0入0汤圆

发表于 2013-8-19 13:38:21 | 显示全部楼层
你不是说一个和多个通信吗?一对一 通信,那不就是串口通信吗?

出0入0汤圆

 楼主| 发表于 2013-8-19 14:48:04 | 显示全部楼层
颖风 发表于 2013-8-19 13:38
你不是说一个和多个通信吗?一对一 通信,那不就是串口通信吗?

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

出0入0汤圆

发表于 2013-8-19 18:59:03 | 显示全部楼层
51的多机通讯是用串口方式2或3进行的
不知楼主是怎么用的?

出0入0汤圆

 楼主| 发表于 2013-8-20 09:09:24 | 显示全部楼层
lxa0 发表于 2013-8-19 18:59
51的多机通讯是用串口方式2或3进行的
不知楼主是怎么用的?

用的是方式3,现在在我把代码贴上,能帮忙看下吗?

出0入0汤圆

 楼主| 发表于 2013-8-20 11:30:50 | 显示全部楼层
本帖最后由 qq511153186 于 2013-8-20 11:33 编辑

             while(TI!=1);
                TI=0;
                while(RI!=1);           //从机比较地址后,等待从机把本机的地址发回主机
                RI=0;
这里的这个while(RI!=1);   过不去,串口没用,从机的数据发不过来,求解释

出0入0汤圆

发表于 2013-8-20 15:10:51 来自手机 | 显示全部楼层
搞不明白是啥问题

出0入0汤圆

 楼主| 发表于 2013-8-20 15:18:47 | 显示全部楼层
benqme 发表于 2013-8-20 15:10
搞不明白是啥问题

用串口通信来实现单片机的多机通信,现在的问题是我仿真时,串口没用,传输不了数据不知道哪里出了问,求指点

出0入0汤圆

发表于 2013-8-21 00:00:40 | 显示全部楼层
检查一下你的多机通讯时的各个寄存器的设置对不对~~~~~~~~~~~~

出0入0汤圆

 楼主| 发表于 2013-8-21 09:04:01 | 显示全部楼层
lxa0 发表于 2013-8-21 00:00
检查一下你的多机通讯时的各个寄存器的设置对不对~~~~~~~~~~~~

我查看了一下寄存器的设置,貌视没有什么设置不对的地方,求提示

出0入0汤圆

发表于 2013-8-21 09:10:23 | 显示全部楼层
mcu 之间?

出0入0汤圆

 楼主| 发表于 2013-8-21 11:37:57 | 显示全部楼层
wkman 发表于 2013-8-21 09:10
mcu 之间?

是的,单片机之间,直接用了串口通信,能帮忙看看吗?

出0入0汤圆

发表于 2013-8-21 14:09:45 | 显示全部楼层
PC->mx232->mcu-master->max485->------------max485->mcu1
                                                    |-----------max485->mcu2                                                   
                                                    |----------- ..........................                                                
                                                    |-----------max485->mcu32

教科书经典电路方案啊。

出0入0汤圆

发表于 2013-8-21 14:17:29 | 显示全部楼层
用nRF24LE1吧,耗电又小,又集成8051指令,还可以无线通讯。

出0入0汤圆

发表于 2013-8-21 14:18:23 | 显示全部楼层
呵呵

出0入0汤圆

 楼主| 发表于 2013-8-21 17:54:52 来自手机 | 显示全部楼层
颜靖峰 发表于 2013-8-21 14:17 用nRF24LE1吧,耗电又小,又集成8051指令,还可以无线通讯。

到时可以试试,但现在得调这个…………

出0入0汤圆

 楼主| 发表于 2013-8-21 17:57:45 来自手机 | 显示全部楼层
wkman 发表于 2013-8-21 14:09 PC->mx232->mcu-master->max485->------------max485->mcu1 ...

我这里没用到电平转换 ,直接用得串口通信,方式3

出0入0汤圆

 楼主| 发表于 2013-8-28 18:38:25 来自手机 | 显示全部楼层
lxa0 发表于 2013-8-21 00:00 检查一下你的多机通讯时的各个寄存器的设置对不对~~~~~~~~~~~~

问题终于解决了,从机的scon设置出了点问题,谢谢你的提醒

出0入0汤圆

发表于 2013-8-28 19:25:47 | 显示全部楼层
qq511153186 发表于 2013-8-28 18:38
问题终于解决了,从机的scon设置出了点问题,谢谢你的提醒

不用客气~~~~~~~~~~~~
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 05:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表