找回密码
 立即注册

QQ登录

只需一步,快速开始

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

多台单片机间网络的实现(互相通信)含源码

[复制链接]
跳转到指定楼层
楼主
一、功能
主体功能:三台单片机之间两两互相通信,为此,我们将其拟人化,以三个主人公Jack、Carl、Lily之间的交流来演示。具体过程如下:
①初始状态(从上至下分别为Jack、Lily、Carl):



②Lily编辑“HELLO!”的字符串准备发送给Jack:

③Lily按下发送后Jack的接收结果:
④Carl编辑“Hi!”发送给Lily同时Lily接收:

⑤Jack编辑“HOW ARE U”发送给Carl同时Carl接收:

⑥特殊情况:当传送过来的数据经奇偶校验出错后给出报错提示:

二、 网络的设计
物理层:
传输介质:
采用两条杜邦线连接单片机的两个io口,一个io口定时变换高低电平输出数据,另一个io口定时检测电平高低来读取数据,实现了全双工通讯。
每台单片机都有2对(4个)io口可以发送接受数据,这为多台机器组成网络提供了基础。
多台单片机连接方式:

我们用3台单片机组成了一条线似的结构,实际上这个网络还可以在边上扩展延长,这个网络中不存在主机,每台机器都是平等的。
每台单片机收到信息后,都会将信息从另一对io口发出。每台单片机发送给信息时候,也会将信息从两对io口同时发出,因此一旦有信息发送,信息会传播到整个网络。
编码技术:采用不归零电平编码方式(NRZ-L),高电平代表1,低电平代表0,每一bit数据的持续时间是31.108ms。由于每bit的持续时间决定了传输速率,因此传输数据可以通过简单修改宏定义来实现,不过随着传输速率的提高,出错率会增加。


传输协议:采用异步传输方式,每次传输一个bit。传输数据的格式如下
0
X
X
X
X
X
X
X
X
P
起始位
数据位
奇偶校验


数据链路层:
成帧技术采用的是字符计数成帧技术,首部的高4位代表接下来要发送的字符数
3(高四位)
1
3
2
1(高四位)
7
2(高四位)
8
4
计数首部
数据部分
数据部分
数据部分
计数首部
数据部分
计数首部
数据部分
数据部分
数据是由谁发出,数据发给谁:
这部分功能也是由字符首部来完成,首部的结构如下:
0
0
1
0
0
0
0
1
计数
目标地址
源地址
如上图所示,这个首部代表接下来还要发送2个字符,目标地址是0,源地址是1。

三、            部分代码
3台单片机的代码都是相同的,连接外部按键和显示器的引脚差别可以通过修改宏定义来适配。因此只列出一台单片机的代码
1.       main.h
  1. #ifndef _main_h_
  2. #define _main_h_

  3. #define MYNAME "Jack"
  4. #define NAME_NUM 2
  5. #define BUTTON_IO P3
  6. #define PRESS_LEFT 0x0E//k30
  7. #define PRESS_RIGHT 0x0D //k31
  8. #define CHANGE 0x0B                 //k32
  9. #define SEND 0x07                            //k33
  10. #define PRESS_TIME 5000//按键消去抖动时间
  11. #define ASCII 32
  12. #define GPIO_KEY P3  //独立键盘用P1口
  13. //carl Lily Jack Lisa

  14. void send(unsigned char* TxArray,unsigned char sendTo);
  15. void receive(void);
  16. void errorFun(unsigned char a);
  17. unsigned char Key_Scan();
  18. Show_Name(int sendTo);  //显示名字
  19. #endif
复制代码

2.       1602LCD.h
#ifndef _1602LCD_h_
#define _1602LCD_h_
sbit RS = P2 ^ 6;    //寄存器选择位,将RS位定义为P2.0引脚
sbit RW = P2 ^ 5;    //读写选择位,将RW位定义为P2.1引脚
sbit E = P2 ^ 7;     //使能信号位,将E位定义为P2.2引脚
sbit BF = P0 ^ 7;    //忙碌标志位,,将BF位定义为P0.7引脚

bit BusyTest(void);
void Write_com(unsigned char dictate);
void WriteAddress(unsigned char x);
void WriteData(unsigned char y);
void LcdInt(void);

#endif

3.       main.c
  1. #include  //  包含51单片机寄存器定义的头文件
  2. #include"1602LCD.h"
  3. #include"myParity.h"
  4. #include"main.h"

  5. sbit TxPort = P1 ^ 0;
  6. sbit RxPort = P1 ^ 1;
  7. sbit TxPort2 = P1 ^ 2;
  8. sbit RxPort2 = P1 ^ 3;
  9. #define TIMEHIGH 0xD0;
  10. #define TIMELOW 0x00;
  11. unsigned char i;
  12. unsigned int TxData;
  13. unsigned char Ti;
  14. unsigned int RxData;
  15. unsigned char Ri;
  16. unsigned char code tab[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90 }; //共阳数码管 0-9


  17. /**************************************************************
  18. 函数功能:主函数
  19. **************************************************************/
  20. void main(void)
  21. {
  22. unsigned char TxArray[13] = {0,0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0 };
  23.               unsigned char position = 0;
  24.               unsigned char sendTo = 0;

  25.               unsigned char keyNum;                 //获取键值
  26.               char a;                                             //循环变量
  27.               char flag=0;
  28.               RxData = 0;
  29.               TxData = 0;
  30.               Ti = 0;
  31.               Ri = 0;
  32.               i = 0;
  33.               P1 = 0xff;
  34.               P3=0xff;
  35.               P3=0xff;
  36.             
  37.               EA = 1;                  //开总中断
  38.               ET0 = 1;                 //定时器T0中断允许        
  39.               TMOD = 0x01;             //使用定时器T0的模式1
  40.               TH0 = TIMEHIGH;
  41.               TL0 = TIMELOW;
  42.               TR0 = 1;                 //启动定时器T0
  43.               LcdInt();
  44.               delay(1000);

  45.               Write_com(0x01);//清显示:清屏幕指令
  46.               WriteAddress(0x40);
  47.               WriteAddress(0x40);
  48.               for(a=0;a<10;a++)
  49.               {                                                      
  50.                             WriteAddress(0x40+a);
  51.                             WriteData(ASCII+TxArray[a]);                           
  52.               }                           
  53.               WriteAddress(0x4A);
  54.               WriteData('-');            
  55.               WriteAddress(0x4B);
  56.               WriteData('>');            
  57.               WriteAddress(0x40);
  58.               sendTo=NAME_NUM+1;
  59.               if(NAME_NUM>1)
  60.               sendTo=0;            
  61.               Show_Name(sendTo);
  62.               WriteAddress(0x40);
  63.               while (1)//无限循环等待中断
  64.               {
  65.                             keyNum = Key_Scan();  //扫描键盘
  66.                             switch (keyNum&0x0F)
  67.                             {
  68.                                           case(PRESS_LEFT) :               
  69.                                                         if( (position>=0) && (position<10) )
  70.                                                         {                                                                                                
  71.                                                                       WriteAddress(0x40+position);
  72.                                                                       if(TxArray[position]<32)
  73.                                                                                     TxArray[position]=128;
  74.                                                                       else            
  75.                                                                                     TxArray[position]--;
  76.                                                                       WriteData(TxArray[position]);                                                                                   
  77.                                                                       WriteAddress(0x40+position);
  78.                                                         }
  79.                                                         else if( (position==10) || (position==11) )
  80.                                                         {
  81.                                                                       for(a=0;a<10;a++)
  82.                                                                       {                                                      
  83.                                                                                     TxArray[a]=0;
  84.                                                                                     WriteAddress(0x40+a);
  85.                                                                                     WriteData(0);            
  86.                                                                       }                           
  87.                                                                       WriteAddress(0x40);
  88.                                                                       position=0;
  89.                                                         }
  90.                                                         else
  91.                                                         {
  92.                                                                       if(sendTo>0)
  93.                                                                       {
  94.                                                                                     sendTo--;
  95.                                                                       }
  96.                                                                       else
  97.                                                                       {
  98.                                                                                     sendTo=3;
  99.                                                                       }                                                                                       
  100.                                                                       Show_Name(sendTo);
  101.                                                         }
  102.                                                         break;
  103.                                           case(PRESS_RIGHT) :                                                         
  104.                                                         if( (position>=0) && (position<10) )
  105.                                                         {                                                                                                
  106.                                                                       WriteAddress(0x40+position);
  107.                                                                       if(TxArray[position]<32)
  108.                                                                                     TxArray[position]=65;
  109.                                                                       else if(TxArray[position]>128)
  110.                                                                                     TxArray[position]=32;
  111.                                                                       else            
  112.                                                                                     TxArray[position]++;
  113.                                                                       WriteData(TxArray[position]);                                                                                   
  114.                                                                       WriteAddress(0x40+position);
  115.                                                         }
  116.                                                         else if( (position==10) || (position==11) )
  117.                                                         {
  118.                                                                       for(a=0;a<10;a++)
  119.                                                                       {                                                      
  120.                                                                                     TxArray[a]=0;
  121.                                                                                     WriteAddress(0x40+a);
  122.                                                                                     WriteData(ASCII);                           
  123.                                                                       }                                         
  124.                                                                       WriteAddress(0x40);
  125.                                                                       position=0;
  126.                                                         }
  127.                                                         else
  128.                                                         {
  129.                                                                       if(sendTo<3)
  130.                                                                       {
  131.                                                                                     sendTo++;
  132.                                                                       }
  133.                                                                       else
  134.                                                                       {
  135.                                                                                     sendTo=0;
  136.                                                                       }                                                                                      
  137.                                                                       Show_Name(sendTo);
  138.                                                         }
  139.                                                         break;
  140.                                           case(CHANGE) :               
  141.                                                         if(position<12)
  142.                                                         {
  143.                                                                       position++;
  144.                                                         }
  145.                                                         else
  146.                                                         {
  147.                                                                       position=0;
  148.                                                         }
  149.                                                         WriteAddress(0x40+position);
  150.                                                         break;
  151.                                           case(SEND) :
  152.                                                         flag=0;
  153.                                                         for(a=9;a>=0;a--)
  154.                                                         {
  155.                                                                       if(flag==1&&TxArray[a]==0)
  156.                                                                                     TxArray[a]=32;
  157.                                                                       else if(TxArray[a]!=0)
  158.                                                                                     flag=1;
  159.                                                         }            
  160.                                                         send(TxArray,sendTo);
  161.                                                         break;
  162.                                           default:
  163.                                                         break;
  164.                             }
  165.                             receive();
  166.               }

  167. }

  168. Show_Name(int sendTo)
  169. {                                                                                                   
  170.               if(sendTo==0)
  171.               {
  172.                             WriteAddress(0x4C);
  173.                             WriteData('C');            
  174.                             WriteAddress(0x4D);
  175.                             WriteData('a');
  176.                             WriteAddress(0x4E);
  177.                             WriteData('r');            
  178.                             WriteAddress(0x4F);
  179.                             WriteData('l');
  180.                             WriteAddress(0x4C);
  181.               }
  182.               else if(sendTo==1)
  183.               {
  184.                             WriteAddress(0x4C);
  185.                             WriteData('L');            
  186.                             WriteAddress(0x4D);
  187.                             WriteData('i');
  188.                             WriteAddress(0x4E);
  189.                             WriteData('l');            
  190.                             WriteAddress(0x4F);
  191.                             WriteData('y');
  192.                             WriteAddress(0x4C);
  193.               }
  194.               else if(sendTo==2)
  195.               {
  196.                             WriteAddress(0x4C);
  197.                             WriteData('J');            
  198.                             WriteAddress(0x4D);
  199.                             WriteData('a');
  200.                             WriteAddress(0x4E);
  201.                             WriteData('c');            
  202.                             WriteAddress(0x4F);
  203.                             WriteData('k');
  204.                             WriteAddress(0x4C);
  205.               }
  206.               else
  207.               {
  208.                             WriteAddress(0x4C);
  209.                             WriteData('L');            
  210.                             WriteAddress(0x4D);
  211.                             WriteData('i');
  212.                             WriteAddress(0x4E);
  213.                             WriteData('s');            
  214.                             WriteAddress(0x4F);
  215.                             WriteData('a');
  216.                             WriteAddress(0x4C);
  217.               }
  218. }
  219. /*******************************************************************************
  220. * 函 数 名         : Key_Scan()
  221. * 函数功能                               : 扫描键盘
  222. * 输    入         : 无
  223. * 输    出         : 读取到的键值
  224. *******************************************************************************/

  225. unsigned char Key_Scan()
  226. {
  227.               unsigned char keyValue = 0 , i; //保存键值

  228.               //--检测按键1--//
  229.               if (GPIO_KEY != 0xFF)                            //检测按键是否按下
  230.               {
  231.                             delay(PRESS_TIME);              //消除抖动

  232.                             if (GPIO_KEY != 0xFF)              //再次检测按键是否按下
  233.                             {
  234.                                           keyValue = GPIO_KEY;
  235. /*                                          i = 0;
  236.                                           while ((i<50) && (GPIO_KEY != 0xFF))              //检测按键是否松开
  237.                                           {
  238.                                                         delay(PRESS_TIME);
  239.                                                         i++;
  240.                                           }  */
  241.                             }
  242.               }

  243.               return keyValue;   //将读取到键值的值返回
  244. }

  245. /**************************************************************
  246. 函数功能:定时器T0的中断服务程序
  247. **************************************************************/
  248. void Time0(void) interrupt 1 using 0 //“interrupt”声明函数为中断服务函数
  249. //其后的1为定时器T0的中断编号;0表示使用第0组工作寄存器
  250. {
  251.               bit RxTemp;
  252.               /*发送数据*/
  253.               if ((TxData & 0x01) == 1)
  254.               {
  255.                             if (Ti == 9)
  256.                             {
  257.                                           TxPort = (bit)(TxData & 0x8000);
  258.                                           TxPort2 = (bit)(TxData & 0x8000);
  259.                                           Ti = 0;
  260.                                           TxData = TxData & 0xfffe;
  261.                             }
  262.                             else
  263.                             {
  264.                                           TxPort = (bit)(TxData & 0x8000);
  265.                                           TxPort2 = (bit)(TxData & 0x8000);
  266.                                           TxData <<= 1;
  267.                                           TxData = TxData - 1;
  268.                                           Ti++;
  269.                             }
  270.               }
  271.               else
  272.               {
  273.                             TxPort = 1;
  274.                             TxPort2 = 1;
  275.               }
  276.               /*发送数据结束*/

  277.               /*接收数据*/
  278.                             RxTemp=RxPort&RxPort2;
  279.               if ((RxData & 0x8000) == 0x8000)//S1==1?
  280.               {
  281.                             if (Ri != 8)
  282.                             {
  283.                                           Ri++;
  284.                                           RxData <<= 1;
  285.                                           RxData = RxData | 0x8000;//S1置1
  286.                                           RxData = RxData | (unsigned int)RxTemp;
  287.                             }
  288.                             else
  289.                             {
  290.                                           RxData <<= 1;
  291.                                           RxData = RxData | (unsigned int)RxTemp;
  292.                                           Ri = 0;
  293.                                           RxData = RxData & 0x7fff;//S1置0
  294.                                           RxData = RxData | 0x4000;//S2置2
  295.                             }
  296.               }
  297.               else
  298.               {
  299.                             if (RxTemp == 0)
  300.                             {
  301.                                           if ((RxData & 0x4000) == 0)//S2==0?
  302.                                           {
  303.                                                         RxData = RxData | 0x8000;//S1置1
  304.                                           }
  305.                                           else
  306.                                           {
  307.                                                         errorFun(1);
  308.                                           }
  309.                             }
  310.               }
  311.               if(RxPort==0)
  312.                             TxPort2=0;
  313.               if(RxPort2==0)
  314.                             TxPort=0;
  315.               /*接收数据结束*/
  316.               TH0 = TIMEHIGH;
  317.               TL0 = TIMELOW;
  318. }

  319. void errorFun(unsigned char a)
  320. {
  321.               char i,s[]="Error";
  322.               WriteAddress(0x00);
  323.               for(i=0;i<16;i++)
  324.               {
  325.                             WriteData(32);            
  326.               }

  327.               WriteAddress(0x00);
  328.               i=0;
  329.               while(s[i]!=0)
  330.               {
  331.                             WriteData(s[i]);
  332.                             i++;
  333.                             delay(100);
  334.               }
  335.               WriteData('0'+a);
  336.               while(1);
  337. }

  338. void send(unsigned char* TxArray,unsigned char sendTo)
  339. {
  340.               unsigned char Tcount=0,i=0,TxD=0;
  341.               while (TxArray[Tcount] != 0)
  342.               {
  343.                             Tcount++;
  344.               }
  345.               TxD |= Tcount;
  346.               TxD<<=4;
  347.               sendTo <<= 2;
  348.               TxD |= sendTo;
  349.               TxD |= NAME_NUM;
  350.               while ((TxData & 0x0001) == 0x0001)//没发完
  351.                             ;
  352.               TxData = calculateTxData(TxD);
  353.               for (i = 0; i < Tcount; i++)
  354.               {
  355.                             while ((TxData & 0x0001) == 0x0001)//没发完
  356.                                           ;
  357.                             TxData = calculateTxData(TxArray[i]);
  358.               }
  359. }

  360. void receive(void)
  361. {
  362.               unsigned char RxArray[13] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  363.               unsigned char Rcount = 0, j = 0, sendTo = 0,temp=0;
  364.               if ((RxData & 0x4000) == 0x4000)//S2==1,数据待读取
  365.               {
  366.                             RxArray[0] = checkRxData();
  367.                             Rcount=RxArray[0] & 0xf0;
  368.                             Rcount>>=4;
  369.                             for (j = 1; j < Rcount+1; j++)
  370.                             {
  371.                                           while ((RxData & 0x4000) == 0x0000)//没有数据读取
  372.                                                         ;
  373.                                           RxArray[j] = checkRxData();
  374.                             }
  375.                             sendTo =RxArray[0] & 0x0c;
  376.                             sendTo>>=2;
  377.                             if (sendTo != NAME_NUM)
  378.                                           ;//send(RxArray + 1, sendTo);
  379.                             else
  380.                             {
  381.                                           WriteAddress(0x00);
  382.                                           switch (RxArray[0] & 0x03)
  383.                                           {
  384.                                           case 0:
  385.                                                         WriteData('C');
  386.                                                         WriteData('a');
  387.                                                         WriteData('r');
  388.                                                         WriteData('l');
  389.                                                         break;
  390.                                           case 1:
  391.                                                         WriteData('L');
  392.                                                         WriteData('i');
  393.                                                         WriteData('l');
  394.                                                         WriteData('y');
  395.                                                         break;
  396.                                           case 2:
  397.                                                         WriteData('J');
  398.                                                         WriteData('a');
  399.                                                         WriteData('c');
  400.                                                         WriteData('k');
  401.                                                         break;
  402.                                           case 3:
  403.                                                         WriteData('L');
  404.                                                         WriteData('i');
  405.                                                         WriteData('s');
  406.                                                         WriteData('a');
  407.                                                         break;
  408.                                           }
  409.                                           WriteData(':');
  410.                                           WriteData(32);
  411.                                           WriteData(32);
  412.                                           WriteData(32);
  413.                                           WriteData(32);
  414.                                           WriteData(32);
  415.                                           WriteData(32);
  416.                                           WriteData(32);
  417.                                           WriteData(32);
  418.                                           WriteData(32);
  419.                                           WriteData(32);
  420.                                           WriteData(32);
  421.                                           WriteAddress(0x05);
  422.                                           for (j = 1; j < Rcount + 1;j++)
  423.                                                         WriteData(RxArray[j]);
  424.                             }
  425.               }
  426. }
  427. 4.       parity.h

  428. #include  //  包含51单片机寄存器定义的头文件
  429. #include"myparity.h"
  430. #include"main.h"
  431. extern unsigned int RxData;
  432. //--定义全局变量--//
  433. unsigned char code DIG_PLACE[8] = {
  434.               0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };//位选控制   查表的方法控制
  435. unsigned char code DIG_CODE[17] = {
  436.               0x50, 0x5c, 0x50, 0x50, 0x79 };
  437. //Error的显示码
  438. unsigned char DisplayData[8];
  439. //用来存放要显示的8位数的值

  440. /*来自安驰的代码如下*/
  441. unsigned char checkRxData()
  442. {
  443.               unsigned int a = 1;  //用于移位后与运算,即为0000 0001
  444.               int i;
  445.               int UsefulData = RxData;
  446.               int bin[9] = { 0 };   //用于记录Rxdata转化为二进制后的数值
  447.               int num1 = 0;    //用于记录Rxdata中1的个数

  448.               UsefulData = UsefulData >> 1;              //先右移一位再与运算提取
  449.               UsefulData = UsefulData & 255;              //出原int型数据中有效的8位

  450.               for (i = 0; i<9; i++)
  451.               {
  452.                             bin[i] = RxData&a;
  453.                             RxData = RxData >> 1; //右移一位
  454.               }
  455.               for (i = 0; i<9; i++)
  456.               {
  457.                             if (bin[i] == 1)
  458.                             {
  459.                                           num1++;
  460.                             }
  461.               }
  462.               if (num1 % 2 == 0)
  463.               {
  464.                             errorFun(2);//奇偶校验错error2
  465.               }
  466.               return (char)UsefulData;
  467. }

  468. unsigned int calculateTxData(unsigned char UsefulData)
  469. {
  470.               unsigned int CutData;
  471.               unsigned int FinalData;
  472.               int flag = 0;   //判断1的个数            
  473.               int bin[8] = { 0 };
  474.               int num1 = 0;
  475.               int num = 0;
  476.               int i;
  477.               CutData = (int)UsefulData;
  478.               num = (int)UsefulData;
  479.               for (i = 0; i<8; i++)
  480.               {
  481.                             bin[i] = CutData & 1;
  482.                             CutData = CutData >> 1; //右移一位
  483.               }
  484.               for (i = 0; i<8; i++)
  485.               {
  486.                             if (bin[i] == 1)
  487. ……………………

  488. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


详细内容见附件:
多台单片机间网络的实现.docx (1.95 MB, 下载次数: 80)



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

使用道具 举报

沙发
ID:1 发表于 2017-5-29 03:17 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:171028 发表于 2020-3-26 19:05 | 只看该作者
哇!感谢,正在学习多机通信
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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