找回密码
 立即注册

QQ登录

只需一步,快速开始

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

PC机与多个51单片机串口通讯

[复制链接]
跳转到指定楼层
楼主
ID:51090 发表于 2014-10-13 15:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近需要用PC机与多个51单片机通过RS232进行通讯。
在多机通讯中,要保证主机与所选择的从机实现可靠的通信,
必须保证串口具有识别的功能。在串行口控制寄存器SCON中
有一位叫做SM2,就是为了多机通讯而设置的控制位。多机通
讯的过程可以如下:1 首先从机初始化,开中断,让其以方式
2或3接收(9位异步通讯方式),置位SM2,REN位,允许接
收,那么当SM2=1的时候,只有当接收到的第9位数据(RB8)
等于1(接收到的为地址帧)的时候,前8位数据送入接收SBUF
,置位RI,产生中断。如果接收到的第9位数据位0,则将接收
到的数据帧丢弃。2 此时主机可以先将从机地址发送给各个从机
系统,各个从机的串口接收到第9位数据RB8为1,由于SM2=1
,置位RI,各个从机相应中断,在中断服务程序中判断主机送来的
地址是否与本机地址相符合(这个地址是由软件编写人员自行设
定的),若相符,则清零SM2,准备接收数据。若不符,则保持
SM2=1. 3 第三步主机开始发送数据帧,此时前面地址相符合的
从机,SM2=0,主机发送的数据RB8=0,这样只有SM2=0的
相符的从机可以产生接收数据中断,激活中断标志位RI,进入中
断服务程序,去接收数据。其他的从机因SM2=1,又RB8=0,
不能激活中断标志RI,不能进入中断,则把接收到的数据丢失不
做处理。从而保证了这个数据通信的正确性。
  上面这个过程就是51单片机通过串行口进行多机通讯的完整过程。
  但是现在我需要PC机与多个51单片机进行通讯,而PC机上面是
无法实现这个RB8的设置,因为我是用串口调试助手来调试程序。
那么我
  所幸不用上面的多机通信的方法。而是自己来规定一个一个信息头
,一个信息尾。比如F0,A5,然后跟着地址信息。之所以加这么一个
信息头,是为了防止数据与地址的值相同,造成从机误接收。这个
信息头设置的越复杂一些,避免误接收的效果就越好,这是很简单
的道理。
  这样只有从机接收到这个代表地址信息的信息头,而且后面跟着的
地址与自己的地址相符合,才跳转到接受数据的程序段。而其他从机
则是不断的在接收这些数据,无论是地址,还是数据,但是全部丢弃
他们。这样就从软件上解决了这个PC机与多个51单片机多机通讯调
试程序时的一个缺陷。当然可以考虑自己通过VC编写一个小的上位机
软件,来处理这个事情,不知道微软的API是否也有这个RB8的机制,
自己才疏学浅,并不知晓。
  下面将自己编写的简单程序段放在这里,方便日后参考:
view plaincopy to clipboardprint?
#include <reg52.h>   
  
#define uchar unsigned char   
#define uint  unsigned int   
#define __MAX_LEN_ 64     
  
sbit FMQ=P3^7;   
  
uchar addr,s=0,i=0,tmp=0xff;   
uchar buf[__MAX_LEN_];   
  
void init_serial()   
{   
     TMOD = 0x20;   
     TH1 = 250;     
     TL1 = 250;   
     TR1 = 1;      
     PCON = 0x80;      
     SCON = 0xd0;   
}   
   
void delay(uint k)   
{   
     uint i,j;   
     for(i=0;i<k;i++)   
          for(j=0;j<110;j++);   
}   
  
void Beep_ok()   
{   
    FMQ=0;   
    delay(200);   
    FMQ=1;   
    delay(200);   
   
    FMQ=0;   
    delay(200);   
    FMQ=1;   
    delay(200);   
}   
  
void Beep_Addr_OK()   
{   
    FMQ=0;   
    delay(1000);   
    FMQ=1;   
}   
  
uchar rec_uart(uchar *buf)   
{   
    uchar DATA;   
    RI = 0;   
    while(!RI);   
    DATA=SBUF;   
    P2 = 0xff;   
    addr = P2;   
    if(DATA==addr)   
       return 0xfe;   
   
    buf[s] = SBUF;   
    s++;   
    if(s==__MAX_LEN_)   
   {   
       s=0;   
    }   
   
    P0=SBUF;   
    Beep_ok();   
    return 0xff;   
}   
  
  
void main()   
{   
    init_serial();     
    EA = 0;      
    while(1)   
   {   
   
loop:  P2 = 0xff;   
          addr = P2;   
          SM2 = 0;     
          tmp = addr-1;   
  
          while(tmp != addr)   
         {   
              RI = 0;   
              while(!RI);   
              tmp = SBUF;   
              P1=tmp;   
              RI = 0;   
          }   
         Beep_Addr_OK();   
  
        TI = 0;   
        TB8 = 0;      
        SBUF = addr;   
        while(!TI);   
        TI = 0;   
       SM2 = 0;      
       tmp = 0xff;   
       while(1)   
       {   
           while(tmp == 0xff)      
          {   
                tmp = rec_uart(buf);      
           }     
  
           if(tmp == 0xfe)      
          {   
                Beep_Addr_OK();   
               goto loop;   
           }   
        }   
  
    }   
}  
#include <reg52.h>
#define uchar unsigned char
#define uint  unsigned int
#define __MAX_LEN_ 64  
sbit FMQ=P3^7;
uchar addr,s=0,i=0,tmp=0xff;
uchar buf[__MAX_LEN_];
void init_serial()
{
     TMOD = 0x20;
     TH1 = 250;  
     TL1 = 250;
     TR1 = 1;   
     PCON = 0x80;   
     SCON = 0xd0;
}

void delay(uint k)
{
     uint i,j;
     for(i=0;i<k;i++)
          for(j=0;j<110;j++);
}
void Beep_ok()
{
    FMQ=0;
    delay(200);
    FMQ=1;
    delay(200);

    FMQ=0;
    delay(200);
    FMQ=1;
    delay(200);
}
void Beep_Addr_OK()
{
    FMQ=0;
    delay(1000);
    FMQ=1;
}
uchar rec_uart(uchar *buf)
{
    uchar DATA;
    RI = 0;
    while(!RI);
    DATA=SBUF;
    P2 = 0xff;
    addr = P2;
    if(DATA==addr)
       return 0xfe;

    buf[s] = SBUF;
    s++;
    if(s==__MAX_LEN_)
   {
       s=0;
    }

    P0=SBUF;
    Beep_ok();
    return 0xff;
}

void main()
{
    init_serial();  
    EA = 0;   
    while(1)
   {

loop:  P2 = 0xff;
          addr = P2;
          SM2 = 0;  
          tmp = addr-1;
          while(tmp != addr)
         {
              RI = 0;
              while(!RI);
              tmp = SBUF;
              P1=tmp;
              RI = 0;
          }
         Beep_Addr_OK();
        TI = 0;
        TB8 = 0;   
        SBUF = addr;
        while(!TI);
        TI = 0;
       SM2 = 0;   
       tmp = 0xff;
       while(1)
       {
           while(tmp == 0xff)   
          {
                tmp = rec_uart(buf);   
           }  
           if(tmp == 0xfe)   
          {
                Beep_Addr_OK();
               goto loop;
           }
        }
    }
}

程序中,并没有使用这个信息头,当然很容易就可以加上,这个只是个
简单的测试,蜂鸣器的响声,也是调试程序中使用,另外程序中使用了
goto,破坏了程序的结构,以后具体应用中再具体编写合适的程序。

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

使用道具 举报

沙发
ID:195884 发表于 2017-6-18 13:48 | 只看该作者
这是一个好贴
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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