现场总线.docx
《现场总线.docx》由会员分享,可在线阅读,更多相关《现场总线.docx(16页珍藏版)》请在冰豆网上搜索。
现场总线
(1)
CAN协议结构
CAN协议结构划分为两层:
数据链路层和物理层。
物理层
物理层分为物理信号子层(PLS)、物理介质连接(PMA)、介质相关接口(MDI)三个部分,规定了通讯时使用的电缆、连接器等的媒体、电气信号规格等,以实现设备间的信号传送,定义了信号实际的发送方式、位时序、位的编码方式及同步的步骤。
物理信号子层(PLS)根据“不归零”NRZ方式对信号实现编码/解码、定时和同步的功能,物理介质连接(PMA)实现总线发送/接收的功能电路并提供总线故障检测方法,介质相关接口(MDI)实现物理介质与媒体访问单元之间的机械和电气接口。
数据链路层
数据链路层将物理层收到的信号组成有意义的数据,提供传输错误控制等数据传输控制流程,由逻辑链路控制子层(LLC)和介质访问控制子层(MAC)组成。
逻辑链路控制子层LLC的功能包括验收滤波、过载通知、
恢复管理;介质访问控制子层(MAC)的功能主要是传送规则,即控制帧结构,执行仲裁、错误检测、出错标定和故障鉴定,如图3-1所示,是CAN协议的核心部分。
如果总线上有两个或两个以上的节点同时开始传送报文,就会产生总线访问冲突,解决总线访问冲突的方法就是使用标识符的位仲裁。
总线上的电平分为显性电平(D)和隐性电平(d)如图3-2所示,位仲裁过程如图3-3所示,如果传送报文的发送位的电平与被监控电平相同,则发送器继续发送报文,如果发送的是一个隐性电平却被监控被显性电平,那么就失去了仲裁,退出发送状态。
单元1:
D
D
D
D
D
D
R
R
D
D
R
D
D
R
R
D
D
D
R
R
仲裁失利,转为接收器
单元2:
赢得仲裁,继续发送
D
D
D
D
D
D
R
R
D
D
D
R
R
D
D
D
R
R
R
R
总线状态:
D
D
D
D
D
D
R
R
D
D
D
R
R
D
D
D
R
R
R
R
图3-3仲裁过程
实际上CAN协议是规定CAN节点之间如何完成通信的通信协议。
端口定义:
本课程采用MCP2551芯片进行通信
CAN总线的发展历程:
随着计算机硬件、软件及集成电路技术的迅速发展,消费类电子产品、嵌入式主板、汽车和工业应用等也发展迅速,从而对高速、高可靠和低成本的通信介质的要求也随之提高。
现场总线是当今自动化领域技术发展的热点之一,它为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有力的技术支持。
在嵌入式硬件系统传输领域内,长期以来使用的通信标准,尽管被广泛使用,是无法在需要使用大量的传感器和控制器的复杂或大规模的环境中使用。
CAN总线就是为适应这种需要而发展起来的。
CAN是ControllerAreaNetwork的缩写,即“局域网控制器”的意思,可以归属于工业现场总线的范畴,通常称为CANBUS,即CAN总线,是目前国际上应用最为广泛的开放式现场总线之一。
CAN总线最早用在汽车电子领域,世界上一些著名的汽车制造厂商都采用CAN总线来实现汽车内部控制系统与各检测和执行机构间的数据通信。
CAN总线规范从CAN1.2规范发展为兼容CAN1.2规范的CAN2.0规范(CAN2.0A为标准格式,CAN2.0B为扩展格式),目前应用的CAN器件大多符合CAN2.0规范。
♦CAN总线发展简史
1986年,Bosch在SAE(汽车工程人员协会)大会上提出CAN总线概念;
1987年,Intel推出第一片CAN控制芯片82526,随后Philips半导体也推出82C200;
1993年,CAN的国际标准ISO11898/ISO11519公布。
ISO11898为高速应用,ISO11519为低速应用;
1994年开始有了国际CAN学术年会ICC。
同年,美国汽车工程师协会以CAN为基础制定了SAEJ1939标准,用于卡车和巴士控制和通信网络。
作用:
MCP2551是一个可容错的高速CAN器件,可作为CAN协议控制器和物理总线接口。
MCP2551可为CAN协议控制器提供差分收发能力,它完全符合ISO-11898标准,包括能满足24V电压要求。
它的工作速率高达1Mb/s。
典型情况下,CAN系统上的每个节点都必须有一个器件,把CAN控制器生成的数字信号转化成为适合总线传输(差分输出)的信号。
它也为CAN控制器和CAN总线上的高压尖峰信号之间加入了缓冲器,这些高压尖峰信号可能是由外部器件产生(EMI、ESD和电气瞬态等)。
CAN具有如下的特点:
1)CAN控制器工作于多主站方式,网络中的各节点都可根据总线访问优先权(取决于报文标识符)采用无损结构的逐位仲裁的方式竞争向总线发送数据。
而利用RS-485只能构成主从式结构系统,通信方式也只能以主站轮询的方式进行,系统的实时性、可靠性较差。
2)CAN协议废除了传统的站地址编码,而代之以对通信数据进行编码,其优点是可使网络内的节点个数在理论上不受限制,加入或减少设备都不影响系统的工作。
同时可使不同的节点同时接收到相同的数据,这些特点使得CAN总线构成的网络各节点之间的数据通信实时性强,并且容易构成冗余结构,提高系统的可靠性和系统的灵活性。
3)CAN总线通过CAN控制器接口芯片的两个输出端CANH和CANL与物理总线相连,而CANH端的状态只能是高电平或悬浮状态,CANL端只能是低电平或悬浮状态。
这样就保证不会出现类似在RS-485网络中系统有错误时会导致出现多节点同时向总线发送数据而导致总线呈现短路从而损坏某些节点的现象。
而且CAN节点在错误严重的情况下具有自动关闭输出功能,以使总线上其他节点的操作不受影响,从而保证不会出现象在网络中,因个别节点出现问题,使得总线处于“死锁”状态。
4)CAN具有的完善的通信协议可由CAN控制器芯片及其接口芯片来实现,从而大大降低了用户系统开发的难度,缩短了开发周期,这些是仅仅有电气协议的RS-485所无法比拟的。
5)与其它现场总线比较而言,CAN总线通信最高速率可达1MBPS,传输速率为5KBPS时,采用双绞线,传输距离可达10KM,并且数据传输可靠性高;CAN总线是具有通信速率高、容易实现、且性价比高等诸多特点的一种已形成国际标准的现场总线。
这些也是目前
CAN总线应用于众多领域,具有强劲的市场竞争力的重要原因。
6)电路结构简单,要求的线数较少,只需要两根线与外部器件互联,各控制单元能够通过CAN总线共享所有的信息和资源。
(2)MCU主电路(如果你想写的话可以把复位电路加上再加上电源之类的)画原理图填字母很麻烦
模拟信号处理电路(全波整流电路)或者采用可调电位器
A/D转换器及通信接口和MCU的接口电路:
(你也可以把片选使能之类的接口连接上,如果我写的很全的话就和以前有的电路一样了,防止老师看出来)
(这是2551和1674以及4011连在一起的电路图)
DSPIC30F4011的参数:
AD1674的参数:
MCP2251的参数:
(3)A/D转换程序:
#include
#include"AD1674.h"
#include"delay.h"
#defineDataBus_8bitsPORTB
#defineAD1674_CE_LATC13
#defineAD1674_CS_LATC13
#defineAD1674_RC_LATD1
#defineAD1674_A0_LATC14
#defineAD1674_STS_RD0
voiddelayus(unsignedintn)
{
while(n--);
}
voiddelayms(unsignedintms)
{
while(ms--)
delayus(800);
}
voidInitialAD1674(void)
{
TRISB=0x00ff;
TRISC=0x0000;
TRISD=0x0001;
}
unsignedintRead_AD1764(void)
{
unsignedintnADResult,nRet;
TRISB=0x00ff;
TRISC=0x0000;
TRISD=0x0001;
_LATC14=0;//A0选择12位转换
_LATD1=0;//RC=0
delayus(3);//等待信号稳定
_LATC13=1;//CE=1启动AD
delayus(10);//while(_LATD0==1);//等待转换结束
_LATC13=0;
delayus
(1);
_LATD1=1;//RC=1允许数据读出
asm("nop");asm("nop");
_LATC13=1;//?
?
?
?
?
?
?
_LATC14=0;//A0=0高8位输出
asm("nop");asm("nop");
nADResult=DataBus_8bits;
nRet=nADResult<<4;
_LATC14=1;//A0=1低4位输出
nADResult=DataBus_8bits;
_LATC13=0;
asm("nop");asm("nop");
_LATD1=0;
nADResult&=0x000F;
nRet|=nADResult;
returnnRet;
}
MCU与PC机的CAN通信程序;
#include"p30f4011.h"
#defineFCY16000000//4M晶振,选择XT的16倍频
#defineFCAN16000000//Fcan=Fcy,在CAN初始化中将经行此设置
#defineBITRATE250000//通信波特率
#defineK16//TQ时钟数
#defineBRP_VAL((FCAN/(2*K*BITRATE))-1)//后面设置BRP时要用到此值
intfailmemory[40];
unsignedintbuffer1;
unsignedintbuffer2;
unsignedintbuffer3;
unsignedintbuffer4;
unsignedlonginti=0;
voidCAN_Init()
{
TRISFbits.TRISF0=1;//将F0口即CANRX口作为输入口
TRISFbits.TRISF1=0;//将F1口即CANTX口作为输出口
C1CTRLbits.REQOP=0x4;//请求进入配置模式
while(C1CTRLbits.OPMODE!
=0x4){}//确认进入配置模式
//波特率设置
C1CTRLbits.CANCKS=1;//CAN主时钟选择,Fcan=Fcy
C1CFG1bits.SJW=00;//同步跳转宽度时间为1*TQ
C1CFG1bits.BRP=BRP_VAL;
C1CFG2=0x02ED;
//中断设置
C1INTF=0;//所有CAN中断清零
IFS1bits.C1IF=0;//CAN中断标志位清零
C1INTE=0X00FF;//CAN中断使能
IEC1bits.C1IE;//CAN中断使能
//发送设置
C1TX0CON=0x0003;//发送0邮箱配置,高优先级
C1TX0SID=0x50a8;//发送0邮箱SID,ID=0X2A8
C1TX0EID=0X0000;//发送0邮箱EID
C1TX0DLC=0x01c0;//发送0数据长度,8字节
C1TX1CON=0X0002;//发送1邮箱配置,高优先级
C1TX1SID=0XA860;//发送1邮箱SID,ID=0X2A0
C1TX1EID=0X0000;//发送1邮箱IED
C1TX1DLC=0X8DA0;//发送1数据长度,4字节
//接收设置
C1RX0CON=0x0000;//接收0邮箱配置
C1RX1CON=0X0002;//接收缓冲器0使用接收过滤器2
C1RX0DLC=0x0008;//接收0数据长度,8字节
C1RXM0SID=C1RXM1SID=0X1F01;//接收的为标准数据帧?
C1RXM0EIDH=C1RXM1EIDH=0X0FFF;//接收过滤器0和1扩展标识符高位寄存器设置
C1RXM0EIDL=C1RXM1EIDL=0XFC00;//接收过滤器0和1扩展标识符低位寄存器设置
C1RXF0SID=0X0AA8;//接收过滤器1SID,ID=0X2AA
C1RXF2SID=0X15C0;//接收过滤器2SID,ID=0X570
C1RXF2EIDH=0X0004;//接收过滤器2扩展标识符高位寄存器设置
C1RXF2EIDL=0X8C00;//接收过滤器2扩展标识符低位寄存器设置
C1CTRLbits.REQOP=0x0;//请求进入正常工作模式
while(C1CTRLbits.OPMODE!
=0x0){}//确认进入正常工作模式
return;
}
intmain()
{
TRISB=0X00;//RB口设置为输出
PORTB=0XFF;//端口初始化,使8个LED熄灭
CAN_Init();
while
(1)
{
if(C1RX0CONbits.RXFUL==1)//如果接受缓冲器包含有效的接收报文
{
buffer1=C1RX0B1;
buffer2=C1RX0B2;
buffer3=C1RX0B3;
buffer4=C1RX0B4;
C1RX0CONbits.RXFUL=0;
}
if(buffer1==0x5555)
{
PORTB=0X00;//点亮8个LED
}
if(buffer1==0x5554)
{
PORTB=0XFF;//使8个LED熄灭
}
}
}
MCU主程序:
#include
#include"Delay.h"
voiddelayus(unsignedintn)
{
while(n--);
}
voiddelayms(unsignedintms)
{
while(ms--)
delayus(800);
}
intmain(void)
{
WDTSWEnable;//程序调试完成,需要WDT时,放开WTD
ClrWdt();//复位WTD,<=1s时,需要加一句.
_init_prog_address(EE_addr,fooArrayInDataEE);
delayms(10);
tempadd=EE_addr;
EE_addr=0x7FFC00;
_memcpy_p2d16(fooArray2inRAM,EE_addr,4);
EE_addr=tempadd;
condition=(uchar)fooArray2inRAM[0];//读取状态
Port_Config();
EE_addr=0x7FFC04;
ClrWdt();
Save_1record();
writeEE(0x01);//4011加电备忘
}
switch(number)
{
case1:
//读4011的EEPROM
{
_T1IE=0;
tempadd=EE_addr;//存当前地址
EE_addr=0x7FFC00;
C1TX0SID=0x50A0;//2A9
for(m=0;m<128;m++)//128*8=1024
{
_memcpy_p2d16(fooArray2inRAM,EE_addr,8);//每次取四个字数据
C1TX0B1=fooArray2inRAM[0];
C1TX0B2=fooArray2inRAM[1];
C1TX0B3=fooArray2inRAM[2];
C1TX0B4=fooArray2inRAM[3];
C1TX0CONbits.TXREQ=1;
delayus(10);
while(C1TX0CONbits.TXREQ==1);
Nop();
EE_addr=EE_addr+8;;//EE地址递增8字节
}
EE_addr=tempadd;//还原地址
_T1IE=1;
number=10;
}
break;
case2:
//送状态信息
OutData0[0]=condition;
number=10;
break;
default:
break;//停止模式
}
Nop();
}
}
④设上位机采用某型USB-CAN转换器,请说明该转换器与MCU的连接;编写指令,分别读(显示)下位机的数据采集结果。
答:
连接线USB端和PC机相连,另一端和USB—CAN的CANH和CANL相连。
在USB—CAN软件上ID地址上输入CAN协议的指令,读取在EEPROM中的数据
#include
#include"Delay.h"
voiddelayus(unsignedintn)
{
while(n--);
}
voiddelayms(unsignedintms)
{
while(ms--)
delayus(800);
}
{
_T1IE=0;
tempadd=EE_addr;//存当前地址
EE_addr=0x7FFC00;
C1TX0SID=0x50A4;//2A9
for(m=0;m<128;m++)//128*8=1024
{
_memcpy_p2d16(fooArray2inRAM,EE_addr,8);//每次取四个字数据
C1TX0B1=fooArray2inRAM[0];
C1TX0B2=fooArray2inRAM[1];
C1TX0B3=fooArray2inRAM[2];
C1TX0B4=fooArray2inRAM[3];
C1TX0CONbits.TXREQ=1;
delayus(10);
while(C1TX0CONbits.TXREQ==1);
Nop();
EE_addr=EE_addr+8;;//EE地址递增8字节
}
EE_addr=tempadd;//送原地址
_T1IE=1;
number=10;
break;
}