实验5485总线及Modbus通讯协议实验Word格式文档下载.docx
《实验5485总线及Modbus通讯协议实验Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《实验5485总线及Modbus通讯协议实验Word格式文档下载.docx(12页珍藏版)》请在冰豆网上搜索。
二、报告内容
Freemodbus是modbus协议在嵌入式处理器上的实现。
包括AVR,PIC,WIN32等等平台。
它是开放性源代码,可用于商业目的。
它实现了ModbusRTU/ASCII、TCP三种传输方式,当前版本是1.5,支持以下功能:
∙读输入寄存器(0x04)
∙读保持寄存器(0x03)
∙写单个寄存器(0x06)
∙写多个寄存器(0x10)
∙读/写多个寄存器(0x17)
∙读取线圈状态(0x01)
∙写单个线圈(0x05)
∙写多个线圈(0x0F)
∙读输入状态(0x02)
∙报告从机标识(0x11)
本实现基于最新的标准并且与标准完全兼容。
接收和传输ModbusRTU/ASCII数据帧是通过一个由硬件提取层的调用来驱动状态机实现的。
这就使得协议非常容易移植到其他的平台之上。
当接收一个完整的数据帧后,该数据帧被传入Modbus应用层,数据帧的内容在该层内得到解析。
为方便地增加新的Modbus功能,Freemodbus在应用层提供了钩子函数Hooks。
如果用到了ModbusTCP协议,那么当准备处理一个新数据帧的时候,移植层就必须首先向协议层发送一个事件标志。
然后,协议栈调用一个返回值为接收到的ModbusTCP数据帧的函数,并且开始处理这个数据帧。
如果数据有效,则响应的Modbus反馈帧将提供给移植层生成反馈帧。
最后,该反馈帧被发送到客户端。
二、实现FreeModbus协议所需要的软/硬件需求
Modbus协议对硬件的需求非常少——基本上任何具有串行接口,并且有一些能够容纳modbus数据帧的RAM的微控制器都足够了。
∙一个异步串行接口,能够支持接收缓冲区满和发送缓存区空中断。
∙一个能够产生RTU传输所需要的t3.5字符超时定时器的时钟。
对于软件部分,仅仅需要一个简单的事件队列。
TheSTR71X/FreeRTOS移植使用FreeRTOS队列作为事件队列来减少Modbus任务所需要的时间。
小点的微控制器往往不允许使用操作系统,在那种情况下,可以使用一个全局变量来实现该事件队列(TheAtmelAVR移植使用这种方式实现)。
实际的存储器需求决定于所使用的Modbus模块的多少。
下表列出了所支持的功能编译后所需要的存储器。
ARM项数值是使用GNUARM编译器3.4.4使用-O1选项得到的。
AVR项数值是使用WinAVR编译器3.4.5使用-Os选项编译得到的。
Module
ARMCode
ARMRAM(static)
AVRCode
AVRRAM(static)
ModbusRTU(Required)
1132Byte
272Byte
1456Byte
266Byte
ModbusASCII(Optional)
1612Byte
28Byte
1222Byte
16Byte
ModbusFunctions[1]
1180Byte
34Byte
1602Byte
ModbusCore(Required)
924Byte
180Byte
608Byte
75Byte
PortingLayer(Required[2])
1756Byte
704Byte
7Byte
Totals
7304Byte
530Byte
5592Byte
398Byte
[1]:
实际大小决定于可支持的Modbus功能码的多少。
功能码可以在头文件
mbconfig.h中进行配置。
[2]:
决定于硬件。
已完成的移植:
CortexM3devices:
∙AtmelAT91SAM3S.
ARMdevices:
∙STR71XwithFreeRTOS/GCC.SeeSTR71X/simple2.cforanexample.
∙STR71TCPwithFreeRTOS/lwIP/GCC.ThisportincludesFreeRTOS,lwIPandafullyworkingPPPstack.ThelwIP,PPPandFreeRTOSpartisgenericandthereforecanbeusedforotherports(orotherprojects).
∙LPC214XwithKeil.SeeLPC214X/demo.cforanexample.ThisportusestheKeilARMCompiler2.41.
∙AT91SAM7XwithFreeRTOS/Rowley.SeeAT91SAM7X_ROWLEY/demo.cforanexample.
AVRdevices:
∙ATMega8/16/32/128/168/169withWinAVR.SeeAVR/demo.cforanexample.
Coldfiredevices:
∙MCF5235withGCC.SeeMCF5235/demo.cforanexample.
∙MCF5235withCodeWarriorandFreeRTOSportforColdFire.SeeMCF5235CW/demo.cforanexample.
∙MCF5235/TCPwithGCC.ThisportfeaturesFreeRTOSandthelwIPstack.ThelwIPpartisgenericandthereforeitshouldbeusedasabasisforotherlwIPports.
MSP430devices
∙MSP430F169withRowleyCrossworks.SeeMSP430/demo.cforanexample.
∙MSP430F169withGCC.SeeMSP430/demo.cforanexample.
Z8Encoredevices
∙Z8F6422andZ8F1622port.SeeZ8ENCORE/demo.cforanexample.TheportusesZDSII-Z8Encore!
4.10.1asdevelopmentenvironment.
Win32:
∙AWin32ModbusRTU/ASCIIPort.
∙AWin32Modbus/TCPPort.
Linux:
∙ALinux(uCLinuxorotherdistributions)ModbusRTU/ASCIIPort.
任务一
PortTimer.c中:
xMBPortTimersInit(USHORTusTim1Timerout50us)负责配置一个时基,vMBPortTimersEnable()启用这个时基。
比如执行:
xMBPortTimersInit(10000);
vMBPortTimersEnable();
Port.c
/*-----------------------Systemincludes--------------------------------*/
#include"
hw_types.h"
interrupt.h"
///zd
/*-----------------------Modbusincludes----------------------------------*/
/*-----------------------Variables----------------------------------------*/
///intVIC_Temp;
/*-----------------------Startimplementation-----------------------------*/
voidEnterCriticalSection(){
IntMasterDisable();
/*DisableInterruptions_zd*/
}
voidExitCriticalSection(){
IntMasterEnable();
/*EnableInterruptions_zd*/
PortSerial.c
/*
*FreeModbusLibary:
LM3SPort
*Copyright(C)2007TiagoPradoLone<
tiago@.br>
*
*Thislibraryisfreesoftware;
youcanredistributeitand/or
*modifyitunderthetermsoftheGNULesserGeneralPublic
*LicenseaspublishedbytheFreeSoftwareFoundation;
either
*version2.1oftheLicense,or(atyouroption)anylaterversion.
*Thislibraryisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;
withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.SeetheGNU
*LesserGeneralPublicLicenseformoredetails.
*YoushouldhavereceivedacopyoftheGNULesserGeneralPublic
*Licensealongwiththislibrary;
ifnot,writetotheFreeSoftware
*Foundation,Inc.,51FranklinSt,FifthFloor,Boston,MA02110-1301USA
*File:
$Id:
portserial.c,v1.12007/04/2423:
15:
18woltiExp$
*/
hw_memmap.h"
hw_ints.h"
sysctl.h"
hw_uart.h"
gpio.h"
uart.h"
/*-------------------------------------------------------------*/
port.h"
mb.h"
mbport.h"
voidvMBPortSerialEnable(BOOLxRxEnable,BOOLxTxEnable){
if(TRUE==xRxEnable){
UARTIntEnable(UART0_BASE,UART_INT_RX|UART_INT_RT);
}else{
UARTIntDisable(UART0_BASE,UART_INT_RX|UART_INT_RT);
}
if(TRUE==xTxEnable){
UARTIntEnable(UART0_BASE,UART_INT_TX);
UARTIntDisable(UART0_BASE,UART_INT_TX);
voidvMBPortClose(void){
UARTIntDisable(UART0_BASE,UART_INT_RX|UART_INT_RT|UART_INT_TX);
IntEnable(INT_UART0);
BOOLxMBPortSerialInit(UCHARucPORT,ULONGulBaudRate,UCHARucDataBits,
eMBParityeParity){
/*
UCHARPORT;
ULONGBaudRate;
UCHARDataBits;
eMBParityParity;
PORT=ucPORT;
BaudRate=ulBaudRate;
DataBits=ucDataBits;
Parity=eParity;
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0|GPIO_PIN_1);
//ConfiguretheUARTforulBaudRate,8-EVEN-1operation.
UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),ulBaudRate,
(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_EVEN));
//EnabletheUARTinterrupt.
UARTIntEnable(UART0_BASE,UART_INT_RX|UART_INT_RT|UART_INT_TX);
returnTRUE;
BOOLxMBPortSerialPutByte(CHARucByte){
UARTCharPutNonBlocking(UART0_BASE,ucByte);
BOOLxMBPortSerialGetByte(CHAR*pucByte){
*pucByte=UARTCharGetNonBlocking(UART0_BASE);
/*
*Createaninterrupthandlerforthetransmitbufferemptyinterrupt
*(oranequivalent)foryourtargetprocessor.Thisfunctionshouldthen
*callpxMBFrameCBTransmitterEmpty()whichtellstheprotocolstackthat
*anewcharactercanbesent.Theprotocolstackwillthencall
*xMBPortSerialPutByte()tosendthecharacter.
staticvoidprvvUARTTxReadyISR(void){
pxMBFrameCBTransmitterEmpty();
*Createaninterrupthandlerforthereceiveinterruptforyourtarget
*processor.ThisfunctionshouldthencallpxMBFrameCBByteReceived().The
*protocolstackwillthencallxMBPortSerialGetByte()toretrievethe
*character.
staticvoidprvvUARTRxISR(void){
pxMBFrameCBByteReceived();
//UARTINTHANDLERZD
voidUART0IntHandler(void){
unsignedlongulStatus;
ulStatus=UARTIntStatus(UART0_BASE,true);
UARTIntClear(UART0_BASE,ulStatus);
if(ulStatus&
(UART_INT_RT|UART_INT_RX)){
prvvUARTRxISR();
UART_INT_TX){
prvvUARTTxReadyISR();
porttimer.c,v1.12007/04/2423:
PortTimer.c
hw_timer.h"
timer.h"
/*-----------------------Platformincludes--------------------------------*/
BOOLxMBPortTimersInit(USHORTusTim1Timerout50us){
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
GPIOPinTypeTimer(TIMER0_BASE,TIMER_A);
TimerConfigure(TIMER0_BASE,TIMER_CFG_32_BIT_PER);
TimerLoadSet(TIMER0_BASE,TIMER_A,
(SysCtlClockGet()/20000)*usTim1Timerout50us);
TimerIntEnable(TIMER0_BASE,TIMER_TIMA_TIMEOUT);
TimerEnable(TIMER0_BASE,TIMER_A);
IntEnable(INT_TIMER0A);
voidvMBPortTimersEnable(){
voidvMBPortTimersDisable(){
TimerDisable(TIMER0_BASE,TIMER_A);
voidTIMERExpiredISR(void){
(void