我做的是两个单片机之间进行串行通信,用的89c52.通过按主机p27口"启动键",主机向从机发送一个四位数据,LED显示。从机经过CRC校验,如果接收到正确数据,与其相连的LED显示所接收的数据。如果经校验后接收错误,则四位LED显示0xFFFF。
仿真时从机一点反应也没有,也许是我程序有问题,或通信协议编的不行。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载):
主机单片机源码:
- #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)
|