单片机双机通信

单工通信

主机控制从机。

主机工作方式

/********************初始化串口
                     bps为波特率**********************************/
void uart_init(unsigned int bps)
{ 
  unsigned char t;
  SCON=0x50;//(0101)工作方式一:8位异步收发,波特率可变,允许接收数据
  PCON=0x00;//SMOD=0
  TI=0;//软件清零,表示未发送完成
  EA=1;//开总中断
  ES=1; //开串口中断
  TMOD=0x20;//8位自动装载模式
  switch(bps)
  { 
    case 1200:t=0xe8;break;
    case 2400:t=0xf4;break;
    case 4800:t=0xfa;break;
    case 9600:t=0xfd;break;
  }
  TH1=t;
  TL1=t;
  TR1=1;//开启T1
}

发送数据

/********************循环发送数据
                     ch为数据口**********************************/
void uart_send(unsigned char ch)
{
  ES=0; //关串口中断
  SBUF=ch;//发送s数组至sbuf,电脑串口助手接收
  while(TI==0);//等待发送完成
  TI=0;  //清除中断标记
  ES=1; //开串口中断
}

main中直接发送P0口的数据给SBUF,等待从机接收

void main()
{
  uart_init(9600);//初始化串口,并设置波特率为9600  
  while(1)
  { 
    uart_send(P0);       //循环发送P0口数据
  }
}

从机工作方式

1、设定工作方式
2、读取数据

void main()
{
   uart_init(9600);//初始化串口,并设置波特率为9600
   while(1)
  {
    if(RI==1)//接收中断标志位 RI=1,表示一帧数据接收完毕
    {
      P0=SBUF;
      RI=0;//接收中断标志位置零
    }
    while(RI==0);//等待接收完成
  }
}

或中断接收

void main()
{
   uart_init(9600);//初始化串口,并设置波特率为9600
   while(1)
  {
    while(RI==0);//等待接收完成
  }
}
void receive() interrupt 4
{
  if(RI==1) 
  {  RI=0;
     P0=SBUF;
  }
}

双机通信

单片机双机通信_第1张图片
单片机既是接收端也是发送端
1、设定工作方式
2、接收发送

void main(void)
{
    init();//设定工作方式
    while(1)
    {   
        SBUF=P1;//sbuf接收
        while(!TI)//发送中断标志位TI=1,表示一帧数据发送结束。
        {
           SBUF=P1;//sbuf接收数据
        }
        TI=0;

        temp=SBUF;//单片机取值
        while(!RI)
        {
           temp=SBUF;//单片机取sbuf数据
        }
        RI=0;
    }   
}

此时sbuf值已经接收到,在数码管上进行显示。字符格式需进行转换。

//字符格式转换函数
unsigned char transfer(unsigned char dat) 
{
    unsigned char endData=0;
    endData=dat%16;//16进制的转换
    return endData;
}

上代码

#include
#define u8 unsigned char
#define u16 unsigned int
void init(){ 
    PCON=0x80;
    SCON=0x90;  //1001,工作方式3
    ES=1;
    EA=1;
    TMOD=0x20;
}
void main(){
    init();
    while(1){ 
        SBUF=P1;
        while(TI==0){
            SBUF=P1;
        }
        TI=0;
        P0=SBUF;
        while(RI==0){
            P0=SBUF;
        }
        RI=0;
    }
}

多机通信

设定工作方式

void init()
{
  SCON=0xF0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收
  PCON=0;//SMOD=0
  TMOD=0x20;//TIMER1工作在MODE2
  TH1=0xF3;//波特率2400
  TR1=1;//启动TIMER1
  IE=0x90;//EA=1、ES=1,CPU、UART中断使能
}
KEY1=0xFF;//键盘口设为输入状态

if(keydata1 != KEY1)//判断指拨开关1有没有变化?
  {
       keydata1 = KEY1;//不同则读入指拨开关1

       TB8=1;//设TB8=1,准备发送地址
       ACK_flag=0;//清主机发送结束标志
       SBUF=0x01;//发出01H地址(89C51-B)
       while(!ACK_flag);//发送完毕否?,没有就等待

       TB8=0;//设TB8=0,准备发送数据
       ACK_flag=0;//清主机发送结束标志
       SBUF = keydata1;//发送指拨开关1的数据
       while(!ACK_flag);//发送完毕否?,没有就等待
  }
if(keydata2 != KEY2)//判断指拨开关2有没有变化?
 {
       keydata2 = KEY2;//不同则读入指拨开关2

       TB8=1;//设TB8=1,准备发送地址
       ACK_flag=0;//清主机发送结束标志
       SBUF=0x02;//发出02H地址(89C51-C)
       while(!ACK_flag);//发送完毕否?,没有就等待

       TB8=0;//设TB8=0,准备发送数据
          ACK_flag=0;//清主机发送结束标志
       SBUF = keydata2;//发送指拨开关2的数据
       while(!ACK_flag);//发送完毕否?,没有就等待
  }
UARTI() interrupt 4  //串行接收中断程序
{   
    if(TI)//是否发送中断?TI=1时,发送中断标志位 TI =1,表示一帧数据发送结束。
        { 
          TI=0;//发送中断,清除TI=0
          ACK_flag=1;//设定应答标志
         }
     else RI=0;//是接收中断,则清除RI=0 
}

上代码

单片机双机通信_第2张图片

主机

#include 
#define KEY1 P1//定义输入开关1
#define KEY2 P2//定义输入开关2
unsigned char keydata1;//存储指拨开关1的值
unsigned char keydata2;//存储指拨开关2的值
bit ACK_flag;//主机发送结束标志

//****************************************************
void init()
{
  SCON=0xF0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收
  PCON=0;//SMOD=0
  TMOD=0x20;//TIMER1工作在MODE2
  TH1=0xF3;//波特率2400
  TR1=1;//启动TIMER1
  IE=0x90;//EA=1、ES=1,CPU、UART中断使能
}

//****************************************************
void main()
{ 
  init();
  keydata1 = 0xFF;//设置指拨开关1初始值
  keydata2 = 0xFF;//设置指拨开关2初始值
  while(1)
   {
       KEY1=0xFF;//键盘口设为输入状态

       if(keydata1 != KEY1)//判断指拨开关1有没有变化?
      {
       keydata1 = KEY1;//不同则读入指拨开关1

       TB8=1;//设TB8=1,准备发送地址
       ACK_flag=0;//清主机发送结束标志
       SBUF=0x01;//发出01H地址(89C51-B)
       while(!ACK_flag);//发送完毕否?,没有就等待

       TB8=0;//设TB8=0,准备发送数据
       ACK_flag=0;//清主机发送结束标志
       SBUF = keydata1;//发送指拨开关1的数据
       while(!ACK_flag);//发送完毕否?,没有就等待
      }

      if(keydata2 != KEY2)//判断指拨开关2有没有变化?
      {
       keydata2 = KEY2;//不同则读入指拨开关2

       TB8=1;//设TB8=1,准备发送地址
       ACK_flag=0;//清主机发送结束标志
       SBUF=0x02;//发出02H地址(89C51-C)
       while(!ACK_flag);//发送完毕否?,没有就等待

       TB8=0;//设TB8=0,准备发送数据
       ACK_flag=0;//清主机发送结束标志
       SBUF = keydata2;//发送指拨开关2的数据
       while(!ACK_flag);//发送完毕否?,没有就等待
      }
   }
}
UARTI() interrupt 4  //串行接收中断程序
{   
    if(TI)//是否发送中断?
        { TI=0;//发送中断,清除TI=0
          ACK_flag=1;//设定应答标志
         }
     else RI=0;//是接收中断,则清除RI=0 
}

从机1

#include 
#define LEDOUT P0//定义输出指示灯
//****************************************************
void main()
 {   SCON=0xf0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收
     PCON=0;//SMOD=0
     TMOD=0x20;//TIMER1工作在MODE2
     TH1=0xF3;//波特率2400
     TR1=1;//启动TIMER1
     IE=0x90;//EA=1、ES=1,CPU、UART中断使能
     while(1); 
 }
//===============================
UARTI() interrupt 4   //串行接收中断程序        
//要么收到地址,要么收到数据,地址不对的是不会接收数据的,也不会产生中断
{   unsigned char a;//
    if(RI)//是否产生接收中断?
        {  RI=0;//接收中断,清除RI=0
           a = SBUF;//将SBUF载入
           if(SM2)//SM2=1接收地址,
               {   if(a==1)//是否89C51-B的地址
                       SM2=0;//是则清除SM2=0,准备接收数据 
               }
           else
               {LEDOUT = a;//SM2=0则将接收数据输出至P2 
                SM2 = 1;
               }//设SM2=1,准备下一次接收地址
        }
    else 
        TI=0;//是发送中断,则清除TI=0 
}

从机二

#include 
#define LEDOUT P0//定义输出指示灯
//*****************************************************
void main()
 {  SCON=0xf0;//设定UART工作在MODE3,SM2=1,REN=1,允许接收
    PCON=0;//SMOD=0
    TMOD=0x20;//TIMER1工作在MODE2
    TH1=0xF3;//波特率2400
    TR1=1;//启动TIMER1
    IE=0x90;//EA=1、ES=1,CPU、UART中断使能
    while(1); 
 }
//===============================
UARTI() interrupt 4 //串行接收中断程序
{   unsigned char a;//
    if(RI)//是否产生接收中断?
       {  RI=0;//接收中断,清除RI=0
          a = SBUF;//将SBUF载入
          if(SM2)//SM2=1接收地址,
             {if(a==2)//是否89C51-C的地址
                SM2=0;//是则清除SM2=0,准备接收数据 
             }
          else
             {LEDOUT = a;//SM2=0则将接收数据输出至LED显示
              SM2 = 1;//设SM2=1,准备下一次接收地址
             }
       }
   else 
       TI=0;//是发送中断,则清除TI=0 
}

你可能感兴趣的:(单片机)