标题:
51单片机CRC串行通信仿真与源码
[打印本页]
作者:
留在夏天
时间:
2018-3-19 17:05
标题:
51单片机CRC串行通信仿真与源码
我做的是两个单片机之间进行串行通信,用的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
作者:
wangtianbao
时间:
2018-7-18 16:40
谢谢楼主
作者:
011010
时间:
2018-8-10 11:52
我想看看的
作者:
011010
时间:
2018-8-10 11:54
为什么不让下栽
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1