找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2760|回复: 1
打印 上一主题 下一主题
收起左侧

请教51单片机多机通信问题

[复制链接]
跳转到指定楼层
楼主
ID:161562 发表于 2017-1-13 18:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人初学单片机,想知道51单片机多机通信,需要遵守哪些协议,是主机发送一次数据,从机应答,返回一次。以此循环?以下是我参考书上写的程序;但测试时主机能发送完地址,从机响应后,返回来,主机便无反应。
请大神帮忙知道下。

/*************主机*******************/

#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

#define SLAVE 0x02 //定义从机的地址
#define BN 16          
uchar rbuf[16];
uchar code tbuf[16] = {"1234567891234567"};//传输

void err()//复位信号
{
        SBUF = 0xff;
        while(TI != 1)
        TI=0;
}

uchar master(uchar addr,uchar command
{
        uchar aa,i,p;
        while(1)
        {
                SBUF = SLAVE ; //主机发送从机地址         (主机发送地址后,从机开始检验,并返回给主机自己的地址再次确认)
                while(!TI);
                TI=0;
                while(!RI)         
                RI =0;
/**/        P1 = 0xfe;//            主机收到从机的回信         /*********/
                if(SBUF != addr
                {
                        err();           //主机发送复位信号
                }
                else
                {
                //主机收到从机应答地址后,确认地址是否相符,不符合,则发复位信号(TB8=1);符合则TB8=0,主机开始发送数据
                        TB8=0; //清地址标志
                        SBUF = command
                        while(!TI);
                        TI=0;
        /**/        P1 = 0xfd; // 主机发送命令判断        /***过不来***/
                        while(!RI);          //主机等待接收
                        RI =0;
                        aa = SBUF;
                        if(aa & 0x80 == 0x80) // 若命令未被接收,发复位信号(TB8 = 1)
                        {
                                TB8 =1;
                                err();
                        }
                        else
                        {
                        //        if(command == 0x01) //主机命令从机接收命令
                                {
                                        if((aa & 0x01)== 0x01)
                                        {
                                /**/        P1 = 0xfc;    //从机返回命令
                                                do
                                                {
                                                        p=0;  //清校验和
                                                        for(i=0;i<BN;i++)
                                                        {
                                                                SBUF=tbuf[i]
                                                                p += tbuf[i] ;//计算校验和
                                                                while(!TI);
                                                            TI=0;
                                                        }
                                                        SBUF = p ; //发送校验和        判断是否完全接收
                                                        while(!TI);
                                                        TI=0;
                                                        while(!RI)         
                                                        RI =0;
                                                }while(SBUF != 0);          //接收不正确则重新发送
                        /**/                P1 = 0xf7; //         从机接收完成
                                                TB8 = 1;   //发地址帧(置地址标志)
                                                return(0);         //结束函数
                                        }
                                        else
                                        {
                                                if((aa&0x02) == 0x02) //主机接受命令,从机准备好发送
                                                {
                                                        while(1)
                                                        {
                                                                p=0;  //清校验和
                                                                for(i=0;i<BN;i++)
                                                                {
                                                                        while(!RI)         
                                                                    RI =0;
                                                                        rbuf[i]=SBUF
                                                                        p += rbuf[i] ;//计算校验和
                                                                }
                                                                while(!RI)
                                                                RI =0;
                                                                if(SBUF == p)  //发送校验和        判断是否完全接收
                                                                {
                                                                        SBUF =0X00;  //校验和相同 发00
                                                                        P1 = 0xfc;
                                                                        while(!TI);
                                                                        TI=0;
                                                                        break;
                                                                }
                                                                else
                                                                {
                                                                        SBUF = 0xff; //校验和不同发0FF 重新接收
                                                                        while(!TI);
                                                                        TI=0;
                                                                }
                                                        }
                                                        TB8 = 1;   //发地址帧(置地址标志)
                                                    return(0);           //结束函数
                                                }
                                        }
                                }
                        }
                               
                }

        }
}
void main()
{
        TMOD = 0x20;  //定时器 T1 方式2
        TL1 = 0xfd;           //9600
        TH1 = 0xfd;
        PCON = 0x00;   //电源寄存器 波特率正常
        TR1 = 1;  //打开定时器
        SCON =0xf8;           //TB8=1;串口工作方式3         SM2=1
        while(1)
        {
          master(SLAVE,0x01);                //01   从机接收数据
          master(SLAVE,0x02);
        }       
}

/**************从机*****************/
#include <reg52.h>       
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

#define SLAVE 0x02 //定义从机的地址
#define BN 16            //一次传输
uchar rbuf[16]; //接收数组变量
uchar tbuf[6]= {"i konw"}; //接收数组变量
bit tready = 0;                   //从机发送准备位 1为准备好
bit rready = 0;                  //从机接收准备位 1为准备好
void str();        //发送数据函数
void sre();          //接收数据函数
bit TR_flag = 0;
bit RE_flag = 0;

void main()
{
        TMOD =0x20;
        TL1 =0xfd;
        TH1 =0xfd;
        PCON = 0x00;
        TR1 =1;
        SCON = 0xf0 ;          //串口3 SM2 = 1;
        ES = 1;
        EA = 1;
        while(1)
        {
                tready= 1;
                rready = 1; //假定准备好接收和发送
                if(RE_flag == 1)
                {
                        P1 = 0x55;           //1 3 5 7
                }
                if(TR_flag == 1)
                {
                        P1 = 0xaa;         // 2 4 6 8
                }
        }
}
/*从机以中断方式控制和主机的通信*/
void ser() interrupt 4
{
        uchar a ;
        P1 = 0xfe;//*//           ///从机收到主机指令
        RI=0;
        ES=0;
        if(SBUF != SLAVE)
        {
                ES = 1;
                goto reti;
        }
        SM2 = 0
        SBUF = SLAVE; //再次向主机发送本地址
        while(!TI);
        TI=0;
        P1 = 0xfd; //从机确认
        while(!RI);         
        RI=0;
        if(RB8 == 1)
        {
                SM2 = 1;
                ES=1;
                goto reti;
        }         // /*复位信号,回复监听*/
        a = SBUF;  //接收主机的命令 command
        if(a == 0x01
        {
                P1        = 0xfc;        //判断是否收到主机命令
                if(rready == 1)
                        SBUF =0x01;
                else
                        SBUF = 0x00;
                while(!TI);
                TI = 0;
                while(!RI);                 //
                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);
                        TI = 0;
                /*        while(!RI);          
                        RI=0;        */
                        if(RB8 == 1)           //随时准备接收新的地址
                        {
                                SM2 = 1;
                                ES = 1;
                                goto reti;
                    }         // */          //lingshan  kejiashang jianyan
                        str(); //发送数据
             }
                 else
                 {
                         SBUF = 0x80        ; /*命令非法*/
                           while(!TI);
                        TI = 0;
                        SM2 = 1;   //恢复监听
                        ES = 1;   
                 }
         }
                       
}
void str() //发送数据
{
        uchar p, i;
        tready =0;
        do
        {
                p=0;
                for(i=0;i<BN;i++)
                {
                        SBUF=tbuf[i]
                        p += tbuf[i] ;//计算校验和
                        while(!TI);
                        TI=0;
                /*        while(!RI);
                        RI=0;*/
                }
                SBUF = p ; //发送校验和        判断是否完全接收
                while(!TI);
                TI=0;
                while(!RI)         
                RI =0;
        }while(SBUF != 0);
        TR_flag = 1;//发送完成
         SM2 = 1;
         ES = 1;
}
void sre()         //接收数据
{
        uchar p , i ;
        rready =0;   //////*////
        while(1)
        {
                p=0;  //清校验和
                for(i=0;i<BN;i++)
                {
                        while(!RI)          //主机等待接收
                    RI =0;
                        rbuf[i]=SBUF
                        p += rbuf[i] ;//计算校验和
                }
                while(!RI)          //从机等待接收主机的 返回值 jiaoyanhe
                RI =0;
                if(SBUF == p)  //发送校验和        判断是否完全接收
                {
                        SBUF =0X00;  //校验和相同 发00
                        RE_flag = 1;
                        break;
                }
                else
                {
                        SBUF = 0xff; //校验和不同发0FF 重新接收
                        while(!TI);
                        TI=0;
                }
        }

        SM2 = 1;
        ES = 1;
}                 







分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:829862 发表于 2022-2-7 15:03 | 只看该作者
:'(:loveliness::lol
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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