当前位置:文档之家› 实验5——485总线及Modbus通讯协议实验

实验5——485总线及Modbus通讯协议实验

课程名称:嵌入式软件技术开课机房:11号机房2012年4月24日星期二8:10~11:35一、实验任务与实验目的二、报告内容Freemodbus是modbus协议在嵌入式处理器上的实现。

包括AVR,PIC,WIN32等等平台。

它是开放性源代码,可用于商业目的。

它实现了Modbus RTU/ASCII、TCP三种传输方式,当前版本是1.5,支持以下功能:∙读输入寄存器(0x04)∙读保持寄存器(0x03)∙写单个寄存器(0x06)∙写多个寄存器(0x10)∙读/写多个寄存器(0x17)∙读取线圈状态(0x01)∙写单个线圈(0x05)∙写多个线圈(0x0F)∙读输入状态(0x02)∙报告从机标识(0x11)本实现基于最新的标准并且与标准完全兼容。

接收和传输Modbus RTU/ASCII数据帧是通过一个由硬件提取层的调用来驱动状态机实现的。

这就使得协议非常容易移植到其他的平台之上。

当接收一个完整的数据帧后,该数据帧被传入Modbus应用层,数据帧的内容在该层内得到解析。

为方便地增加新的Modbus功能,Freemodbus在应用层提供了钩子函数Hooks。

如果用到了Modbus TCP协议,那么当准备处理一个新数据帧的时候,移植层就必须首先向协议层发送一个事件标志。

然后,协议栈调用一个返回值为接收到的Modbus TCP数据帧的函数,并且开始处理这个数据帧。

如果数据有效,则响应的Modbus反馈帧将提供给移植层生成反馈帧。

最后,该反馈帧被发送到客户端。

二、实现FreeModbus协议所需要的软/硬件需求Modbus协议对硬件的需求非常少——基本上任何具有串行接口,并且有一些能够容纳modbus 数据帧的RAM的微控制器都足够了。

∙一个异步串行接口,能够支持接收缓冲区满和发送缓存区空中断。

∙一个能够产生RTU传输所需要的t3.5 字符超时定时器的时钟。

对于软件部分,仅仅需要一个简单的事件队列。

The STR71X/FreeRTOS 移植使用FreeRTOS 队列作为事件队列来减少Modbus 任务所需要的时间。

小点的微控制器往往不允许使用操作系统,在那种情况下,可以使用一个全局变量来实现该事件队列(The Atmel AVR 移植使用这种方式实现)。

实际的存储器需求决定于所使用的Modbus 模块的多少。

下表列出了所支持的功能编译后所需要的存储器。

ARM 项数值是使用GNUARM 编译器 3.4.4 使用-O1 选项得到的。

AVR项数值是使用WinAVR 编译器 3.4.5 使用-Os 选项编译得到的。

∙ATMega8/16/32/128/168/169 with WinAVR. See AVR/demo.c for an example.Coldfire devices:∙MCF5235 with GCC. See MCF5235/demo.c for an example.∙MCF5235 with CodeWarrior and FreeRTOS port for ColdFire. SeeMCF5235CW/demo.c for an example.∙MCF5235/TCP with GCC. This port features FreeRTOS and the lwIP stack.The lwIP part is generic and therefore it should be used as a basis for otherlwIP ports.MSP430 devices∙MSP430F169 with Rowley Crossworks. See MSP430/demo.c for an example.∙MSP430F169 with GCC. See MSP430/demo.c for an example.Z8Encore devices∙Z8F6422 and Z8F1622 port. See Z8ENCORE/demo.c for an example. The port uses ZDS II - Z8 Encore! 4.10.1 as development environment.Win32:∙ A Win32 Modbus RTU/ASCII Port.∙ A Win32 Modbus/TCP Port.Linux:∙ A Linux (uCLinux or other distributions) Modbus RTU/ASCII Port.任务一PortTimer.c中:xMBPortTimersInit( USHORT usTim1Timerout50us ) 负责配置一个时基,vMBPortTimersEnable( ) 启用这个时基。

比如执行:xMBPortTimersInit( 10000 );vMBPortTimersEnable( );Port.c/* ----------------------- System includes --------------------------------*/ #include"hw_types.h"#include"interrupt.h"///zd/* ----------------------- Modbus includes----------------------------------*//* ----------------------- Variables----------------------------------------*////int VIC_Temp;/* ----------------------- Start implementation-----------------------------*/void EnterCriticalSection() {IntMasterDisable(); /* Disable Interruptions _zd */}void ExitCriticalSection() {IntMasterEnable(); /* Enable Interruptions _zd */}PortSerial.c/** FreeModbus Libary: LM3S Port* Copyright (C) 2007 Tiago Prado Lone <tiago@.br>** This library is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 2.1 of the License, or (at your option) any later version.** This library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public* License along with this library; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ** File: $Id: portserial.c,v 1.1 2007/04/24 23:15:18 wolti Exp $*/#include"hw_memmap.h"#include"hw_ints.h"#include"hw_types.h"#include"sysctl.h"#include"hw_uart.h"#include"gpio.h"#include"interrupt.h"#include"uart.h"/*-------------------------------------------------------------*/#include"port.h"/* ----------------------- Modbus includes----------------------------------*/#include"mb.h"#include"mbport.h"/* ----------------------- Start implementation-----------------------------*/void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) { 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);} else {UARTIntDisable(UART0_BASE, UART_INT_TX);}}void vMBPortClose(void) {UARTIntDisable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX);IntEnable (INT_UART0);}BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity) {/*UCHAR PORT;ULONG BaudRate;UCHAR DataBits;eMBParity Parity;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);// Configure the UART for ulBaudRate, 8-EVEN-1 operation.UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), ulBaudRate,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_EVEN));// Enable the UART interrupt.IntEnable (INT_UART0);UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX);return TRUE;}BOOL xMBPortSerialPutByte(CHAR ucByte) {UARTCharPutNonBlocking(UART0_BASE, ucByte);return TRUE;}BOOL xMBPortSerialGetByte(CHAR * pucByte) {*pucByte = UARTCharGetNonBlocking(UART0_BASE);return TRUE;}/** Create an interrupt handler for the transmit buffer empty interrupt* (or an equivalent) for your target processor. This function should then * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that * a new character can be sent. The protocol stack will then call* xMBPortSerialPutByte( ) to send the character.*/static void prvvUARTTxReadyISR(void) {pxMBFrameCBTransmitterEmpty();}/** Create an interrupt handler for the receive interrupt for your target* processor. This function should then call pxMBFrameCBByteReceived( ). The * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the* character.*/static void prvvUARTRxISR(void) {pxMBFrameCBByteReceived();}// UART INT HANDLER ZDvoid UART0IntHandler(void) {unsigned long ulStatus;ulStatus = UARTIntStatus(UART0_BASE, true);UARTIntClear(UART0_BASE, ulStatus);if (ulStatus & (UART_INT_RT | UART_INT_RX)) {prvvUARTRxISR();}if (ulStatus & UART_INT_TX) {prvvUARTTxReadyISR();}}/** FreeModbus Libary: LM3S Port* Copyright (C) 2007 Tiago Prado Lone <tiago@.br>** This library is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 2.1 of the License, or (at your option) any later version.** This library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public* License along with this library; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ** File: $Id: porttimer.c,v 1.1 2007/04/24 23:15:18 wolti Exp $*/PortTimer.c#include"hw_memmap.h"#include"hw_ints.h"#include"hw_types.h"#include"sysctl.h"#include"interrupt.h"#include"hw_timer.h"#include"hw_types.h"#include"gpio.h"#include"timer.h"/* ----------------------- Platform includes--------------------------------*/#include"port.h"/* ----------------------- Modbus includes----------------------------------*/#include"mb.h"#include"mbport.h"/* ----------------------- Start implementation-----------------------------*/BOOL xMBPortTimersInit(USHORT usTim1Timerout50us) { 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);return TRUE;}void vMBPortTimersEnable() {TimerEnable(TIMER0_BASE, TIMER_A);}void vMBPortTimersDisable() {TimerDisable(TIMER0_BASE, TIMER_A);}void TIMERExpiredISR(void) {(void) pxMBPortCBTimerExpired();}// TIME0 INT HANDLER ZDvoid Timer0IntHandler(void) {TIMERExpiredISR();TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);TimerEnable(TIMER0_BASE, TIMER_A);}PortEvent.c/** FreeModbus Libary: LM3S Port* Copyright (C) 2007 Tiago Prado Lone <tiago@.br>** This library is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 2.1 of the License, or (at your option) any later version.** This library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public* License along with this library; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ** File: $Id: portevent.c,v 1.1 2007/04/24 23:15:18 wolti Exp $*//* ----------------------- Modbus includes----------------------------------*/#include"mb.h"#include"mbport.h"/* ----------------------- Variables----------------------------------------*/static eMBEventType eQueuedEvent;static BOOL xEventInQueue;/* ----------------------- Start implementation -----------------------------*/BOOL xMBPortEventInit(void) {xEventInQueue = FALSE;return TRUE;}BOOL xMBPortEventPost(eMBEventType eEvent) { xEventInQueue = TRUE;eQueuedEvent = eEvent;return TRUE;}BOOL xMBPortEventGet(eMBEventType * eEvent) { BOOL xEventHappened = FALSE;if (xEventInQueue) {*eEvent = eQueuedEvent;xEventInQueue = FALSE;xEventHappened = TRUE;}return xEventHappened;}。

相关主题