西南科技大学工业数据通信 现场总线期末作业题.docx
《西南科技大学工业数据通信 现场总线期末作业题.docx》由会员分享,可在线阅读,更多相关《西南科技大学工业数据通信 现场总线期末作业题.docx(19页珍藏版)》请在冰豆网上搜索。
![西南科技大学工业数据通信 现场总线期末作业题.docx](https://file1.bdocx.com/fileroot1/2022-12/12/bd237b31-639a-4299-bb94-9dc71ef5931b/bd237b31-639a-4299-bb94-9dc71ef5931b1.gif)
西南科技大学工业数据通信现场总线期末作业题
现场总线技术及其应用
期末作业
课程名称:
现场总线技术及其应用
姓名:
学号:
班级:
电气09
任课教师:
张海涛
信息工程学院
2012年5月15日
1、为了实现数据的可靠传输,在通信过程中常采取一些差错检测措施。
常用的检错方式有奇偶校验、求和校验、纵向冗余校验、循环冗余校验等。
说简要明这些检错方式的原理及其实现方法,并编写程序代码(C语言编写)。
包括海明码纠错算法的实现过程(C语言编程)(20分)
答:
1、奇偶校验:
在奇偶校验中,一个单一的校验位被加在每个单位数据域上,使得包括该校验位在内的各单位数据域中1的个数是偶数(即为偶校验),或者为奇数(奇校验)。
在接收端采用同一种校验方式检查接收到的数据和校验位,判断该传输过程是否出错,如果出现1的个数为偶数,就表明传输的过程是正确的,数据可用。
若在某个数据域中1的个数不是偶数,就说明传输过程出现错误。
奇偶校验程序为:
#include
#include
#defineset_bit(x,y)((x)|=(0x01<<(y)))//置位x的y位
#defineclr_bit(x,y)((x)&=(~(0x01<<(y))))//清零x的y位
unsignedcharparity_check(unsignedcharData)
{inti;
unsignedcharCount=0;//单个数据类型内1的个数
for(i=0;i<8;i++)
{
if(Data&0x01)
{
Count++;}
Data>>=1;}
return(Count&0x01);}
intmain()
{
unsignedcharData[200];
unsignedcharParity_bit[25]={0};
inti,length_Data,length_Parity_bit;
printf("\n*********以下数据均以字符串形式输入************\n");
printf("请输入数据:
");
gets(Data);
length_Data=strlen(Data);
printf("原始数据(字符串):
(%d字节)\n",length_Data);
for(i=0;i{printf("%c",Data[i]);
if(parity_check(Data[i]))
{
set_bit(Parity_bit[i/8],i%8);
}
else
{
clr_bit(Parity_bit[i/8],i%8);
}
}
length_Parity_bit=strlen(Parity_bit);
printf("\n校验码(十六进制):
(%d字节)\n",length_Parity_bit);
for(i=0;i{printf("%4x",Parity_bit[i]);
}
printf("\n****************偶校验*********\n");
return0;
}
2、求和校验:
在求和校验中,在发送端将数据分为k段,每段均为等长的n比特。
将分段1与分段2做求和操作,再逐一与分段3至k做求和操作,得到长度为n比特的求和结果,将该结果取反后作为校验和放在数据块后面,与数据块一起发送到接收端。
在接收端对接收到的、包括校验和在内的所有k+1段数据求和,如果结果为零,就认为传输过程没有错误,所传数据正确,否则认为传输的数据出现错误。
求和校验的C语言程序为:
#include
#include
unsignedcharsum_checking(unsignedchar*data,intn)
{inti;
charsum=0;
for(i=0;i{sum+=*(data+i);
}
sum=~sum+1;
returnsum;
}
voidmain()
{inti,n;
unsignedcharsum=0;
unsignedchardata[100];
printf("\n*******************以下数据均以字符串形式输入*********************\n");
printf("请输入数据:
");
gets(data);
n=strlen(data);
data[n]=sum_checking(data,n);
printf("K+1段数据(%d+1字节)",n);
for(i=0;i{
printf("%c",data[i]);
}
printf("\n校验和:
(十六进制:
%x)(字符数据:
%c)\n",data[n],data[n]);
}
3、纵向冗余校验:
纵向冗余校验按预定的数量将多个单位数据域组成一个数据块。
首先每个单位数据域各自采用奇偶校验,得到各单位数据域的冗余校验位。
再将各单位数据域的对应位分别做奇偶校验。
并将所有位置奇偶校验得到的冗余校验位组成一个新的数据单元,附加在数据块的最后面发送出去。
采用相同的校验方法,在接受方如果发现一个冗余校验位出现错误,不管是哪个单位数据域的校验位,还是附加在数据块后面的信数据块的冗余位都认为是发送出错
纵向冗余校验程序:
BYTEGetCheckCode(constchar*pSendBuf,intnEnd)//获得校验码
{
BYTEbyLrc=0;
charpBuf[4];
intnData=0;
for(i=1;i{
//每两个需要发送的ASCII码转化为一个十六进制数
pBuf[0]=pSendBuf[i];
pBuf[1]=pSendBuf[i+1];
pBuf[2]='\0';
scanf(pBuf,"%x",&nData);
byLrc+=nData;
}
byLrc=~byLrc;
byLrc++;
returnbyLrc;
}
4、循环冗余校验:
循环冗余校验对传输序列进行一次规定的除法操作,将除法操作的余数加附加到传输信息的后边。
在接收端,也对收到的数据做相同的除法。
如果接收端除法得到的结果其余数不为零,就表明在传输过程中出现了数据错误。
基于除法的循环冗余校验,其计算量大于奇偶与求和求和校验,其差错检测的有效性也较高。
循环冗余校验的C语言程序为:
CRC16(unsignedcharbuf[],intlgn)
{
unsignedcharparity_tab[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsignedchara,c,b,d,e,e1,e2;
inti,j;
lgn=2;
a=0xff;
c=0xff;
b=0xff;
d=0xff;
for(i=0;i{
e=buf[i];
a=a^a;
c=c^e;
e2=0;
for(j=0;j<8;j)
{
if((c&parity_tab[j])!
=0)
e2=1;
}
if((e2&0x01)!
=0)
a=0x07;
b=c;
if((a&0x01)!
=0)
e=1;
else
e=0;
if((b&0x01)!
=0)
e1=1;
else
e1=0;
b=b>>1;
a=a>>1;
if(e==1)
b=b|0x80;
if(e1==1)
a=a|0x80;
b=b^c;
if((a&0x01)!
=0)
e=1;
else
e=0;
if((b&0x01)!
=0)
e1=1;
else
e1=0;
b=b>>1;
a=a>>1;
if(e==1)
b=b|0x80;
if(e1==1)
a=a|0x80;
a=a^d;
c=a;
d=b;
}
buf[lgn-2]=c;
buf[lgn-1]=d;
}
5、海明码纠错算法的实现过程:
海明校验的实现原理实现原理:
在数据中加人几个校验位,将数据代码的码距均匀拉大,将数据按某种规律分成若干组作为奇偶检测,就能提供多位检错信息,当某一位出错后,就会引起有关的几个校验位的值发生变化,从而可发现出错,指出哪一位出错.为进一步自动纠错提供了依据.要增多校验位才能分成多组检测,所以说海明检验的实质是多重奇偶校验
海明码纠错算法的实现过程程序:
#include
#include
#include
#include
#defineM100//最大的数据位数
#defineN50//最大的校验位数
structHamming{
intflag;
intvalue;//海明码的数值
}H[M];//存放海明码信息
intP[N];//存放校验位信息
intC[N];//存放检验位信息
intm[M+N];//存放需要纠正的海明码
intDC=0,PC=0,EC=0,HC=0,ERROR=0,ERROR1=0;//DC是数据的位数,PC是校验位的位数,不能在此更改这些数据的值,否则出错
showInf(){//显示信息
printf("-------------------------------------------------------------------------------\n");
printf("*****************************************海明码********************************\n");
printf("***************************************输入格式如下:
***************************\n");
printf("*****************************如果要输入1101,需输入1101-1******************\n");
printf("-----------------------------选择操作:
----------------------------------------\n");
printf("1输入数据后生成海明码2输入海明码3清屏4纠正海明码5返回主页6结束程序\n\n");
printf("请选择操作,只能输入一个数:
");
}
intinputData(intchoice){//输入数据或海明码,参数是1就表示输入的是数据,参数是2就表示输入的是海明码。
返回-1就表示输入数据错误。
intdata,i=1;
scanf("%d",&data);
if(data!
=0&&data!
=1){
system("cls");
printf("\n\n提示信息:
输入格式不正确,第一位只能是0或1,请重新选择操作\n\n\n");
return-1;
}
DC=1;
PC=1;
while(data!
=-1){
if(pow(2,PC-1)!
=i){//存放数据值到海明码结构体中
H[i].flag=0;
H[i].value=data;
m[i]=data;
DC++;
scanf("%d",&data);
}
elseif(pow(2,PC-1)==i&&choice==1){
H[i].flag=1;
PC++;
}
if((pow(2,PC-1)==i)&&choice==2){//把海明码中的校验位放到校验位数组中,以便用这个校验位和利用数据生成的校验位异或来计算哪一位出错
H[i].flag=1;
P[PC++]=data;
m[i]=data;
scanf("%d",&data);
}
i++;
}
DC--;
PC--;
if(PC+DC<3)
ERROR=2;
return;
}
caculateHammingCode(){//根据海明码结构体中数据位的数据值计算海明码,并把正确的海明码放到海明码结构体中。
intm,j,k,temp=0;
for(m=3;m<=DC+PC;m++){
temp=0;
if(H[m].flag==0){
for(j=PC;j>=1;j--){
k=(int)pow(2,j-1);
if(kH[k].value=H[k].value^H[m].value;
temp=k;
break;
}
}
for(k=j-1;k>=1;k--){
if(H[k].flag==1){
if(temp+pow(2,k-1)==m){
H[k].value=H[k].value^H[m].value;
break;
}
if(temp+pow(2,k-1)H[k].value=H[k].value^H[m].value;
temp=temp+pow(2,k-1);
}
}
}
}
}
}
caculateC(intpc){//计算检验位的值,并放到检验位的数组中。
接受的参数是校验位的个数
inti,k;
for(i=1;i<=pc;i++){
k=(int)pow(2,i-1);
C[i]=P[i]^H[k].value;
}
}
initial(){//使海明码结构体清零
inti;
for(i=1;i<=DC+PC;i++){
H[i].value=0;
}
}
showHammingCode(intdc,intpc){//打印海明码结构体中的值。
接受的参数是dc为数据位的个数,pc为校验位的个数。
inti;
printf("\n\n生成的海明码为:
\n");
for(i=1;i<=dc+pc;i++){
printf("第%d位:
",i);
printf("%d\n",H[i].value);
}
printf("\n");
}
judge(intpc){//判断出哪一位出错,并打印出这一位是数据位还是校验位
inti,result=0,flag=0;
//system("cls");
for(i=1;i<=pc;i++){
if(C[i]==1)flag++;
}
for(i=1;i<=pc;i++){
if(flag==0)
result=result+C[i]*pow(2,pc-i);
elseresult=result+C[i]*pow(2,i-1);
}
if(result!
=0){
printf("\n\n\n提示信息:
第%d位出错,",result);
EC=result;
if(flag>=2)
printf("这一位是数据位!
\n\n");
elseprintf("这一位是校验位!
\n\n");
}
elseprintf("\n\n提示信息:
海明码正确!
\n\n\n");
}
mend(mc){//纠正错误的海明码。
并打印出纠正前错误的海明码和纠正后正确的海明码
inti,k=0,p=1;
if(EC==0){
printf("\n\n提示信息:
海明码正确或者已经纠正或者海明码为空,请重新选择操作\n\n\n");
return;
}
system("cls");
printf("\n提示信息:
海明码第%d位有错误\n\n",EC);
printf("\n输入的错误的海明码是:
\n\n");
for(i=1;i<=mc;i++)
printf("第%d位%d\n",i,m[i]);
m[EC]=!
m[EC];
printf("\n\n纠正后的正确的海明码是:
\n\n");
for(i=1;i<=mc;i++)
printf("第%d位%d\n",i,m[i]);
}
run(intcommand){//运行不同的操作模式,command为1表示输入的数据位,command为2表示输入的是海明码
inti;
if(command==1){//输入的是数据
printf("\n\n请输入数据,以-1做结束符:
");
i=inputData
(1);//返回输入的数据位数
if(i==-1)return;
caculateHammingCode();
showHammingCode(DC,PC);
initial();
HC=PC+DC;
DC=0;
PC=0;
}
else{//输入的是海明码
printf("\n\n请输入海明码,以-1做结束符,只能有一位错误:
");
i=inputData
(2);
if(i==-1)return;
caculateHammingCode();
if(ERROR==1||ERROR==2){
system("cls");
printf("\n\n提示信息:
输入格式不正确,第一位只能是0或1,并且输入的位数要大于等于3.请重选操作\n\n\n");
ERROR=0;
PC=0;
return;
}
caculateC(PC);
judge(PC);
initial();
HC=PC+DC;
PC=0;
DC=0;
}
}
voidmain(){
intfunction,flag=1,command,md=0,back=0;
showInf();
scanf("%d",&function);
while(flag){
switch(function){
case1:
command=1;
run(command);//输入数据
md=0;
break;
case2:
command=2;//输入海明码
run(command);
md=1;
break;
case3:
system("cls");//清屏
break;
case4:
system("cls");
if(md==1)//纠正海明码
mend(HC);
elseprintf("\n\n提示信息:
您还没有输入海明码或者输入的海明码已经被纠正了.\n\n\n");
md=0;
EC=0;
break;
case5:
system("cls");//返回主页
back=1;
break;
case6:
exit
(1);//退出
default:
system("cls");
printf("\n\n\n提示信息:
操作不正确,请重新选择!
\n\n");
break;
}
if(back==1){
showInf();
back=0;
}
else{
printf("\n1输入数据后生成海明码2输入海明码3清屏4纠正海明码5返回主页6结束程序\n\n");
printf("请选择操作,只能输入一个数:
");
}
scanf("%d",&function);
}
}
2、CAN总线的媒体访问控制访问方式是什么?
它有什么优缺点?
根据CAN总线的媒体访问控制方式的缺点,有哪些改进的措施?
并谈一谈这些改进措施的如何实现?
(至少提出两种以上的改进措施)(20分)
答:
CAN总线的媒体访问控制访问方式是带优先级的CS-MA/CD。
采用多主竞争式结构:
网络上任意节点均可以在任意时刻主动地向网络上其它节点发送信息,而不分主从,即当发现总线空闲时,各个节点都有权使用网络。
在发生冲突时,采用非破坏性总线优先仲裁技术:
当几个节点同时向网络发送信息时,运用逐位仲裁规则,借助帧中开始部分的标识符,优先级低的节点主动停止发送数据,而优先级高的节点可不受影响地继续发送信息,从而有效地避免了总线冲突,使信息和时间均无损失。
例如,规定0的优先级高,在节点发送信息时,CAN总线作与运算。
每个节点都是边发送信息边检测网络状态,当某一个节点发送1而检测到0时,此节点知道有更高优先级的信息在发送,它就停止发送信息,直到再一次检测到网络空闲。
主要的优点:
CAN的传输信号采用短帧结构(有效数据最多为8个字节),和带优先级的CS-MA/CA通信介质访问控制方式,对高优先级的通信请求来说,在1Mbps通信速率时,最长的等待时间为0.15ms,完全可以满足现场控制的实时性要求。
CAN突出的差错检验机理,如5种错误检测、出错标定和故障界定;CAN传输信号为短帧结构,因而传输时间短,受干扰概率低。
这些保证了出错率极低,剩余错误概率为报文出错率的4.7×10-11。
另外,CAN节点在严重错误的情况下,具有自动关闭输出的功能,以使总线上其它节点的操作不受其影响。
因此,CAN具有高可靠性。
CAN的通信协议主要有CAN总线控制器完成。
CAN控制器主要由实现CAN总线协议部分和微控制器接口部分电路组成。
通过简单的连接即可完成CAN协议的物理层和数据链路层的所有功能,应用层功能由微控制器完成。
CAN总线上的节点即可以是基于微控制器的智能节点,也可以是具有CAN接口的I/O器件。
具有实时性强、传输距离较远、抗电磁干扰能力强、成本低等优点;采用双线串行通信方式,检错能力强,可在高噪声干扰环境中工作、具有优先权和仲裁功能,多个控制模块通过CAN控制器挂到CAN-bus上,形成多主机局部网络;可根据报文的ID决定接收或屏蔽该报文;可靠的错误处理和检错机制;发送的信息遭到破坏后,可自动重发;节点在错误严重的情况下具有自动退出总线的功能;报文不包含源地址或目标地址,仅用标志符来指示功能信息、优先级信息。
其缺点:
工业以太网采用的是带有冲突检测的载波侦听多路访问协议(CSMA/CD),无法保证数据传输的实时性要求,是一种非确定性的网络系统;安全可靠性问题,以太网采用超时重发机制,单点的故障容易扩散,造成整个网络系统的瘫痪;对工业环境的适应能力问题,目前工业以太