[添付レポート 51 シングルチップマルチコンピュータ通信] ホストはスレーブ 1 のステッピング モーターとスレーブ 2 の超音波距離測定を制御します (ホストはステッパーの速度、方向、開始と停止の状態を集中的に表示できます)モーターと超音波距離測定結果)

1. 設計目標

    51個のシングルチップマイコンを3台使用し、マルチコンピュータ通信を実現します。

2、機能を実現する

    1号ワンチップマイコンは2号、3号ワンチップマイコンの遠隔制御や超音波距離測定などを行うことができます。

    ワンチップマイコンNo.1により、ステッピングモーターの速度、方向、起動、停止状態、超音波距離測定結果を集中表示できます。

3. ハードウェア原理

    51シングルチップマイコン、超音波測距モジュール、4相バイポーラステッピングモーター、ワイヤー、スタティックデジタル管、ダイナミックデジタル管、独立キー、74HC245チップ、74HC138チップ。

        5460d38d3c864746851f84ac52e3c071.png

 図1   

 

3eb589ddcfcd44d68535ccd3f95ba7eb.png

図2

 

455801d074444c8097fc8d250fd8239a.png

画像3

 

7f89457d0aa7486faab68dd705b11ebb.png

図4

 

3c5529e346d14dc1821ac61db95af7ec.png

図5

6f528dbb348446cb8c12bbe522063d6d.png

図6

 

09133c9243cb4976860770b4600377d5.png

図7

 

90f029f2c9144f47bfa20e0591e991fc.png

図8

 

542c6b4c53844d65802626d82e35ff54.png

図9

 

81b125d4c9a​​d42c9adeaea8b14d458c3.png

図10

 

b318b09ec4594c6a898d957509019028.png

図11 

 

5010f1a6c98545e381d0acd73daaf882.png

図12

    図1は超音波測距モジュールの内部回路図です。

    図2は、超音波測距の音波の出力および受信のタイミング論理図である。

    図 3 と図 5 はダイナミックデジタル管の制御です。51シングルチップマイコンのP0_0、P0_1、P0_2端子を74HC138チップのA、B、Cピンに接続し、どのデジタル管を点灯させるかを制御します。

    静止型ニキシー管の内部回路図である。

    ステッピングモータを制御する部分の内部回路図である。

    図 4 は独立したボタンの設定です。

    【図8】4線式バイポーラステッピングモータの内部概略図である。

    図 9 は、ステッピング モーターの回転の概略図です。

①Aプラスプラス極、A-プラスマイナス極、Bプラスマイナス極、B-プラスマイナス極(モーター状態、N極アップ)。

②Aプラスマイナス極、A-プラスマイナス極、Bプラスプラス極、B-プラスマイナス極(モーター状態、N極右向き、90度回転)。

③Aプラスマイナス極、A-プラスプラス極、Bプラスマイナス極、B-プラスマイナス極(モーター状態、N極が下向き)。

④Aプラスマイナス極、A-プラスマイナス極、Bプラスマイナス極、B-プラスプラス極(モーター状態、N極左向き)。

    対応するレベルを対応するピンに順番に与える限り、モーターを回転させることができ、最小回転角度は 90 度です。より小さい電源角度を実現するために、この設計での電源シーケンスは次のとおりです: A、AB、B、BA-、A-、AB-、B-、BA、最小回転角度は 45°です。

    図 10、図 11、および図 12 は、マルチマシン通信の動作原理を示しています。

    マルチコンピュータ通信では、ホストが各スレーブを識別できる必要があります。これは、51 シリーズ シングルチップ マイコンの SCON レジスタの SM2 ビットによって実現されます。シリアルポートがモード 2 またはモード 3 でデータを送信する場合、各フレーム情報は 11 ビットで、9 番目のビットはデータプログラマブルビットです。TB8 を 1 または 0 に設定することで、アドレスフレームとデータフレームを区別します。このビットが 1 の場合はアドレス フレームを送信し、このビットが 0 の場合はデータ フレームを送信します。

4. プログラムフローチャート

cd35b7baaad34204800defa0a0e2f4bb.png

 

5. コードの説明

    ホストコンピュータのコードは、メインプログラム、ハンドシェイクサブルーチン、ボタン昇降判定サブルーチン、遅延プログラム、送信デジタルプログラム、同期モータプログラム、速度チェックプログラム、クリアプログラム、距離測定プログラム、表示割り込みプログラムで構成されます。

    No.1スレーブコードは、メインプログラム、遅延プログラム、通信中断プログラム、速度調整プログラム、速度検証プログラム、表示プログラムで構成されます。

    第2子機コードは、メインプログラム、遅延プログラム、通信中断プログラム、レンジングプログラムから構成されます。

1. 主な機能

①ホスト

/**********************主函数*************************/
void main()
{
  zjcsh();
  key();
  lian();
  return 0;
}

 

②スレーブ1

/*************************主函数**********************************************************/
void main()
{
  csh();
  Int0Init();//声明加速的中断
  Int1Init();//声明减速的中断
  while(1)
  {
    mode(key());//先按键扫描,后选择模式
  }	
}

 

③スレーブ2

/*************************主函数*******************************/
void main()
{
 unsigned int time = 0;
 csh();
 while(1)
 {  
  time = RunOnce();//传感器接收到高电平的时间
  distance = GetDistance(time);
  xianshi(distance);
 }
}

 

2. サブ機能 1

    ホストの遅延機能。

/**********************延时函数*************************/
void delay(unsigned int t)//调节给电机供电的时间,从而调速	
{
  while(t--);

 

3. サブ機能 2

    ホストのダイナミックデジタルチューブ表示機能。超音波距離測定結果を表示するダイナミックデジタルチューブに使用されます。

}/*********************动态数码管显示*************************/
void shumaguan(unsigned char wei,num)//第几位(wei)显示
{
 switch(wei)
 {
  case 1:P3_5=0;P3_6=0;P3_7=0;break;
  case 2:P3_5=0;P3_6=0;P3_7=1;break;
  case 3:P3_5=0;P3_6=1;P3_7=0;break;
  case 4:P3_5=0;P3_6=1;P3_7=1;break;
  case 5:P3_5=1;P3_6=0;P3_7=0;break;
  case 6:P3_5=1;P3_6=0;P3_7=1;break;
  case 7:P3_5=1;P3_6=1;P3_7=0;break;
  case 8:P3_5=1;P3_6=1;P3_7=1;break;
 }
 P1=shuzi[num];
 delay(1);
}

 

4. サブ機能3

    ホストの範囲表示機能。ダイナミックデジタルチューブを制御して超音波距離測定の結果を表示するために使用されます。

/**********************测距显示*************************/
void xianshi(int d)
{
  int k=8,m;
  while(d!=0)
  {
    m=(d%10);//在数码管上显示个位,从后往前显示
    shumaguan(k,m);
    k--;//数码管向前移位
    d=d/10;
  }
}

5. サブ機能 4

    ホスト初期化機能。動作モード 3 を定義し、SM2 の初期状態を定義します。ボーレートを 9600 として定義します。

/**********************主机初始化*************************/
void zjcsh()
{
  TMOD=0x20;
  SCON=0xd0;
  TH1=TL1=0xfd;
  PCON=0X00;;
  TR1=1;
  ES=1;
  EA=1;
}

 

6. サブ機能 5

    マスターがスレーブと接続を確立し、呼び出し用のアドレスを送信する機能。

/**********************建立联系——发地址*************************/
void lian(date)
{
  TB8=1;//发送的地址
  if(date==1&&2&&3&&4&&5&&6)
  {
    SBUF=0xA1;//从机1 步进电机
  }
  else
  {
    SBUF=0xA2;//从机2 超声波测距
  }
  while(!TI);
  TI=0;
}

 

7. サブ機能 6

    ホストの割り込みデータ送受信機能。受信したスレーブ機のフィードバック情報を判断し、どのスレーブ機が送信したかを判断し、2台のスレーブ機に異なるコマンド情報を送信して制御します。受信したデータがスレーブからフィードバックされると、さまざまな方法で表示されます。ダイナミックデジタルチューブは超音波距離測定結果を表示し、スタティックデジタルチューブはステッピングモーターの速度を表示します。

/**********************中断接收——发数据*************************/
void zd()interrupt 4
{
  RI=0;
  addr=SBUF;
  if(RB8==1)//判断是否为地址
  {
	if(addr==0xA1)
	{
	  TB8=0;//发送的是数据
	  SBUF=date;//给从机1发数据
	  while(!TI);
	  TI=0;
	}
	if(addr==0xA2)
	{
	  TB8=0;//发送的是数据
	  SBUF=date;//给从机2发数据
	  while(!TI);
	  TI=0;
	}
  }
  else
  {
    if(RB8==0)//判断是否为数据
	{
	  dat=SBUF; 
	  if(addr==0xA1)
	  {
	    P0=smg[dat];//显示电机速度
	  }
	  else
	  {
	    xianshi(dat);//显示测距结果
	  }  
	}
  }
}

 

8. サブ機能7

    ホストのキー判定機能。ステッピングモーターの制御コマンドを生成するために使用されます。

/**********************按键判断*************************/
void key()
{
  if(P2_0==0) date=1;//顺时针
  if(P2_1==0) date=2;//逆时针
  if(P2_2==0) date=3;//启动
  if(P2_3==0) date=4;//停机
  if(P2_4==0) date=5;//加速
  if(P2_5==0) date=6;//减速
  if(P2_6==0) date=7;//超声波测距
  if(P2_7==0) date=8;
}

 

9. サブ機能8

    スレーブ1の遅延機能。

/***************************延时函数*******************************/
void delay(unsigned int t)//调节给电机供电的时间,从而调速	
{
  while(t--);
}

 

10. サブ機能9

    スレーブ1のキースキャン機能。スレーブ側のステッピングモーターの制御に使用します。

/***************************按键扫描***************************************/
int key()
{
  if(P0_0==0) i=1;//顺时针
  if(P0_1==0) i=2;//逆时针
  if(P0_2==0) i=3;//启动/回到初速度
  if(P0_3==0) i=4;//停机
  return i;
}  

 

11. サブ機能10

    スレーブ1のモード判定機能。ステッピングモーターの制御に使用されます。

/****************************模式判断**************************************/  
void mode(int i)//由按键扫描返回值判断 
{
  switch(i)
  {
/****************模式1 正转****************/
	case 1:
	  while(1)
	  {
	    for(n=0;n<8;n++)//循环供电
		{
		  P2=SSZ[n];//供电
		  delay(V);//延时
		  P1=~smg[D];//显示速度档
		}
		break;
	  }  
	 break; 	 
/****************模式2 反转****************/
	case 2:
	  while(1)
	  {
	    for(n=0;n<8;n++)//循环供电
		{
		  P2=NSZ[n];//供电
		  delay(V);//延时
		  P1=~smg[D];//显示速度档
		}
		break;
	  }
	  break;     
/****************启动/重启****************/ 
	case 3:
	  V=500;//启动的速度/初速度
	  D=1;//速度1档,自动进入模式1
/****************停机****************/
	case 4:
	  P2=0X00;//不给电机供电
	  P1=~smg[0];//数码管显示0 共阳极 取反供电 
	  break;  	       
  }
}

 

 

12. サブ機能11

    スレーブ1の割り込み初期化関数。

/*************************中断初始化*****************************/
void Int0Init()//加速
{
  IT0=1;//下降沿有效 
  EX0=1;//IT0中断允许 
  EA=1;//总开关打开 
}

void Int1Init()//减速
{
  IT1=1;
  EX1=1;
  EA=1;
}

 

13. サブ機能12

    スレーブ1の速度調整機能。

/*************************调速函数****************************/
void Int0() interrupt 0	 //加速
{
  if(P3_2==0)//判断加速键是否被按下
  {
    delay(2000);//消抖
    if(P3_2==0)//消抖后再次判断
	{
      V=V-50;//延时时间减少,所以速度增加
	  D=D+1;//速度档加1
	}
  }
}

void Int1() interrupt 2	 //减速
{
  if(P3_3==0)//判断减速键是否被按下
  {
    delay(2000);//消抖
    if(P3_3==0)//消抖后再次判断
	{
      V=V+50;//延时时间增加,所以速度减少
	  D=D-1;//速度档减1
	}
  }
}

 

14. サブ機能13

    スレーブ1の通信初期化関数。

/*************************初始化*******************************/
void csh()
{
  TMOD=0x20; //定时器工作方式2 
  REN=1;
  SM0=1;
  SM1=1;
  SM2=1;//主机置0 从机置1
  TH1=TL1=0xfd; //9600波特率
  SCON=0X00;
  TR1=1;//开定时
  TI=0;
  RI=0;
  ES=1;//开串口中断
  EA=1;//串口总开关
}

15. サブ機能14

    スレーブ1の割り込み受信機能。

/*************************中断收*******************************/
void zd() interrupt 4
{
  RI=0;
  if(RB8==1)//再判断接受数据=地址
  {
    if(addr==SBUF)
	{
	  SM2=0;
	  P2_0=0;
	  TB8=1;
	  SBUF=0XA1;
	  while(!TI);
	  TI=0;
	}
  }
  else
  {
    date=SBUF;
	P2_1=0;
	mode(date);
	TB8=1;
	SBUF=D;
	while(!TI);
	TI=0;
	SM2=1;
  }
}

16. サブ機能15

    スレーブ2の遅延機能。

/******************************************延时函数***************************************/
void delay(unsigned int xms)//延时x毫秒 
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=112;j>0;j--);
return;
}

 

17. サブ機能16

    スレーブ2のデジタル管表示機能。

/******************************************数码管控制函数***************************************/
unsigned char shuzi[]={0x3f/*0*/,0x06/*1*/,0x5b/*2*/,0x4f/*3*/,0x66/*4*/,0x6d/*5*/,0x7d/*6*/,0x07/*7*/,0x7f/*8*/,0x6f/*9*/};//显示的数字(num)的数组
 
void shumaguan(unsigned char wei,num)//第几位(wei)显示
{
 switch(wei)
 {
  case 1:P0_2=0;P0_1=0;P0_0=0;break;
  case 2:P0_2=0;P0_1=0;P0_0=1;break;
  case 3:P0_2=0;P0_1=1;P0_0=0;break;
  case 4:P0_2=0;P0_1=1;P0_0=1;break;
  case 5:P0_2=1;P0_1=0;P0_0=0;break;
  case 6:P0_2=1;P0_1=0;P0_0=1;break;
  case 7:P0_2=1;P0_1=1;P0_0=0;break;
  case 8:P0_2=1;P0_1=1;P0_0=1;break;
 }
 P3=shuzi[num];
 delay(1);
}

 

18. サブ機能17

    スレーブ2のタイマー機能。方形波を生成するために使用されます。

/**********************************定时器函数 延时10us*************************************/
void Delay10us()
{
 TMOD |= 0x01;//16位定时器/计数器
 TH0 = 0xFF;//赋初值
 TL0 = 0xF6;//赋初值
 TR0 = 1;//启动
 
 while(!TF0);//溢出
 
 TF0 = 0;//清溢出
}

 

19. サブ機能18

    スレーブ2の距離関数を計算します。

/******************************************算距离函数***************************************/
float GetDistance(unsigned int time)  
{
 float distance;
 distance = (float)time * 0.017;//cm    距离=高电平时间×声速/2        0.017cm/us
 
 return distance;//将距离返回主函数
}

 

20. サブ機能19

    スレーブ2の計測時間機能です。

/******************************************测时间函数***************************************/
unsigned int RunOnce()  
{
 unsigned int time;
 
/******************发送10us高电平信号*************/
 Trig = 0;
 Trig = 1;
 Delay10us();
 Trig = 0;
/**************等待高电平信号接收*****************/
 while(!Echo);
/*********T0清0重新计数(高电平持续时间)*********/
 TH0 = 0;
 TL0 = 0;
 TR0 = 1;
/*********等待高电平信号接收结束******************/
 while(Echo);
/*******************关闭T0计数********************/
 TR0 = 0;
/**********高电平时间赋值,单位us*****************/
 time = TH0*256 + TL0; 
 TH0 = 0;
 TL0 = 0;
 
 return time;
}

 

21. サブ機能20

    スレーブマシン 2 のダイナミックニキシー管は結果関数を表示します。データを処理し、デジタル管機能に渡して結果を表示するために使用されます。

/**************************************动态数码管显示结果***********************************/
void xianshi(int d)
{
  int k=8,m;
  while(d!=0)
  {
    m=(d%10);//在数码管上显示个位,从后往前显示
    shumaguan(k,m);
 k--;//数码管向前移位
 d=d/10;
  }
}

 

22. サブ機能21

    スレーブ2の通信初期化関数。

/*************************初始化*******************************/
void csh()
{
  TMOD=0x20; //定时器工作方式2 
  REN=1;
  SM0=1;
  SM1=1;
  SM2=1;//主机置0 从机置1
  TH1=TL1=0xfd; //9600波特率
  SCON=0X00;
  TR1=1;//开定时
  TI=0;
  RI=0;
  ES=1;//开串口中断
  EA=1;//串口总开关
}

 

23. サブ機能22

    スレーブ2の割り込み受信機能。

/*************************中断收*******************************/
void zd() interrupt 4
{
  RI=0;
  if(RB8==1)//再判断接受数据=地址
  {
    if(addr==SBUF)
	{
	  SM2=0;
	  P2_0=0;
	  TB8=1;
	  SBUF=0XA2;
	  while(!TI);
	  TI=0;
	}
  }
  else
  {
    date=SBUF;
	P2_1=0;
	TB8=0;
	SBUF=distance;
	while(!TI);
	TI=0;
	SM2=1; 
  }
}

6. ソースコード 

1. ホスト

#include <REGX51.H>
int addr;
int date,dat;
int num;
int D=1;//V在延时函数中,用于调速;D用来控制数码管显示的数字
smg[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//用于显示档速 0-f 
unsigned char shuzi[]={0x3f/*0*/,0x06/*1*/,0x5b/*2*/,0x4f/*3*/,0x66/*4*/,0x6d/*5*/,0x7d/*6*/,0x07/*7*/,0x7f/*8*/,0x6f/*9*/};//显示的数字(num)的数组
/**********************延时函数*************************/
void delay(unsigned int t)//调节给电机供电的时间,从而调速	
{
  while(t--);
}/*********************动态数码管显示*************************/
void shumaguan(unsigned char wei,num)//第几位(wei)显示
{
 switch(wei)
 {
  case 1:P3_5=0;P3_6=0;P3_7=0;break;
  case 2:P3_5=0;P3_6=0;P3_7=1;break;
  case 3:P3_5=0;P3_6=1;P3_7=0;break;
  case 4:P3_5=0;P3_6=1;P3_7=1;break;
  case 5:P3_5=1;P3_6=0;P3_7=0;break;
  case 6:P3_5=1;P3_6=0;P3_7=1;break;
  case 7:P3_5=1;P3_6=1;P3_7=0;break;
  case 8:P3_5=1;P3_6=1;P3_7=1;break;
 }
 P1=shuzi[num];
 delay(1);
}
/**********************测距显示*************************/
void xianshi(int d)
{
  int k=8,m;
  while(d!=0)
  {
    m=(d%10);//在数码管上显示个位,从后往前显示
    shumaguan(k,m);
    k--;//数码管向前移位
    d=d/10;
  }
}
/**********************主机初始化*************************/
void zjcsh()
{
  TMOD=0x20;
  SCON=0xd0;
  TH1=TL1=0xfd;
  PCON=0X00;;
  TR1=1;
  ES=1;
  EA=1;
}
/**********************建立联系——发地址*************************/
void lian(date)
{
  TB8=1;//发送的地址
  if(date==1&&2&&3&&4&&5&&6)
  {
    SBUF=0xA1;//从机1 步进电机
  }
  else
  {
    SBUF=0xA2;//从机2 超声波测距
  }
  while(!TI);
  TI=0;
}
/**********************中断接收——发数据*************************/
void zd()interrupt 4
{
  RI=0;
  addr=SBUF;
  if(RB8==1)//判断是否为地址
  {
	if(addr==0xA1)
	{
	  TB8=0;//发送的是数据
	  SBUF=date;//给从机1发数据
	  while(!TI);
	  TI=0;
	}
	if(addr==0xA2)
	{
	  TB8=0;//发送的是数据
	  SBUF=date;//给从机2发数据
	  while(!TI);
	  TI=0;
	}
  }
  else
  {
    if(RB8==0)//判断是否为数据
	{
	  dat=SBUF; 
	  if(addr==0xA1)
	  {
	    P0=smg[dat];//显示电机速度
	  }
	  else
	  {
	    xianshi(dat);//显示测距结果
	  }  
	}
  }
}
/**********************按键判断*************************/
void key()
{
  if(P2_0==0) date=1;//顺时针
  if(P2_1==0) date=2;//逆时针
  if(P2_2==0) date=3;//启动
  if(P2_3==0) date=4;//停机
  if(P2_4==0) date=5;//加速
  if(P2_5==0) date=6;//减速
  if(P2_6==0) date=7;//超声波测距
  if(P2_7==0) date=8;
}
/**********************主函数*************************/
void main()
{
  zjcsh();
  key();
  lian();
  return 0;
}

2. スレーブ 1 (ステッピング モーター)

#include <REGX51.H>
int addr=0xA1;
int date;
unsigned char SSZ[] = {0x08,0x0a,0x02,0x06,0x04,0x05,0x01,0x09};//顺时针数组
unsigned char NSZ[] = {0x09,0x01,0x05,0x04,0x06,0x02,0x0a,0x08};//逆时针数组
smg[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//用于显示档速 0-f 
int V=500,D=1;//V在延时函数中,用于调速;D用来控制数码管显示的数字
int i=4;//先使电机处于停机状态
int n=0;//用于循环给电机通电
/*************************步进电机******************************************************************************/
/***************************延时函数*******************************/
void delay(unsigned int t)//调节给电机供电的时间,从而调速	
{
  while(t--);
}
/***************************按键扫描***************************************/
int key()
{
  if(P0_0==0) i=1;//顺时针
  if(P0_1==0) i=2;//逆时针
  if(P0_2==0) i=3;//启动/回到初速度
  if(P0_3==0) i=4;//停机
  return i;
}  
/****************************模式判断**************************************/  
void mode(int i)//由按键扫描返回值判断 
{
  switch(i)
  {
/****************模式1 正转****************/
	case 1:
	  while(1)
	  {
	    for(n=0;n<8;n++)//循环供电
		{
		  P2=SSZ[n];//供电
		  delay(V);//延时
		  P1=~smg[D];//显示速度档
		}
		break;
	  }  
	 break; 	 
/****************模式2 反转****************/
	case 2:
	  while(1)
	  {
	    for(n=0;n<8;n++)//循环供电
		{
		  P2=NSZ[n];//供电
		  delay(V);//延时
		  P1=~smg[D];//显示速度档
		}
		break;
	  }
	  break;     
/****************启动/重启****************/ 
	case 3:
	  V=500;//启动的速度/初速度
	  D=1;//速度1档,自动进入模式1
/****************停机****************/
	case 4:
	  P2=0X00;//不给电机供电
	  P1=~smg[0];//数码管显示0 共阳极 取反供电 
	  break;  	       
  }
}
/*************************中断初始化*****************************/
void Int0Init()//加速
{
  IT0=1;//下降沿有效 
  EX0=1;//IT0中断允许 
  EA=1;//总开关打开 
}

void Int1Init()//减速
{
  IT1=1;
  EX1=1;
  EA=1;
}
/*************************调速函数****************************/
void Int0() interrupt 0	 //加速
{
  if(P3_2==0)//判断加速键是否被按下
  {
    delay(2000);//消抖
    if(P3_2==0)//消抖后再次判断
	{
      V=V-50;//延时时间减少,所以速度增加
	  D=D+1;//速度档加1
	}
  }
}

void Int1() interrupt 2	 //减速
{
  if(P3_3==0)//判断减速键是否被按下
  {
    delay(2000);//消抖
    if(P3_3==0)//消抖后再次判断
	{
      V=V+50;//延时时间增加,所以速度减少
	  D=D-1;//速度档减1
	}
  }
}
/*************************初始化*******************************/
void csh()
{
  TMOD=0x20; //定时器工作方式2 
  REN=1;
  SM0=1;
  SM1=1;
  SM2=1;//主机置0 从机置1
  TH1=TL1=0xfd; //9600波特率
  SCON=0X00;
  TR1=1;//开定时
  TI=0;
  RI=0;
  ES=1;//开串口中断
  EA=1;//串口总开关
}
/*************************中断收*******************************/
void zd() interrupt 4
{
  RI=0;
  if(RB8==1)//再判断接受数据=地址
  {
    if(addr==SBUF)
	{
	  SM2=0;
	  P2_0=0;
	  TB8=1;
	  SBUF=0XA1;
	  while(!TI);
	  TI=0;
	}
  }
  else
  {
    date=SBUF;
	P2_1=0;
	mode(date);
	TB8=1;
	SBUF=D;
	while(!TI);
	TI=0;
	SM2=1;
  }
}

/*************************主函数**********************************************************/
void main()
{
  csh();
  Int0Init();//声明加速的中断
  Int1Init();//声明减速的中断
  while(1)
  {
    mode(key());//先按键扫描,后选择模式
  }	
}

3. スレーブ 2 (超音波測距)

#include <REGX51.H>
int addr=0xA2;
int date;
float distance;
sbit Trig = P1^0;
sbit Echo = P1^1;
/******************************************延时函数***************************************/
void delay(unsigned int xms)//延时x毫秒 
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=112;j>0;j--);
return;
}
/******************************************数码管控制函数***************************************/
unsigned char shuzi[]={0x3f/*0*/,0x06/*1*/,0x5b/*2*/,0x4f/*3*/,0x66/*4*/,0x6d/*5*/,0x7d/*6*/,0x07/*7*/,0x7f/*8*/,0x6f/*9*/};//显示的数字(num)的数组
 
void shumaguan(unsigned char wei,num)//第几位(wei)显示
{
 switch(wei)
 {
  case 1:P0_2=0;P0_1=0;P0_0=0;break;
  case 2:P0_2=0;P0_1=0;P0_0=1;break;
  case 3:P0_2=0;P0_1=1;P0_0=0;break;
  case 4:P0_2=0;P0_1=1;P0_0=1;break;
  case 5:P0_2=1;P0_1=0;P0_0=0;break;
  case 6:P0_2=1;P0_1=0;P0_0=1;break;
  case 7:P0_2=1;P0_1=1;P0_0=0;break;
  case 8:P0_2=1;P0_1=1;P0_0=1;break;
 }
 P3=shuzi[num];
 delay(1);
}
/**********************************定时器函数 延时10us*************************************/
void Delay10us()
{
 TMOD |= 0x01;//16位定时器/计数器
 TH0 = 0xFF;//赋初值
 TL0 = 0xF6;//赋初值
 TR0 = 1;//启动
 
 while(!TF0);//溢出
 
 TF0 = 0;//清溢出
}
/******************************************算距离函数***************************************/
float GetDistance(unsigned int time)  
{
 float distance;
 distance = (float)time * 0.017;//cm    距离=高电平时间×声速/2        0.017cm/us
 
 return distance;//将距离返回主函数
}
/******************************************测时间函数***************************************/
unsigned int RunOnce()  
{
 unsigned int time;
 
/******************发送10us高电平信号*************/
 Trig = 0;
 Trig = 1;
 Delay10us();
 Trig = 0;
/**************等待高电平信号接收*****************/
 while(!Echo);
/*********T0清0重新计数(高电平持续时间)*********/
 TH0 = 0;
 TL0 = 0;
 TR0 = 1;
/*********等待高电平信号接收结束******************/
 while(Echo);
/*******************关闭T0计数********************/
 TR0 = 0;
/**********高电平时间赋值,单位us*****************/
 time = TH0*256 + TL0; 
 TH0 = 0;
 TL0 = 0;
 
 return time;
}
/**************************************动态数码管显示结果***********************************/
void xianshi(int d)
{
  int k=8,m;
  while(d!=0)
  {
    m=(d%10);//在数码管上显示个位,从后往前显示
    shumaguan(k,m);
 k--;//数码管向前移位
 d=d/10;
  }
}
/*************************初始化*******************************/
void csh()
{
  TMOD=0x20; //定时器工作方式2 
  REN=1;
  SM0=1;
  SM1=1;
  SM2=1;//主机置0 从机置1
  TH1=TL1=0xfd; //9600波特率
  SCON=0X00;
  TR1=1;//开定时
  TI=0;
  RI=0;
  ES=1;//开串口中断
  EA=1;//串口总开关
}
/*************************中断收*******************************/
void zd() interrupt 4
{
  RI=0;
  if(RB8==1)//再判断接受数据=地址
  {
    if(addr==SBUF)
	{
	  SM2=0;
	  P2_0=0;
	  TB8=1;
	  SBUF=0XA2;
	  while(!TI);
	  TI=0;
	}
  }
  else
  {
    date=SBUF;
	P2_1=0;
	TB8=0;
	SBUF=distance;
	while(!TI);
	TI=0;
	SM2=1; 
  }
}
/*************************主函数*******************************/
void main()
{
 unsigned int time = 0;
 csh();
 while(1)
 {  
  time = RunOnce();//传感器接收到高电平的时间
  distance = GetDistance(time);
  xianshi(distance);
 }
}

 

 

おすすめ

転載: blog.csdn.net/m0_57007304/article/details/130144460