找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2640|回复: 3
收起左侧

51单片机CRC串行通信仿真与源码

[复制链接]
ID:294116 发表于 2018-3-19 17:05 | 显示全部楼层 |阅读模式
    我做的是两个单片机之间进行串行通信,用的89c52.通过按主机p27口"启动键",主机向从机发送一个四位数据,LED显示。从机经过CRC校验,如果接收到正确数据,与其相连的LED显示所接收的数据。如果经校验后接收错误,则四位LED显示0xFFFF。
    仿真时从机一点反应也没有,也许是我程序有问题,或通信协议编的不行。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载):
0.png 0.png

主机单片机源码:
  1. #define        _PPDATAT_H

  2. #include <reg51.h>
  3. #include <string.h>

  4. #define uchar unsigned char
  5. #define uint unsigned int

  6. /* 握手信号宏定义 */
  7. #define CALL 0x24                // 主机呼叫
  8. #define OK 0x00                        // 从机准备好

  9. #define MAXLEN 64                // 缓冲区最大长度

  10. uchar buf[MAXLEN];

  11. sbit  p00 = P0^0; sbit  p01 = P0^1; sbit  p02 = P0^2; sbit  p03 = P0^3;
  12. sbit p10=P1^0; sbit p11=P1^1; sbit p12=P1^2; sbit p13=P1^3;
  13. sbit p14=P1^4; sbit p15=P1^5; sbit p16=P1^6; sbit p17=P1^7;
  14. sbit p23 = P2^3;sbit p25 = P2^5;sbit p27 = P2^7;

  15. unsigned char a;
  16. unsigned char b;
  17. unsigned char c;
  18. unsigned char d;
  19. unsigned char in1,in2,in3,count;
  20. unsigned char j1,j2;
  21. unsigned char z1,z2,z3;
  22. unsigned int x=1234;
  23. bit qidong;

  24. void delay();

  25. //********************八段码*************************//
  26. code unsigned char LEDMAP[] = {
  27. 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
  28. 0x7f, 0x6f, 0x00,0x71//共阳显示码,分别显示0、1、2、3、4、5、6、7、8、9、灭、F。
  29. };
  30. //***********************显示码选择**********************//
  31. int DisplayLED(unsigned char j)
  32. {
  33.         unsigned int i=0;
  34.         unsigned int x1;
  35.         x1= LEDMAP[(i+j) & 0x0f];
  36.         return  x1;
  37. }
  38. //***********************转换*************************//
  39. void si()
  40. {
  41.     unsigned int M;
  42.         a=x%10;
  43.         M=x/10;
  44.         b=M%10;
  45.         M=M/10;
  46.         c=M%10;
  47.         d=M/10;//a取出第四位,b取出第三位,c取出第二位,d取出第一位
  48. }
  49. //***********************显示**********************//
  50. void  display()
  51. {
  52.     si();
  53.         P0=0xf7;
  54.         P1=DisplayLED(a);
  55.         delay();
  56.         P0=0xfb;
  57.         P1=DisplayLED(b);
  58.         delay();
  59.         P0=0xfd;
  60.         P1=DisplayLED(c);
  61.         delay();
  62.         P0=0xfe;
  63.         P1=DisplayLED(d);
  64.         delay();       
  65. }
  66. //************************扫描按键**********************//
  67. void timer0() interrupt 1 using 1
  68. {
  69.         in1=p23;
  70.         in2=p25;
  71.         in3=p27;
  72.         TH0=0xc3;
  73.         TL0=0x50;
  74.         count++;

  75.         if(in1==0)
  76.                 z1++;
  77.         if(in2==0)
  78.                 z2++;
  79.         if(in3==0)
  80.                 z3++;
  81.         if(count==40)
  82.         {
  83. //*************************x+***********************//
  84.         if((0<z1)&(z1<40))
  85.                         x++;
  86.                 if (z1==40)
  87.                         j1++;
  88.                 count=0;
  89.                 z1=0;
  90.                 if((0<j1)&(j1<6))
  91.                         x++;
  92.                 if((5<j1)&(j1<11))
  93.                         x=x+10;
  94.                 if(10<j1)
  95.                         x=x+100;
  96.                 if(in1==1)
  97.                         j1=0;
  98. //************************x-*******************//
  99.                 if((0<z2)&(z2<40))
  100.                         x--;
  101.                 if (z2==40)
  102.                         j2++;
  103.                 z2=0;
  104.                 if((0<j2)&(j2<6))
  105.                         x--;
  106.                 if((5<j2)&(j2<11))
  107.                         x=x-10;
  108.                 if(10<j2)
  109.                         x=x-100;
  110.                 if(in1==1)
  111.                         j2=0;
  112. //************************启动*******************//
  113.                 if(z3>5)
  114.                   qidong=1;
  115.          }  
  116. }
  117. void init()
  118. {
  119.      TMOD=0x21;                          //定时器0工作于方式1,定时器1工作于方式2
  120.         TH1 = 250;                          // 设置初值
  121.             TL1 = 250;

  122.             PCON = 0x80;                        // SMOD = 1
  123.             SCON = 0x50;                        //工作方式1,波特率9600bps,允许接收

  124.             ET0=1;                              //允许定时器0中断
  125.             TR0=1;                              //定时器0开始工作
  126.             TR1 = 1;                            //定时器1开始工作
  127.             EA=1;                               //打开所有中断

  128. }
  129. //*************************delay*********************//
  130. void delay()
  131. {
  132.         unsigned int i,n;
  133.         n=100;
  134.         for (i=0; i<n; i++) {}
  135. }
  136. //************************CRC计算****************************************//
  137. uint getcrc(uchar *s,uchar len)
  138. {
  139.   uint acc=0,i,j=0;
  140. while(len--)
  141. {
  142.     acc=acc^(*s++<<8);
  143.     for(i=0;i++<8;)
  144.       if(acc&0x8000)
  145.         acc=(acc<<1)^0x1021;
  146.       else
  147.         acc=acc<<1;
  148. }
  149. return(acc);
  150. }


  151. //************************串口通信程序****************************************//

  152. /* 发送数据函数 */
  153. void senddata(uchar *buf)
  154. {
  155.         uchar i;
  156.         uchar len;                                        // 保存数据长度
  157.         uint ecc;                                        // 保存校验字节

  158.         len = strlen(buf);                        // 计算要发送数据的长度

  159.         /* 发送数据长度 */
  160.         TI = 0;
  161.         SBUF = len;                                        // 发送长度
  162.         while(!TI);
  163.         TI = 0;
  164.     /* 发送数据和校验字节 */
  165.     ecc=getcrc(buf,len);
  166.     buf[len]=ecc/256;
  167.     buf[len+1]=ecc%256;
  168.         for (i=0;i<len+2;i++)
  169.         {
  170.                 SBUF = *buf;
  171.                 buf++;
  172.                 while(!TI);
  173.                 TI = 0;
  174.         }
  175. }       
  176. void tongxin()
  177. {
  178.         uchar i = 0;
  179.         uchar tmp;
  180.         /* 发送呼叫信号CALL并接收应答信息,如果没有接收到从机准备好的信号,则重新发送呼叫帧 */
  181.         while(tmp!=OK)                       
  182.         {
  183.                 /* 发送呼叫信号CALL */
  184.                 TI = 0;
  185.                 SBUF = CALL;
  186.                 while(!TI);
  187.                 TI = 0;

  188.                 /* 接收从机应答 */
  189.                 RI = 0;
  190.                 while(!RI);
  191.                 tmp = SBUF;
  192.                 RI = 0;               
  193.         }

  194.        
  195. }


  196. //*************************主函数***********************//
  197. void  main()
  198. {
  199.            init();
  200.            while(1)
  201.            {
  202.              display();
  203.              if(qidong==1)
  204.               {
  205.                si();
  206.                buf[0]=a;buf[1]=b;            
  207.                buf[2]=c;buf[3]=d;
  208.                senddata(buf);
  209.                tongxin();
  210.                qidong=0;     
  211.               }
  212.            }  
  213. }  
复制代码

丛机单片机源程序如下:
  1. #define        _PPDATAR_H

  2. #include <reg51.h>
  3. #include <string.h>

  4. #define uchar unsigned char
  5. #define uint unsigned int

  6. /* 握手信号宏定义 */
  7. #define CALL 0x24                // 主机呼叫
  8. #define OK 0x00                        // 从机准备好
  9. #define MAXLEN 64            // 缓冲区最大长度
  10. uchar buf[MAXLEN];
  11. sbit  p00 = P0^0; sbit  p01 = P0^1; sbit  p02 = P0^2; sbit  p03 = P0^3;
  12. sbit p10=P1^0; sbit p11=P1^1; sbit p12=P1^2; sbit p13=P1^3;
  13. sbit p14=P1^4; sbit p15=P1^5; sbit p16=P1^6; sbit p17=P1^7;
  14. bit err;
  15. void delay();

  16. //********************八段码*************************//
  17. code unsigned char LEDMAP[] = {
  18. 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
  19. 0x7f, 0x6f, 0x00,0x71//共阳显示码,分别显示0、1、2、3、4、5、6、7、8、9、灭、F。
  20. };
  21. //***********************显示码选择**********************//
  22. int DisplayLED(unsigned char j)
  23. {
  24.         unsigned int i=0;
  25.         unsigned int x1;
  26.         x1= LEDMAP[(i+j) & 0x0f];
  27.         return  x1;
  28. }

  29. //***********************显示**********************//
  30. void  display()
  31. {
  32.         P0=0xf7;
  33.         P1=DisplayLED(buf[0]);
  34.         delay();
  35.         P0=0xfb;
  36.         P1=DisplayLED(buf[1]);
  37.         delay();
  38.         P0=0xfd;
  39.         P1=DisplayLED(buf[2]);
  40.         delay();
  41.         P0=0xfe;
  42.         P1=DisplayLED(buf[3]);
  43.         delay();
  44. }
  45. //////////////////////显示FFFF//////////////////////////////
  46. void  display_f()
  47. {
  48.         P0=0xfe;
  49.         P1=DisplayLED(11);
  50.         delay();
  51.         P0=0xfd;
  52.         P1=DisplayLED(11);
  53.         delay();
  54.         P0=0xfb;
  55.         P1=DisplayLED(11);
  56.         delay();
  57.         P0=0xf7;
  58.         P1=DisplayLED(11);
  59.         delay();
  60. }
  61. //************************CRC计算****************************************//
  62. uint getcrc(uchar *s,uchar len)
  63. {
  64.   uint acc=0,i,j=0;
  65. while(len--)
  66. {
  67.     acc=acc^(*s++<<8);
  68.     for(i=0;i++<8;)
  69.       if(acc&0x8000)
  70.         acc=(acc<<1)^0x1021;
  71.       else
  72.         acc=acc<<1;
  73. }
  74. return(acc);
  75. }
  76. //*************************delay*********************//
  77. void delay()
  78. {
  79.         unsigned int i,n;
  80.         n=100;
  81.         for (i=0; i<n; i++) {}
  82. }
  83. //************************进行数据校验****************************************//
  84. int chkcrc(uchar *buf,uchar len)
  85.         {
  86.           uint strcrc;
  87.            strcrc=getcrc(buf,len);   //生成接收数据的CRC码
  88.            if(((0xff&buf[len])==(0xff&(strcrc/256)))&&((0xff&buf[len+1])==(0xff&(strcrc%256))))
  89.                                    //接收的CRC码和生成的CRC码进行比较
  90.              return(0);
  91.            else
  92.              return(-1);
  93.         }

  94. /* 接收数据函数 */
  95. bit recvdata(uchar *buf)
  96. {
  97.         uchar i;
  98.         uchar len;                                        // 保存数据长度
  99.         int ecc;                                        // 保存校验字节
  100.        
  101.         /* 接收数据长度字节 */
  102.         RI = 0;
  103.         while(!RI);
  104.         len = SBUF;
  105.         RI = 0;

  106.         /* 接收数据及校验字节 */
  107.         for (i=0;i<len+2;i++)
  108.         {
  109.                 while(!RI);
  110.                 *buf = SBUF;       
  111.                 RI = 0;       
  112.                 buf++;               
  113.         }
  114.         *buf = 0;                                        // 表示接收结束       
  115.       
  116.          /* 进行数据校验 */
  117.         ecc = chkcrc(buf,len);
  118.         if (ecc!=0)                                        // 如果校验错误
  119.        
  120.                       return 1;                        // 返回1表示校验错误
  121.         else
  122.                return 0;                                        // 校验成功,返回0
  123.       
  124. }

  125. void init_serial()
  126. {
  127.         TMOD = 0x20;                                // 定时器T1使用工作方式2
  128.         TH1 = 250;
  129.         TL1 = 250;
  130.         TR1 = 1;                                        // 开始计时
  131.         PCON = 0x80;                                // SMOD = 1
  132.         SCON = 0x50;                                // 工作方式1,波特率9600kbit/s,允许接收
  133. }

  134. /*串口通信程序 */
  135. void tongxin()
  136. {
  137.         uchar tmp=0;
  138.         init_serial();
  139.         EA = 0;                                        // 关闭所有中断

  140.        /* 如果接收到的数据不是CALL,则继续等待 */
  141.                 while (tmp!=CALL)
  142.                 {
  143.                         RI = 0;
  144.                         while(!RI)
  145.                         tmp = SBUF;
  146.                         RI = 0;
  147.                 }
  148.        
  149.                 /* 发送OK信号,表示从机可以接收数据 */
  150.                 TI = 0;                               
  151.                 SBUF = OK;
  152.                 while(!TI);
  153. ……………………

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

所有资料51hei提供下载:
CRC串行通信.zip (86.14 KB, 下载次数: 41)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:344633 发表于 2018-7-18 16:40 来自手机 | 显示全部楼层
谢谢楼主      
回复

使用道具 举报

ID:381488 发表于 2018-8-10 11:52 | 显示全部楼层
我想看看的
回复

使用道具 举报

ID:381488 发表于 2018-8-10 11:54 | 显示全部楼层
为什么不让下栽
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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