一、功能 主體功能:三臺單片機之間兩兩互相通信,為此,我們將其擬人化,以三個主人公Jack、Carl、Lily之間的交流來演示。具體過程如下: ①初始狀態(從上至下分別為Jack、Lily、Carl):
1.001.jpg (59.86 KB, 下載次數: 185)
下載附件
2017-5-29 03:14 上傳
②Lily編輯“HELLO!”的字符串準備發送給Jack:
1.002.jpg (28.38 KB, 下載次數: 175)
下載附件
2017-5-29 03:14 上傳
③Lily按下發送后Jack的接收結果:
1.003.jpg (51.82 KB, 下載次數: 169)
下載附件
2017-5-29 03:14 上傳
④Carl編輯“Hi!”發送給Lily同時Lily接收:
1.004.jpg (21.76 KB, 下載次數: 183)
下載附件
2017-5-29 03:14 上傳
⑤Jack編輯“HOW ARE U”發送給Carl同時Carl接收:
1.005.jpg (45.5 KB, 下載次數: 188)
下載附件
2017-5-29 03:14 上傳
⑥特殊情況:當傳送過來的數據經奇偶校驗出錯后給出報錯提示:
1.006.jpg (53.21 KB, 下載次數: 168)
下載附件
2017-5-29 03:14 上傳
二、 網絡的設計物理層: 傳輸介質: 采用兩條杜邦線連接單片機的兩個io口,一個io口定時變換高低電平輸出數據,另一個io口定時檢測電平高低來讀取數據,實現了全雙工通訊。 每臺單片機都有2對(4個)io口可以發送接受數據,這為多臺機器組成網絡提供了基礎。 多臺單片機連接方式:
0.png (5.33 KB, 下載次數: 184)
下載附件
2017-5-29 03:15 上傳
我們用3臺單片機組成了一條線似的結構,實際上這個網絡還可以在邊上擴展延長,這個網絡中不存在主機,每臺機器都是平等的。 每臺單片機收到信息后,都會將信息從另一對io口發出。每臺單片機發送給信息時候,也會將信息從兩對io口同時發出,因此一旦有信息發送,信息會傳播到整個網絡。 編碼技術:采用不歸零電平編碼方式(NRZ-L),高電平代表1,低電平代表0,每一bit數據的持續時間是31.108ms。由于每bit的持續時間決定了傳輸速率,因此傳輸數據可以通過簡單修改宏定義來實現,不過隨著傳輸速率的提高,出錯率會增加。
傳輸協議:采用異步傳輸方式,每次傳輸一個bit。傳輸數據的格式如下
數據鏈路層: 成幀技術采用的是字符計數成幀技術,首部的高4位代表接下來要發送的字符數 數據是由誰發出,數據發給誰: 這部分功能也是由字符首部來完成,首部的結構如下: 如上圖所示,這個首部代表接下來還要發送2個字符,目標地址是0,源地址是1。
三、 部分代碼3臺單片機的代碼都是相同的,連接外部按鍵和顯示器的引腳差別可以通過修改宏定義來適配。因此只列出一臺單片機的代碼 1. main.h- #ifndef _main_h_
- #define _main_h_
-
- #define MYNAME "Jack"
- #define NAME_NUM 2
- #define BUTTON_IO P3
- #define PRESS_LEFT 0x0E//k30
- #define PRESS_RIGHT 0x0D //k31
- #define CHANGE 0x0B //k32
- #define SEND 0x07 //k33
- #define PRESS_TIME 5000//按鍵消去抖動時間
- #define ASCII 32
- #define GPIO_KEY P3 //獨立鍵盤用P1口
- //carl Lily Jack Lisa
-
- void send(unsigned char* TxArray,unsigned char sendTo);
- void receive(void);
- void errorFun(unsigned char a);
- unsigned char Key_Scan();
- Show_Name(int sendTo); //顯示名字
- #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- #include // 包含51單片機寄存器定義的頭文件
- #include"1602LCD.h"
- #include"myParity.h"
- #include"main.h"
-
- sbit TxPort = P1 ^ 0;
- sbit RxPort = P1 ^ 1;
- sbit TxPort2 = P1 ^ 2;
- sbit RxPort2 = P1 ^ 3;
- #define TIMEHIGH 0xD0;
- #define TIMELOW 0x00;
- unsigned char i;
- unsigned int TxData;
- unsigned char Ti;
- unsigned int RxData;
- unsigned char Ri;
- unsigned char code tab[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90 }; //共陽數碼管 0-9
-
-
- /**************************************************************
- 函數功能:主函數
- **************************************************************/
- void main(void)
- {
- unsigned char TxArray[13] = {0,0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0 };
- unsigned char position = 0;
- unsigned char sendTo = 0;
-
- unsigned char keyNum; //獲取鍵值
- char a; //循環變量
- char flag=0;
- RxData = 0;
- TxData = 0;
- Ti = 0;
- Ri = 0;
- i = 0;
- P1 = 0xff;
- P3=0xff;
- P3=0xff;
-
- EA = 1; //開總中斷
- ET0 = 1; //定時器T0中斷允許
- TMOD = 0x01; //使用定時器T0的模式1
- TH0 = TIMEHIGH;
- TL0 = TIMELOW;
- TR0 = 1; //啟動定時器T0
- LcdInt();
- delay(1000);
-
- Write_com(0x01);//清顯示:清屏幕指令
- WriteAddress(0x40);
- WriteAddress(0x40);
- for(a=0;a<10;a++)
- {
- WriteAddress(0x40+a);
- WriteData(ASCII+TxArray[a]);
- }
- WriteAddress(0x4A);
- WriteData('-');
- WriteAddress(0x4B);
- WriteData('>');
- WriteAddress(0x40);
- sendTo=NAME_NUM+1;
- if(NAME_NUM>1)
- sendTo=0;
- Show_Name(sendTo);
- WriteAddress(0x40);
- while (1)//無限循環等待中斷
- {
- keyNum = Key_Scan(); //掃描鍵盤
- switch (keyNum&0x0F)
- {
- case(PRESS_LEFT) :
- if( (position>=0) && (position<10) )
- {
- WriteAddress(0x40+position);
- if(TxArray[position]<32)
- TxArray[position]=128;
- else
- TxArray[position]--;
- WriteData(TxArray[position]);
- WriteAddress(0x40+position);
- }
- else if( (position==10) || (position==11) )
- {
- for(a=0;a<10;a++)
- {
- TxArray[a]=0;
- WriteAddress(0x40+a);
- WriteData(0);
- }
- WriteAddress(0x40);
- position=0;
- }
- else
- {
- if(sendTo>0)
- {
- sendTo--;
- }
- else
- {
- sendTo=3;
- }
- Show_Name(sendTo);
- }
- break;
- case(PRESS_RIGHT) :
- if( (position>=0) && (position<10) )
- {
- WriteAddress(0x40+position);
- if(TxArray[position]<32)
- TxArray[position]=65;
- else if(TxArray[position]>128)
- TxArray[position]=32;
- else
- TxArray[position]++;
- WriteData(TxArray[position]);
- WriteAddress(0x40+position);
- }
- else if( (position==10) || (position==11) )
- {
- for(a=0;a<10;a++)
- {
- TxArray[a]=0;
- WriteAddress(0x40+a);
- WriteData(ASCII);
- }
- WriteAddress(0x40);
- position=0;
- }
- else
- {
- if(sendTo<3)
- {
- sendTo++;
- }
- else
- {
- sendTo=0;
- }
- Show_Name(sendTo);
- }
- break;
- case(CHANGE) :
- if(position<12)
- {
- position++;
- }
- else
- {
- position=0;
- }
- WriteAddress(0x40+position);
- break;
- case(SEND) :
- flag=0;
- for(a=9;a>=0;a--)
- {
- if(flag==1&&TxArray[a]==0)
- TxArray[a]=32;
- else if(TxArray[a]!=0)
- flag=1;
- }
- send(TxArray,sendTo);
- break;
- default:
- break;
- }
- receive();
- }
-
- }
-
- Show_Name(int sendTo)
- {
- if(sendTo==0)
- {
- WriteAddress(0x4C);
- WriteData('C');
- WriteAddress(0x4D);
- WriteData('a');
- WriteAddress(0x4E);
- WriteData('r');
- WriteAddress(0x4F);
- WriteData('l');
- WriteAddress(0x4C);
- }
- else if(sendTo==1)
- {
- WriteAddress(0x4C);
- WriteData('L');
- WriteAddress(0x4D);
- WriteData('i');
- WriteAddress(0x4E);
- WriteData('l');
- WriteAddress(0x4F);
- WriteData('y');
- WriteAddress(0x4C);
- }
- else if(sendTo==2)
- {
- WriteAddress(0x4C);
- WriteData('J');
- WriteAddress(0x4D);
- WriteData('a');
- WriteAddress(0x4E);
- WriteData('c');
- WriteAddress(0x4F);
- WriteData('k');
- WriteAddress(0x4C);
- }
- else
- {
- WriteAddress(0x4C);
- WriteData('L');
- WriteAddress(0x4D);
- WriteData('i');
- WriteAddress(0x4E);
- WriteData('s');
- WriteAddress(0x4F);
- WriteData('a');
- WriteAddress(0x4C);
- }
- }
- /*******************************************************************************
- * 函 數 名 : Key_Scan()
- * 函數功能 : 掃描鍵盤
- * 輸 入 : 無
- * 輸 出 : 讀取到的鍵值
- *******************************************************************************/
-
- unsigned char Key_Scan()
- {
- unsigned char keyValue = 0 , i; //保存鍵值
-
- //--檢測按鍵1--//
- if (GPIO_KEY != 0xFF) //檢測按鍵是否按下
- {
- delay(PRESS_TIME); //消除抖動
-
- if (GPIO_KEY != 0xFF) //再次檢測按鍵是否按下
- {
- keyValue = GPIO_KEY;
- /* i = 0;
- while ((i<50) && (GPIO_KEY != 0xFF)) //檢測按鍵是否松開
- {
- delay(PRESS_TIME);
- i++;
- } */
- }
- }
-
- return keyValue; //將讀取到鍵值的值返回
- }
-
- /**************************************************************
- 函數功能:定時器T0的中斷服務程序
- **************************************************************/
- void Time0(void) interrupt 1 using 0 //“interrupt”聲明函數為中斷服務函數
- //其后的1為定時器T0的中斷編號;0表示使用第0組工作寄存器
- {
- bit RxTemp;
- /*發送數據*/
- if ((TxData & 0x01) == 1)
- {
- if (Ti == 9)
- {
- TxPort = (bit)(TxData & 0x8000);
- TxPort2 = (bit)(TxData & 0x8000);
- Ti = 0;
- TxData = TxData & 0xfffe;
- }
- else
- {
- TxPort = (bit)(TxData & 0x8000);
- TxPort2 = (bit)(TxData & 0x8000);
- TxData <<= 1;
- TxData = TxData - 1;
- Ti++;
- }
- }
- else
- {
- TxPort = 1;
- TxPort2 = 1;
- }
- /*發送數據結束*/
-
- /*接收數據*/
- RxTemp=RxPort&RxPort2;
- if ((RxData & 0x8000) == 0x8000)//S1==1?
- {
- if (Ri != 8)
- {
- Ri++;
- RxData <<= 1;
- RxData = RxData | 0x8000;//S1置1
- RxData = RxData | (unsigned int)RxTemp;
- }
- else
- {
- RxData <<= 1;
- RxData = RxData | (unsigned int)RxTemp;
- Ri = 0;
- RxData = RxData & 0x7fff;//S1置0
- RxData = RxData | 0x4000;//S2置2
- }
- }
- else
- {
- if (RxTemp == 0)
- {
- if ((RxData & 0x4000) == 0)//S2==0?
- {
- RxData = RxData | 0x8000;//S1置1
- }
- else
- {
- errorFun(1);
- }
- }
- }
- if(RxPort==0)
- TxPort2=0;
- if(RxPort2==0)
- TxPort=0;
- /*接收數據結束*/
- TH0 = TIMEHIGH;
- TL0 = TIMELOW;
- }
-
- void errorFun(unsigned char a)
- {
- char i,s[]="Error";
- WriteAddress(0x00);
- for(i=0;i<16;i++)
- {
- WriteData(32);
- }
-
- WriteAddress(0x00);
- i=0;
- while(s[i]!=0)
- {
- WriteData(s[i]);
- i++;
- delay(100);
- }
- WriteData('0'+a);
- while(1);
- }
-
- void send(unsigned char* TxArray,unsigned char sendTo)
- {
- unsigned char Tcount=0,i=0,TxD=0;
- while (TxArray[Tcount] != 0)
- {
- Tcount++;
- }
- TxD |= Tcount;
- TxD<<=4;
- sendTo <<= 2;
- TxD |= sendTo;
- TxD |= NAME_NUM;
- while ((TxData & 0x0001) == 0x0001)//沒發完
- ;
- TxData = calculateTxData(TxD);
- for (i = 0; i < Tcount; i++)
- {
- while ((TxData & 0x0001) == 0x0001)//沒發完
- ;
- TxData = calculateTxData(TxArray[i]);
- }
- }
-
- void receive(void)
- {
- unsigned char RxArray[13] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char Rcount = 0, j = 0, sendTo = 0,temp=0;
- if ((RxData & 0x4000) == 0x4000)//S2==1,數據待讀取
- {
- RxArray[0] = checkRxData();
- Rcount=RxArray[0] & 0xf0;
- Rcount>>=4;
- for (j = 1; j < Rcount+1; j++)
- {
- while ((RxData & 0x4000) == 0x0000)//沒有數據讀取
- ;
- RxArray[j] = checkRxData();
- }
- sendTo =RxArray[0] & 0x0c;
- sendTo>>=2;
- if (sendTo != NAME_NUM)
- ;//send(RxArray + 1, sendTo);
- else
- {
- WriteAddress(0x00);
- switch (RxArray[0] & 0x03)
- {
- case 0:
- WriteData('C');
- WriteData('a');
- WriteData('r');
- WriteData('l');
- break;
- case 1:
- WriteData('L');
- WriteData('i');
- WriteData('l');
- WriteData('y');
- break;
- case 2:
- WriteData('J');
- WriteData('a');
- WriteData('c');
- WriteData('k');
- break;
- case 3:
- WriteData('L');
- WriteData('i');
- WriteData('s');
- WriteData('a');
- break;
- }
- WriteData(':');
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteData(32);
- WriteAddress(0x05);
- for (j = 1; j < Rcount + 1;j++)
- WriteData(RxArray[j]);
- }
- }
- }
- 4. parity.h
- #include // 包含51單片機寄存器定義的頭文件
- #include"myparity.h"
- #include"main.h"
- extern unsigned int RxData;
- //--定義全局變量--//
- unsigned char code DIG_PLACE[8] = {
- 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };//位選控制 查表的方法控制
- unsigned char code DIG_CODE[17] = {
- 0x50, 0x5c, 0x50, 0x50, 0x79 };
- //Error的顯示碼
- unsigned char DisplayData[8];
- //用來存放要顯示的8位數的值
-
- /*來自安馳的代碼如下*/
- unsigned char checkRxData()
- {
- unsigned int a = 1; //用于移位后與運算,即為0000 0001
- int i;
- int UsefulData = RxData;
- int bin[9] = { 0 }; //用于記錄Rxdata轉化為二進制后的數值
- int num1 = 0; //用于記錄Rxdata中1的個數
-
- UsefulData = UsefulData >> 1; //先右移一位再與運算提取
- UsefulData = UsefulData & 255; //出原int型數據中有效的8位
-
- for (i = 0; i<9; i++)
- {
- bin[i] = RxData&a;
- RxData = RxData >> 1; //右移一位
- }
- for (i = 0; i<9; i++)
- {
- if (bin[i] == 1)
- {
- num1++;
- }
- }
- if (num1 % 2 == 0)
- {
- errorFun(2);//奇偶校驗錯error2
- }
- return (char)UsefulData;
- }
-
- unsigned int calculateTxData(unsigned char UsefulData)
- {
- unsigned int CutData;
- unsigned int FinalData;
- int flag = 0; //判斷1的個數
- int bin[8] = { 0 };
- int num1 = 0;
- int num = 0;
- int i;
- CutData = (int)UsefulData;
- num = (int)UsefulData;
- for (i = 0; i<8; i++)
- {
- bin[i] = CutData & 1;
- CutData = CutData >> 1; //右移一位
- }
- for (i = 0; i<8; i++)
- {
- if (bin[i] == 1)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
詳細內容見附件:
多臺單片機間網絡的實現.docx
(1.95 MB, 下載次數: 81)
2017-5-27 20:03 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|