我做的是兩個單片機之間進行串行通信,用的89c52.通過按主機p27口"啟動鍵",主機向從機發送一個四位數據,LED顯示。從機經過CRC校驗,如果接收到正確數據,與其相連的LED顯示所接收的數據。如果經校驗后接收錯誤,則四位LED顯示0xFFFF。
仿真時從機一點反應也沒有,也許是我程序有問題,或通信協議編的不行。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載):
0.png (40.29 KB, 下載次數: 32)
下載附件
2018-3-19 19:06 上傳
0.png (57 KB, 下載次數: 21)
下載附件
2018-3-19 19:05 上傳
主機單片機源碼:
- #define _PPDATAT_H
- #include <reg51.h>
- #include <string.h>
- #define uchar unsigned char
- #define uint unsigned int
- /* 握手信號宏定義 */
- #define CALL 0x24 // 主機呼叫
- #define OK 0x00 // 從機準備好
- #define MAXLEN 64 // 緩沖區最大長度
- uchar buf[MAXLEN];
- sbit p00 = P0^0; sbit p01 = P0^1; sbit p02 = P0^2; sbit p03 = P0^3;
- sbit p10=P1^0; sbit p11=P1^1; sbit p12=P1^2; sbit p13=P1^3;
- sbit p14=P1^4; sbit p15=P1^5; sbit p16=P1^6; sbit p17=P1^7;
- sbit p23 = P2^3;sbit p25 = P2^5;sbit p27 = P2^7;
- unsigned char a;
- unsigned char b;
- unsigned char c;
- unsigned char d;
- unsigned char in1,in2,in3,count;
- unsigned char j1,j2;
- unsigned char z1,z2,z3;
- unsigned int x=1234;
- bit qidong;
- void delay();
- //********************八段碼*************************//
- code unsigned char LEDMAP[] = {
- 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
- 0x7f, 0x6f, 0x00,0x71//共陽顯示碼,分別顯示0、1、2、3、4、5、6、7、8、9、滅、F。
- };
- //***********************顯示碼選擇**********************//
- int DisplayLED(unsigned char j)
- {
- unsigned int i=0;
- unsigned int x1;
- x1= LEDMAP[(i+j) & 0x0f];
- return x1;
- }
- //***********************轉換*************************//
- void si()
- {
- unsigned int M;
- a=x%10;
- M=x/10;
- b=M%10;
- M=M/10;
- c=M%10;
- d=M/10;//a取出第四位,b取出第三位,c取出第二位,d取出第一位
- }
- //***********************顯示**********************//
- void display()
- {
- si();
- P0=0xf7;
- P1=DisplayLED(a);
- delay();
- P0=0xfb;
- P1=DisplayLED(b);
- delay();
- P0=0xfd;
- P1=DisplayLED(c);
- delay();
- P0=0xfe;
- P1=DisplayLED(d);
- delay();
- }
- //************************掃描按鍵**********************//
- void timer0() interrupt 1 using 1
- {
- in1=p23;
- in2=p25;
- in3=p27;
- TH0=0xc3;
- TL0=0x50;
- count++;
- if(in1==0)
- z1++;
- if(in2==0)
- z2++;
- if(in3==0)
- z3++;
- if(count==40)
- {
- //*************************x+***********************//
- if((0<z1)&(z1<40))
- x++;
- if (z1==40)
- j1++;
- count=0;
- z1=0;
- if((0<j1)&(j1<6))
- x++;
- if((5<j1)&(j1<11))
- x=x+10;
- if(10<j1)
- x=x+100;
- if(in1==1)
- j1=0;
- //************************x-*******************//
- if((0<z2)&(z2<40))
- x--;
- if (z2==40)
- j2++;
- z2=0;
- if((0<j2)&(j2<6))
- x--;
- if((5<j2)&(j2<11))
- x=x-10;
- if(10<j2)
- x=x-100;
- if(in1==1)
- j2=0;
- //************************啟動*******************//
- if(z3>5)
- qidong=1;
- }
- }
- void init()
- {
- TMOD=0x21; //定時器0工作于方式1,定時器1工作于方式2
- TH1 = 250; // 設置初值
- TL1 = 250;
- PCON = 0x80; // SMOD = 1
- SCON = 0x50; //工作方式1,波特率9600bps,允許接收
- ET0=1; //允許定時器0中斷
- TR0=1; //定時器0開始工作
- TR1 = 1; //定時器1開始工作
- EA=1; //打開所有中斷
- }
- //*************************delay*********************//
- void delay()
- {
- unsigned int i,n;
- n=100;
- for (i=0; i<n; i++) {}
- }
- //************************CRC計算****************************************//
- uint getcrc(uchar *s,uchar len)
- {
- uint acc=0,i,j=0;
- while(len--)
- {
- acc=acc^(*s++<<8);
- for(i=0;i++<8;)
- if(acc&0x8000)
- acc=(acc<<1)^0x1021;
- else
- acc=acc<<1;
- }
- return(acc);
- }
- //************************串口通信程序****************************************//
- /* 發送數據函數 */
- void senddata(uchar *buf)
- {
- uchar i;
- uchar len; // 保存數據長度
- uint ecc; // 保存校驗字節
- len = strlen(buf); // 計算要發送數據的長度
- /* 發送數據長度 */
- TI = 0;
- SBUF = len; // 發送長度
- while(!TI);
- TI = 0;
- /* 發送數據和校驗字節 */
- ecc=getcrc(buf,len);
- buf[len]=ecc/256;
- buf[len+1]=ecc%256;
- for (i=0;i<len+2;i++)
- {
- SBUF = *buf;
- buf++;
- while(!TI);
- TI = 0;
- }
- }
- void tongxin()
- {
- uchar i = 0;
- uchar tmp;
- /* 發送呼叫信號CALL并接收應答信息,如果沒有接收到從機準備好的信號,則重新發送呼叫幀 */
- while(tmp!=OK)
- {
- /* 發送呼叫信號CALL */
- TI = 0;
- SBUF = CALL;
- while(!TI);
- TI = 0;
- /* 接收從機應答 */
- RI = 0;
- while(!RI);
- tmp = SBUF;
- RI = 0;
- }
-
- }
- //*************************主函數***********************//
- void main()
- {
- init();
- while(1)
- {
- display();
- if(qidong==1)
- {
- si();
- buf[0]=a;buf[1]=b;
- buf[2]=c;buf[3]=d;
- senddata(buf);
- tongxin();
- qidong=0;
- }
- }
- }
復制代碼
叢機單片機源程序如下:
- #define _PPDATAR_H
- #include <reg51.h>
- #include <string.h>
- #define uchar unsigned char
- #define uint unsigned int
- /* 握手信號宏定義 */
- #define CALL 0x24 // 主機呼叫
- #define OK 0x00 // 從機準備好
- #define MAXLEN 64 // 緩沖區最大長度
- uchar buf[MAXLEN];
- sbit p00 = P0^0; sbit p01 = P0^1; sbit p02 = P0^2; sbit p03 = P0^3;
- sbit p10=P1^0; sbit p11=P1^1; sbit p12=P1^2; sbit p13=P1^3;
- sbit p14=P1^4; sbit p15=P1^5; sbit p16=P1^6; sbit p17=P1^7;
- bit err;
- void delay();
- //********************八段碼*************************//
- code unsigned char LEDMAP[] = {
- 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
- 0x7f, 0x6f, 0x00,0x71//共陽顯示碼,分別顯示0、1、2、3、4、5、6、7、8、9、滅、F。
- };
- //***********************顯示碼選擇**********************//
- int DisplayLED(unsigned char j)
- {
- unsigned int i=0;
- unsigned int x1;
- x1= LEDMAP[(i+j) & 0x0f];
- return x1;
- }
- //***********************顯示**********************//
- void display()
- {
- P0=0xf7;
- P1=DisplayLED(buf[0]);
- delay();
- P0=0xfb;
- P1=DisplayLED(buf[1]);
- delay();
- P0=0xfd;
- P1=DisplayLED(buf[2]);
- delay();
- P0=0xfe;
- P1=DisplayLED(buf[3]);
- delay();
- }
- //////////////////////顯示FFFF//////////////////////////////
- void display_f()
- {
- P0=0xfe;
- P1=DisplayLED(11);
- delay();
- P0=0xfd;
- P1=DisplayLED(11);
- delay();
- P0=0xfb;
- P1=DisplayLED(11);
- delay();
- P0=0xf7;
- P1=DisplayLED(11);
- delay();
- }
- //************************CRC計算****************************************//
- uint getcrc(uchar *s,uchar len)
- {
- uint acc=0,i,j=0;
- while(len--)
- {
- acc=acc^(*s++<<8);
- for(i=0;i++<8;)
- if(acc&0x8000)
- acc=(acc<<1)^0x1021;
- else
- acc=acc<<1;
- }
- return(acc);
- }
- //*************************delay*********************//
- void delay()
- {
- unsigned int i,n;
- n=100;
- for (i=0; i<n; i++) {}
- }
- //************************進行數據校驗****************************************//
- int chkcrc(uchar *buf,uchar len)
- {
- uint strcrc;
- strcrc=getcrc(buf,len); //生成接收數據的CRC碼
- if(((0xff&buf[len])==(0xff&(strcrc/256)))&&((0xff&buf[len+1])==(0xff&(strcrc%256))))
- //接收的CRC碼和生成的CRC碼進行比較
- return(0);
- else
- return(-1);
- }
- /* 接收數據函數 */
- bit recvdata(uchar *buf)
- {
- uchar i;
- uchar len; // 保存數據長度
- int ecc; // 保存校驗字節
-
- /* 接收數據長度字節 */
- RI = 0;
- while(!RI);
- len = SBUF;
- RI = 0;
- /* 接收數據及校驗字節 */
- for (i=0;i<len+2;i++)
- {
- while(!RI);
- *buf = SBUF;
- RI = 0;
- buf++;
- }
- *buf = 0; // 表示接收結束
-
- /* 進行數據校驗 */
- ecc = chkcrc(buf,len);
- if (ecc!=0) // 如果校驗錯誤
-
- return 1; // 返回1表示校驗錯誤
- else
- return 0; // 校驗成功,返回0
-
- }
- void init_serial()
- {
- TMOD = 0x20; // 定時器T1使用工作方式2
- TH1 = 250;
- TL1 = 250;
- TR1 = 1; // 開始計時
- PCON = 0x80; // SMOD = 1
- SCON = 0x50; // 工作方式1,波特率9600kbit/s,允許接收
- }
- /*串口通信程序 */
- void tongxin()
- {
- uchar tmp=0;
- init_serial();
- EA = 0; // 關閉所有中斷
- /* 如果接收到的數據不是CALL,則繼續等待 */
- while (tmp!=CALL)
- {
- RI = 0;
- while(!RI)
- tmp = SBUF;
- RI = 0;
- }
-
- /* 發送OK信號,表示從機可以接收數據 */
- TI = 0;
- SBUF = OK;
- while(!TI);
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
CRC串行通信.zip
(86.14 KB, 下載次數: 41)
2018-3-19 17:05 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|