Browse Source

[modbus]port modbus master and slave by rtt device framework.

armink 10 years ago
parent
commit
2a14e4071c

+ 7 - 8
components/net/freemodbus-v1.6.0/port/port.c

@@ -1,6 +1,6 @@
  /*
-  * FreeModbus Libary: LPC214X Port
-  * Copyright (C) 2007 Tiago Prado Lone <tiago@maxwellbohr.com.br>
+  * FreeModbus Libary: RT-Thread Port
+  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
   * 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: port.c,v 1.1 2007/04/24 23:15:18 wolti Exp $
+  * File: $Id: portevent.c,v 1.60 2015/02/01 9:18:05 Armink $
   */
 
 /* ----------------------- System includes --------------------------------*/
@@ -24,16 +24,15 @@
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "port.h"
 /* ----------------------- Variables ----------------------------------------*/
-
+static rt_base_t level;
 /* ----------------------- Start implementation -----------------------------*/
 void EnterCriticalSection(void)
 {
-	//关闭全局中断
-	__disable_irq();
+	level = rt_hw_interrupt_disable();
 }
 
 void ExitCriticalSection(void)
 {
-	//开启全局中断
-	__enable_irq();
+	rt_hw_interrupt_enable(level);
 }
+

+ 4 - 10
components/net/freemodbus-v1.6.0/port/port.h

@@ -1,6 +1,6 @@
 /*
  * FreeModbus Libary: BARE Port
- * Copyright (C) 2006 Christian Walter <wolti@sil.at>
+ * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,18 +34,9 @@
 #define PR_BEGIN_EXTERN_C           extern "C" {
 #define	PR_END_EXTERN_C             }
 
-//TODO  暂时先写B13引脚,等组网测试时再确认
-#define SLAVE_RS485_SEND_MODE  GPIO_SetBits(GPIOB,GPIO_Pin_13)
-#define SLAVE_RS485_RECEIVE_MODE  GPIO_ResetBits(GPIOB,GPIO_Pin_13)
-#define MASTER_RS485_SEND_MODE  GPIO_SetBits(GPIOB,GPIO_Pin_13)
-#define MASTER_RS485_RECEIVE_MODE  GPIO_ResetBits(GPIOB,GPIO_Pin_13)
-
 #define ENTER_CRITICAL_SECTION()	EnterCriticalSection()
 #define EXIT_CRITICAL_SECTION()    ExitCriticalSection()
 
-void EnterCriticalSection(void);
-void ExitCriticalSection(void);
-
 typedef uint8_t BOOL;
 
 typedef unsigned char UCHAR;
@@ -65,4 +56,7 @@ typedef int32_t LONG;
 #define FALSE           0
 #endif
 
+void EnterCriticalSection(void);
+void ExitCriticalSection(void);
+
 #endif

+ 24 - 14
components/net/freemodbus-v1.6.0/port/portevent.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,35 +24,45 @@
 #include "mbport.h"
 
 /* ----------------------- Variables ----------------------------------------*/
-static eMBEventType eQueuedEvent;
-static BOOL     xEventInQueue;
-
+static struct rt_event     xSlaveOsEvent;
 /* ----------------------- Start implementation -----------------------------*/
 BOOL
 xMBPortEventInit( void )
 {
-    xEventInQueue = FALSE;
+    rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO);
     return TRUE;
 }
 
 BOOL
 xMBPortEventPost( eMBEventType eEvent )
 {
-    xEventInQueue = TRUE;
-    eQueuedEvent = eEvent;
+    rt_event_send(&xSlaveOsEvent, eEvent);
     return TRUE;
 }
 
 BOOL
 xMBPortEventGet( eMBEventType * eEvent )
 {
-    BOOL            xEventHappened = FALSE;
-
-    if( xEventInQueue )
+    rt_uint32_t recvedEvent;
+    /* waiting forever OS event */
+    rt_event_recv(&xSlaveOsEvent,
+            EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT,
+            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+            &recvedEvent);
+    switch (recvedEvent)
     {
-        *eEvent = eQueuedEvent;
-        xEventInQueue = FALSE;
-        xEventHappened = TRUE;
+    case EV_READY:
+        *eEvent = EV_READY;
+        break;
+    case EV_FRAME_RECEIVED:
+        *eEvent = EV_FRAME_RECEIVED;
+        break;
+    case EV_EXECUTE:
+        *eEvent = EV_EXECUTE;
+        break;
+    case EV_FRAME_SENT:
+        *eEvent = EV_FRAME_SENT;
+        break;
     }
-    return xEventHappened;
+    return TRUE;
 }

+ 192 - 14
components/net/freemodbus-v1.6.0/port/portevent_m.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -21,41 +21,219 @@
 
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
+#include "mb_m.h"
 #include "mbport.h"
+#include "port.h"
 
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Defines ------------------------------------------*/
 /* ----------------------- Variables ----------------------------------------*/
-static eMBMasterEventType eMasterQueuedEvent;
-static BOOL     xMasterEventInQueue;
-
+static struct rt_semaphore xMasterRunRes;
+static struct rt_event     xMasterOsEvent;
 /* ----------------------- Start implementation -----------------------------*/
 BOOL
 xMBMasterPortEventInit( void )
 {
-    xMasterEventInQueue = FALSE;
+    rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO);
     return TRUE;
 }
 
 BOOL
 xMBMasterPortEventPost( eMBMasterEventType eEvent )
 {
-    xMasterEventInQueue = TRUE;
-    eMasterQueuedEvent = eEvent;
+    rt_event_send(&xMasterOsEvent, eEvent);
     return TRUE;
 }
 
 BOOL
 xMBMasterPortEventGet( eMBMasterEventType * eEvent )
 {
-    BOOL            xEventHappened = FALSE;
+    rt_uint32_t recvedEvent;
+    /* waiting forever OS event */
+    rt_event_recv(&xMasterOsEvent,
+            EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE |
+            EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS,
+            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+            &recvedEvent);
+    /* the enum type couldn't convert to int type */
+    switch (recvedEvent)
+    {
+    case EV_MASTER_READY:
+        *eEvent = EV_MASTER_READY;
+        break;
+    case EV_MASTER_FRAME_RECEIVED:
+        *eEvent = EV_MASTER_FRAME_RECEIVED;
+        break;
+    case EV_MASTER_EXECUTE:
+        *eEvent = EV_MASTER_EXECUTE;
+        break;
+    case EV_MASTER_FRAME_SENT:
+        *eEvent = EV_MASTER_FRAME_SENT;
+        break;
+    case EV_MASTER_ERROR_PROCESS:
+        *eEvent = EV_MASTER_ERROR_PROCESS;
+        break;
+    }
+    return TRUE;
+}
+/**
+ * This function is initialize the OS resource for modbus master.
+ * Note:The resource is define by OS.If you not use OS this function can be empty.
+ *
+ */
+void vMBMasterOsResInit( void )
+{
+    rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO);
+}
+
+/**
+ * This function is take Mobus Master running resource.
+ * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE.
+ *
+ * @param lTimeOut the waiting time.
+ *
+ * @return resource taked result
+ */
+BOOL xMBMasterRunResTake( LONG lTimeOut )
+{
+    /*If waiting time is -1 .It will wait forever */
+    return rt_sem_take(&xMasterRunRes, lTimeOut) ? FALSE : TRUE ;
+}
+
+/**
+ * This function is release Mobus Master running resource.
+ * Note:The resource is define by Operating System.If you not use OS this function can be empty.
+ *
+ */
+void vMBMasterRunResRelease( void )
+{
+    /* release resource */
+    rt_sem_release(&xMasterRunRes);
+}
+
+/**
+ * This is modbus master respond timeout error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+        USHORT ucPDULength) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT);
+
+    /* You can add your code under here. */
 
-    if( xMasterEventInQueue )
+}
+
+/**
+ * This is modbus master receive data error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+        USHORT ucPDULength) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA);
+
+    /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master execute function error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+        USHORT ucPDULength) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION);
+
+    /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master request process success callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ */
+void vMBMasterCBRequestScuuess( void ) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_PROCESS_SUCESS);
+
+    /* You can add your code under here. */
+
+}
+
+/**
+ * This function is wait for modbus master request finish and return result.
+ * Waiting result include request process success, request respond timeout,
+ * receive data error and execute function error.You can use the above callback function.
+ * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run
+ * much user custom delay for waiting.
+ *
+ * @return request error code
+ */
+eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
+    eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
+    rt_uint32_t recvedEvent;
+    /* waiting for OS event */
+    rt_event_recv(&xMasterOsEvent,
+            EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT
+                    | EV_MASTER_ERROR_RECEIVE_DATA
+                    | EV_MASTER_ERROR_EXECUTE_FUNCTION,
+            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+            &recvedEvent);
+    switch (recvedEvent)
     {
-        *eEvent = eMasterQueuedEvent;
-        xMasterEventInQueue = FALSE;
-        xEventHappened = TRUE;
+    case EV_MASTER_PROCESS_SUCESS:
+        break;
+    case EV_MASTER_ERROR_RESPOND_TIMEOUT:
+    {
+        eErrStatus = MB_MRE_TIMEDOUT;
+        break;
+    }
+    case EV_MASTER_ERROR_RECEIVE_DATA:
+    {
+        eErrStatus = MB_MRE_REV_DATA;
+        break;
+    }
+    case EV_MASTER_ERROR_EXECUTE_FUNCTION:
+    {
+        eErrStatus = MB_MRE_EXE_FUN;
+        break;
+    }
     }
-    return xEventHappened;
+    return eErrStatus;
 }
 
 #endif

+ 155 - 122
components/net/freemodbus-v1.6.0/port/portserial.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,122 +24,148 @@
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
 #include "mbport.h"
+#include "rtdevice.h"
+#include "bsp.h"
+
+/* ----------------------- Static variables ---------------------------------*/
+ALIGN(RT_ALIGN_SIZE)
+/* software simulation serial transmit IRQ handler thread stack */
+static rt_uint8_t serial_soft_trans_irq_stack[512];
+/* software simulation serial transmit IRQ handler thread */
+static struct rt_thread thread_serial_soft_trans_irq;
+/* serial event */
+static struct rt_event event_serial;
+/* modbus slave serial device */
+static rt_serial_t *serial;
+
+/* ----------------------- Defines ------------------------------------------*/
+/* serial transmit event */
+#define EVENT_SERIAL_TRANS_START    (1<<0)
+
 /* ----------------------- static functions ---------------------------------*/
 static void prvvUARTTxReadyISR(void);
 static void prvvUARTRxISR(void);
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
+static void serial_soft_trans_irq(void* parameter);
+
 /* ----------------------- Start implementation -----------------------------*/
+BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
+        eMBParity eParity)
+{
+    /**
+     * set 485 mode receive and transmit control IO
+     * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user
+     */
+    rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
+
+    /* set serial name */
+    if (ucPORT == 1) {
+#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
+        extern struct rt_serial_device serial1;
+        serial = &serial1;
+#endif
+    } else if (ucPORT == 2) {
+#if defined(RT_USING_UART2)
+        extern struct rt_serial_device serial2;
+        serial = &serial2;
+#endif
+    } else if (ucPORT == 3) {
+#if defined(RT_USING_UART3)
+        extern struct rt_serial_device serial3;
+        serial = &serial3;
+#endif
+    }
+    /* set serial configure parameter */
+    serial->config.baud_rate = ulBaudRate;
+    serial->config.stop_bits = STOP_BITS_1;
+    switch(eParity){
+    case MB_PAR_NONE: {
+        serial->config.data_bits = DATA_BITS_8;
+        serial->config.parity = PARITY_NONE;
+        break;
+    }
+    case MB_PAR_ODD: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_ODD;
+        break;
+    }
+    case MB_PAR_EVEN: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_EVEN;
+        break;
+    }
+    }
+    /* set serial configure */
+    serial->ops->configure(serial, &(serial->config));
+
+    /* open serial device */
+    if (!serial->parent.open(&serial->parent,
+            RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) {
+        serial->parent.rx_indicate = serial_rx_ind;
+    } else {
+        return FALSE;
+    }
+
+    /* software initialize */
+    rt_thread_init(&thread_serial_soft_trans_irq,
+                   "slave trans",
+                   serial_soft_trans_irq,
+                   RT_NULL,
+                   serial_soft_trans_irq_stack,
+                   sizeof(serial_soft_trans_irq_stack),
+                   10, 5);
+    rt_thread_startup(&thread_serial_soft_trans_irq);
+    rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
+
+    return TRUE;
+}
 
 void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
 {
-	if (xRxEnable)
-	{
-		SLAVE_RS485_RECEIVE_MODE;
-		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-	}
-	else
-	{
-		SLAVE_RS485_SEND_MODE;
-		USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
-	}
-	if (xTxEnable)
-	{
-		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
-	}
-	else
-	{
-		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
-	}
+    rt_uint32_t recved_event;
+    if (xRxEnable)
+    {
+        /* enable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+        /* switch 485 to receive mode */
+        rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW);
+    }
+    else
+    {
+        /* switch 485 to transmit mode */
+    	rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH);
+        /* disable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+    }
+    if (xTxEnable)
+    {
+        /* start serial transmit */
+        rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
+    }
+    else
+    {
+        /* stop serial transmit */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
+                RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
+                &recved_event);
+    }
 }
 
 void vMBPortClose(void)
 {
-	USART_ITConfig(USART1, USART_IT_TXE | USART_IT_RXNE, DISABLE);
-	USART_Cmd(USART1, DISABLE);
-}
-//默认一个从机 串口1 波特率可设置  奇偶检验可设置
-BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
-		eMBParity eParity)
-{
-	GPIO_InitTypeDef GPIO_InitStructure;
-	USART_InitTypeDef USART_InitStructure;
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//======================时钟初始化=======================================
-	RCC_APB2PeriphClockCmd(
-			RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1,
-			ENABLE);
-	//======================IO初始化=======================================	
-	//USART1_TX
-	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//USART1_RX
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//配置485发送和接收模式
-//    TODO   暂时先写B13 等之后组网测试时再修改
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
-	GPIO_Init(GPIOB, &GPIO_InitStructure);
-	//======================串口初始化=======================================
-	USART_InitStructure.USART_BaudRate = ulBaudRate;
-	//设置校验模式
-	switch (eParity)
-	{
-	case MB_PAR_NONE: //无校验
-		USART_InitStructure.USART_Parity = USART_Parity_No;
-		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
-		break;
-	case MB_PAR_ODD: //奇校验
-		USART_InitStructure.USART_Parity = USART_Parity_Odd;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	case MB_PAR_EVEN: //偶校验
-		USART_InitStructure.USART_Parity = USART_Parity_Even;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	default:
-		return FALSE;
-	}
-
-	USART_InitStructure.USART_StopBits = USART_StopBits_1;
-	USART_InitStructure.USART_HardwareFlowControl =
-			USART_HardwareFlowControl_None;
-	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-	if (ucPORT != 1)
-		return FALSE;
-
-	ENTER_CRITICAL_SECTION(); //关全局中断
-
-	USART_Init(USART1, &USART_InitStructure);
-	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-	USART_Cmd(USART1, ENABLE);
-
-	//=====================中断初始化======================================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-
-	EXIT_CRITICAL_SECTION(); //开全局中断
-
-	return TRUE;
+    serial->parent.close(&(serial->parent));
 }
 
 BOOL xMBPortSerialPutByte(CHAR ucByte)
 {
-	USART_SendData(USART1, ucByte);
-	return TRUE;
+    serial->parent.write(&(serial->parent), 0, &ucByte, 1);
+    return TRUE;
 }
 
 BOOL xMBPortSerialGetByte(CHAR * pucByte)
 {
-	*pucByte = USART_ReceiveData(USART1);
-	return TRUE;
+    serial->parent.read(&(serial->parent), 0, pucByte, 1);
+    return TRUE;
 }
 
 /* 
@@ -151,7 +177,7 @@ BOOL xMBPortSerialGetByte(CHAR * pucByte)
  */
 void prvvUARTTxReadyISR(void)
 {
-	pxMBFrameCBTransmitterEmpty();
+    pxMBFrameCBTransmitterEmpty();
 }
 
 /* 
@@ -162,28 +188,35 @@ void prvvUARTTxReadyISR(void)
  */
 void prvvUARTRxISR(void)
 {
-	pxMBFrameCBByteReceived();
+    pxMBFrameCBByteReceived();
 }
-/*******************************************************************************
- * Function Name  : USART1_IRQHandler
- * Description    : This function handles USART1 global interrupt request.
- * Input          : None
- * Output         : None
- * Return         : None
- *******************************************************************************/
-void USART1_IRQHandler(void)
-{
-	rt_interrupt_enter();
-	//接收中断
-	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
-	{
-		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
-		prvvUARTRxISR();
-	}
-	//发送中断
-	if (USART_GetITStatus(USART1, USART_IT_TXE) == SET)
-	{
-		prvvUARTTxReadyISR();
-	}
-	rt_interrupt_leave();
+
+/**
+ * Software simulation serial transmit IRQ handler.
+ *
+ * @param parameter parameter
+ */
+static void serial_soft_trans_irq(void* parameter) {
+    rt_uint32_t recved_event;
+    while (1)
+    {
+        /* waiting for serial transmit start */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
+                RT_WAITING_FOREVER, &recved_event);
+        /* execute modbus callback */
+        prvvUARTTxReadyISR();
+    }
+}
+
+/**
+ * This function is serial receive callback function
+ *
+ * @param dev the device of serial
+ * @param size the data size that receive
+ *
+ * @return return RT_EOK
+ */
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
+    prvvUARTRxISR();
+    return RT_EOK;
 }

+ 154 - 121
components/net/freemodbus-v1.6.0/port/portserial_m.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,123 +24,149 @@
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
 #include "mbport.h"
+#include "rtdevice.h"
+#include "bsp.h"
+
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Static variables ---------------------------------*/
+ALIGN(RT_ALIGN_SIZE)
+/* software simulation serial transmit IRQ handler thread stack */
+static rt_uint8_t serial_soft_trans_irq_stack[512];
+/* software simulation serial transmit IRQ handler thread */
+static struct rt_thread thread_serial_soft_trans_irq;
+/* serial event */
+static struct rt_event event_serial;
+/* modbus slave serial device */
+static rt_serial_t *serial;
+
+/* ----------------------- Defines ------------------------------------------*/
+/* serial transmit event */
+#define EVENT_SERIAL_TRANS_START    (1<<0)
 
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
 /* ----------------------- static functions ---------------------------------*/
 static void prvvUARTTxReadyISR(void);
 static void prvvUARTRxISR(void);
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
+static void serial_soft_trans_irq(void* parameter);
+
 /* ----------------------- Start implementation -----------------------------*/
+BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
+        eMBParity eParity)
+{
+    /**
+     * set 485 mode receive and transmit control IO
+     * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user
+     */
+	rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
+
+    /* set serial name */
+    if (ucPORT == 1) {
+#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
+        extern struct rt_serial_device serial1;
+        serial = &serial1;
+#endif
+    } else if (ucPORT == 2) {
+#if defined(RT_USING_UART2)
+        extern struct rt_serial_device serial2;
+        serial = &serial2;
+#endif
+    } else if (ucPORT == 3) {
+#if defined(RT_USING_UART3)
+        extern struct rt_serial_device serial3;
+        serial = &serial3;
+#endif
+    }
+    /* set serial configure parameter */
+    serial->config.baud_rate = ulBaudRate;
+    serial->config.stop_bits = STOP_BITS_1;
+    switch(eParity){
+    case MB_PAR_NONE: {
+        serial->config.data_bits = DATA_BITS_8;
+        serial->config.parity = PARITY_NONE;
+        break;
+    }
+    case MB_PAR_ODD: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_ODD;
+        break;
+    }
+    case MB_PAR_EVEN: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_EVEN;
+        break;
+    }
+    }
+    /* set serial configure */
+    serial->ops->configure(serial, &(serial->config));
+
+    /* open serial device */
+    if (!serial->parent.open(&serial->parent,
+            RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) {
+        serial->parent.rx_indicate = serial_rx_ind;
+    } else {
+        return FALSE;
+    }
+
+    /* software initialize */
+    rt_thread_init(&thread_serial_soft_trans_irq,
+                   "slave trans",
+                   serial_soft_trans_irq,
+                   RT_NULL,
+                   serial_soft_trans_irq_stack,
+                   sizeof(serial_soft_trans_irq_stack),
+                   10, 5);
+    rt_thread_startup(&thread_serial_soft_trans_irq);
+    rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
+
+    return TRUE;
+}
 
 void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
 {
-	if (xRxEnable)
-	{
-		MASTER_RS485_RECEIVE_MODE;
-		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
-	}
-	else
-	{
-		MASTER_RS485_SEND_MODE;
-		USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
-	}
-	if (xTxEnable)
-	{
-		USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
-	}
-	else
-	{
-		USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
-	}
+    rt_uint32_t recved_event;
+    if (xRxEnable)
+    {
+        /* enable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+        /* switch 485 to receive mode */
+		rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW);
+    }
+    else
+    {
+        /* switch 485 to transmit mode */
+    	rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH);
+        /* disable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+    }
+    if (xTxEnable)
+    {
+        /* start serial transmit */
+        rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
+    }
+    else
+    {
+        /* stop serial transmit */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
+                RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
+                &recved_event);
+    }
 }
 
 void vMBMasterPortClose(void)
 {
-	USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE);
-	USART_Cmd(USART2, DISABLE);
-}
-//默认一个主机 串口2 波特率可设置  奇偶检验可设置
-BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
-		eMBParity eParity)
-{
-	GPIO_InitTypeDef GPIO_InitStructure;
-	USART_InitTypeDef USART_InitStructure;
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//======================时钟初始化=======================================
-	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
-	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
-	//======================IO初始化=======================================	
-	//USART2_TX
-	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//USART2_RX
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//配置485发送和接收模式
-//    TODO   暂时先写B13 等之后组网测试时再修改
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
-	GPIO_Init(GPIOB, &GPIO_InitStructure);
-	//======================串口初始化=======================================
-	USART_InitStructure.USART_BaudRate = ulBaudRate;
-	//设置校验模式
-	switch (eParity)
-	{
-	case MB_PAR_NONE: //无校验
-		USART_InitStructure.USART_Parity = USART_Parity_No;
-		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
-		break;
-	case MB_PAR_ODD: //奇校验
-		USART_InitStructure.USART_Parity = USART_Parity_Odd;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	case MB_PAR_EVEN: //偶校验
-		USART_InitStructure.USART_Parity = USART_Parity_Even;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	default:
-		return FALSE;
-	}
-
-	USART_InitStructure.USART_StopBits = USART_StopBits_1;
-	USART_InitStructure.USART_HardwareFlowControl =
-			USART_HardwareFlowControl_None;
-	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-	if (ucPORT != 2)
-		return FALSE;
-
-	ENTER_CRITICAL_SECTION(); //关全局中断
-
-	USART_Init(USART2, &USART_InitStructure);
-	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
-	USART_Cmd(USART2, ENABLE);
-
-	//=====================中断初始化======================================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-
-	EXIT_CRITICAL_SECTION(); //开全局中断
-
-	return TRUE;
+	serial->parent.close(&(serial->parent));
 }
 
 BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
 {
-	USART_SendData(USART2, ucByte);
+    serial->parent.write(&(serial->parent), 0, &ucByte, 1);
 	return TRUE;
 }
 
 BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
 {
-	*pucByte = USART_ReceiveData(USART2);
-	return TRUE;
+    serial->parent.read(&(serial->parent), 0, pucByte, 1);
+    return TRUE;
 }
 
 /* 
@@ -152,7 +178,7 @@ BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
  */
 void prvvUARTTxReadyISR(void)
 {
-	pxMBMasterFrameCBTransmitterEmpty();
+    pxMBMasterFrameCBTransmitterEmpty();
 }
 
 /* 
@@ -163,30 +189,37 @@ void prvvUARTTxReadyISR(void)
  */
 void prvvUARTRxISR(void)
 {
-	pxMBMasterFrameCBByteReceived();
+    pxMBMasterFrameCBByteReceived();
 }
-/*******************************************************************************
- * Function Name  : USART2_IRQHandler
- * Description    : This function handles USART2 global interrupt request.
- * Input          : None
- * Output         : None
- * Return         : None
- *******************************************************************************/
-void USART2_IRQHandler(void)
-{
-	rt_interrupt_enter();
-	//接收中断
-	if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
-	{
-		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
-		prvvUARTRxISR();
-	}
-	//发送中断
-	if (USART_GetITStatus(USART2, USART_IT_TXE) == SET)
-	{
-		prvvUARTTxReadyISR();
-	}
-	rt_interrupt_leave();
+
+/**
+ * Software simulation serial transmit IRQ handler.
+ *
+ * @param parameter parameter
+ */
+static void serial_soft_trans_irq(void* parameter) {
+    rt_uint32_t recved_event;
+    while (1)
+    {
+        /* waiting for serial transmit start */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
+                RT_WAITING_FOREVER, &recved_event);
+        /* execute modbus callback */
+        prvvUARTTxReadyISR();
+    }
+}
+
+/**
+ * This function is serial receive callback function
+ *
+ * @param dev the device of serial
+ * @param size the data size that receive
+ *
+ * @return return RT_EOK
+ */
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
+    prvvUARTRxISR();
+    return RT_EOK;
 }
 
 #endif

+ 14 - 58
components/net/freemodbus-v1.6.0/port/porttimer.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -27,81 +27,37 @@
 #include "mbport.h"
 
 /* ----------------------- static functions ---------------------------------*/
+static struct rt_timer timer;
 static void prvvTIMERExpiredISR(void);
+static void timer_timeout_ind(void* parameter);
 
 /* ----------------------- Start implementation -----------------------------*/
 BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
 {
-
-	uint16_t PrescalerValue = 0;
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//====================================时钟初始化===========================
-	//使能定时器3时钟
-	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
-	//====================================定时器初始化===========================
-	//定时器时间基配置说明
-	//HCLK为72MHz,APB1经过2分频为36MHz
-	//TIM3的时钟倍频后为72MHz(硬件自动倍频,达到最大)
-	//TIM3的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us
-	//TIM最大计数值为usTim1Timerout50u
-	
-	PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
-	//定时器1初始化
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t) usTim1Timerout50us;
-	TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
-	//预装载使能
-	TIM_ARRPreloadConfig(TIM3, ENABLE);
-	//====================================中断初始化===========================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-	//清除溢出中断标志位
-	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
-	//定时器3溢出中断关闭
-	TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
-	//定时器3禁能
-	TIM_Cmd(TIM3, DISABLE);
-	return TRUE;
+    rt_timer_init(&timer, "slave timer",
+                   timer_timeout_ind, /* bind timeout callback function */
+                   RT_NULL,
+                   (50*usTim1Timerout50us)/(1000*1000/RT_TICK_PER_SECOND),
+                   RT_TIMER_FLAG_ONE_SHOT); /* one shot */
+    return TRUE;
 }
 
 void vMBPortTimersEnable()
 {
-	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
-	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM3, 0);
-	TIM_Cmd(TIM3, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBPortTimersDisable()
 {
-	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
-	TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
-	TIM_SetCounter(TIM3, 0);
-	TIM_Cmd(TIM3, DISABLE);
+    rt_timer_stop(&timer);
 }
 
 void prvvTIMERExpiredISR(void)
 {
-	(void) pxMBPortCBTimerExpired();
+    (void) pxMBPortCBTimerExpired();
 }
 
-void TIM3_IRQHandler(void)
+static void timer_timeout_ind(void* parameter)
 {
-	rt_interrupt_enter();
-	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
-	{
-		
-		TIM_ClearFlag(TIM3, TIM_FLAG_Update);	     //清中断标记
-		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);	 //清除定时器T3溢出中断标志位
-		prvvTIMERExpiredISR();
-	}
-	rt_interrupt_leave();
+    prvvTIMERExpiredISR();
 }

+ 35 - 85
components/net/freemodbus-v1.6.0/port/porttimer_m.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -27,10 +27,12 @@
 #include "mb_m.h"
 #include "mbport.h"
 
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
 /* ----------------------- Variables ----------------------------------------*/
 static USHORT usT35TimeOut50us;
-static USHORT usPrescalerValue = 0;
+static struct rt_timer timer;
+static void prvvTIMERExpiredISR(void);
+static void timer_timeout_ind(void* parameter);
 
 /* ----------------------- static functions ---------------------------------*/
 static void prvvTIMERExpiredISR(void);
@@ -38,120 +40,68 @@ static void prvvTIMERExpiredISR(void);
 /* ----------------------- Start implementation -----------------------------*/
 BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
 {
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//====================================时钟初始化===========================
-	//使能定时器2时钟
-	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
-	//====================================定时器初始化===========================
-	//定时器时间基配置说明
-	//HCLK为72MHz,APB1经过2分频为36MHz
-	//TIM2的时钟倍频后为72MHz(硬件自动倍频,达到最大)
-	//TIM2的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us
-	//TIM最大计数值为usTim1Timerout50u	
-	usPrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
-	//保存T35定时器计数值
-	usT35TimeOut50us = usTimeOut50us; 
-
-	//预装载使能
-	TIM_ARRPreloadConfig(TIM2, ENABLE);
-	//====================================中断初始化===========================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-	//清除溢出中断标志位
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	//定时器3溢出中断关闭
-	TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
-	//定时器3禁能
-	TIM_Cmd(TIM2, DISABLE);
-	return TRUE;
+    /* backup T35 ticks */
+    usT35TimeOut50us = usTimeOut50us;
+
+    rt_timer_init(&timer, "master timer",
+                   timer_timeout_ind, /* bind timeout callback function */
+                   RT_NULL,
+                   (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND),
+                   RT_TIMER_FLAG_ONE_SHOT); /* one shot */
+
+    return TRUE;
 }
 
 void vMBMasterPortTimersT35Enable()
 {
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+	rt_tick_t timer_tick = (50 * usT35TimeOut50us)
+			/ (1000 * 1000 / RT_TICK_PER_SECOND);
 
-	/* Set current timer mode,don't change it.*/
-	vMBMasterSetCurTimerMode(MB_TMODE_T35);
+    /* Set current timer mode, don't change it.*/
+    vMBMasterSetCurTimerMode(MB_TMODE_T35);
 
-	TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t) usT35TimeOut50us;
-	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
+	rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
 
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBMasterPortTimersConvertDelayEnable()
 {
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+	rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000;
 
-	/* Set current timer mode,don't change it.*/
-	vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
+    /* Set current timer mode, don't change it.*/
+    vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
 
-	TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_DELAY_MS_CONVERT * 1000 / 50);
-	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
+	rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
 
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBMasterPortTimersRespondTimeoutEnable()
 {
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+	rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000;
 
-	/* Set current timer mode,don't change it.*/
-	vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
+    /* Set current timer mode, don't change it.*/
+    vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
 
-	TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_TIMEOUT_MS_RESPOND * 1000 / 50);
-	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
+	rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
 
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBMasterPortTimersDisable()
 {
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, DISABLE);
+	rt_timer_stop(&timer);
 }
 
 void prvvTIMERExpiredISR(void)
 {
-	(void) pxMBMasterPortCBTimerExpired();
+    (void) pxMBMasterPortCBTimerExpired();
 }
 
-void TIM2_IRQHandler(void)
+static void timer_timeout_ind(void* parameter)
 {
-	rt_interrupt_enter();
-	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
-	{
-		
-		TIM_ClearFlag(TIM2, TIM_FLAG_Update);	     //清中断标记
-		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);	 //清除定时器TIM2溢出中断标志位
-		prvvTIMERExpiredISR();
-	}
-	rt_interrupt_leave();
+    prvvTIMERExpiredISR();
 }
 
 #endif

+ 175 - 238
components/net/freemodbus-v1.6.0/port/user_mb_app.c

@@ -1,4 +1,25 @@
+/*
+ * FreeModbus Libary: user callback functions and buffer define in slave mode
+ * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
+ *
+ * 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: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $
+ */
 #include "user_mb_app.h"
+
 /*------------------------Slave mode use these variables----------------------*/
 //Slave mode:DiscreteInputs variables
 USHORT   usSDiscInStart                               = S_DISCRETE_INPUT_START;
@@ -20,81 +41,41 @@ USHORT   usSRegInBuf[S_REG_INPUT_NREGS]               ;
 //Slave mode:HoldingRegister variables
 USHORT   usSRegHoldStart                              = S_REG_HOLDING_START;
 USHORT   usSRegHoldBuf[S_REG_HOLDING_NREGS]           ;
-/*-----------------------Master mode use these variables----------------------*/
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
-//Master mode:DiscreteInputs variables
-USHORT   usMDiscInStart                             = M_DISCRETE_INPUT_START;
-#if      M_DISCRETE_INPUT_NDISCRETES%8
-UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
-#else
-UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
-#endif
-//Master mode:Coils variables
-USHORT   usMCoilStart                               = M_COIL_START;
-#if      M_COIL_NCOILS%8
-UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
-#else
-UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
-#endif
-//Master mode:InputRegister variables
-USHORT   usMRegInStart                              = M_REG_INPUT_START;
-USHORT   usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
-//Master mode:HoldingRegister variables
-USHORT   usMRegHoldStart                            = M_REG_HOLDING_START;
-USHORT   usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
-#endif
-//******************************输入寄存器回调函数**********************************
-//函数定义: eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
-//描    述:输入寄存器相关的功能(读、连续读)
-//入口参数:pucRegBuffer : 回调函数将Modbus寄存器的当前值写入的缓冲区
-//			usAddress    : 寄存器的起始地址,输入寄存器的地址范围是1-65535。
-//			usNRegs      : 寄存器数量
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
+
+/**
+ * Modbus slave input register callback function.
+ *
+ * @param pucRegBuffer input register buffer
+ * @param usAddress input register address
+ * @param usNRegs input register number
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-    int             iRegIndex;
+    USHORT          iRegIndex;
     USHORT *        pusRegInputBuf;
-    UCHAR           REG_INPUT_START;
-    UCHAR           REG_INPUT_NREGS;
-    UCHAR           usRegInStart;
+    USHORT          REG_INPUT_START;
+    USHORT          REG_INPUT_NREGS;
+    USHORT          usRegInStart;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress()];
-    	REG_INPUT_START = M_REG_INPUT_START;
-    	REG_INPUT_NREGS = M_REG_INPUT_NREGS;
-    	usRegInStart = usMRegInStart;
-    }
-    else
-    {
-    	pusRegInputBuf = usSRegInBuf;
-    	REG_INPUT_START = S_REG_INPUT_START;
-    	REG_INPUT_NREGS = S_REG_INPUT_NREGS;
-    	usRegInStart = usSRegInStart;
-    }
+    pusRegInputBuf = usSRegInBuf;
+    REG_INPUT_START = S_REG_INPUT_START;
+    REG_INPUT_NREGS = S_REG_INPUT_NREGS;
+    usRegInStart = usSRegInStart;
 
-    if( ( usAddress >= REG_INPUT_START )
-        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_INPUT_START)
+            && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
     {
-        iRegIndex = ( int )( usAddress - usRegInStart );
-        while( usNRegs > 0 )
+        iRegIndex = usAddress - usRegInStart;
+        while (usNRegs > 0)
         {
-            //Determine the master or slave
-            if (xMBMasterGetCBRunInMasterMode())
-            {
-            	pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
-                pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
-            }
-            else
-            {
-				*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] >> 8 );
-				*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] & 0xFF );
-            }
+            *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8);
+            *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF);
             iRegIndex++;
             usNRegs--;
         }
@@ -106,67 +87,55 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 
     return eStatus;
 }
-//******************************保持寄存器回调函数**********************************
-//函数定义: eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
-//描    述:保持寄存器相关的功能(读、连续读、写、连续写)
-//入口参数:pucRegBuffer : 如果需要更新用户寄存器数值,这个缓冲区必须指向新的寄存器数值。
-//                         如果协议栈想知道当前的数值,回调函数必须将当前值写入这个缓冲区
-//			usAddress    : 寄存器的起始地址。
-//			usNRegs      : 寄存器数量
-//          eMode        : 如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。
-//                         如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
+
+/**
+ * Modbus slave holding register callback function.
+ *
+ * @param pucRegBuffer holding register buffer
+ * @param usAddress holding register address
+ * @param usNRegs holding register number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNRegs, eMBRegisterMode eMode)
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-    int             iRegIndex;
+    USHORT          iRegIndex;
     USHORT *        pusRegHoldingBuf;
-    UCHAR           REG_HOLDING_START;
-    UCHAR           REG_HOLDING_NREGS;
-    UCHAR           usRegHoldStart;
+    USHORT          REG_HOLDING_START;
+    USHORT          REG_HOLDING_NREGS;
+    USHORT          usRegHoldStart;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress()];
-    	REG_HOLDING_START = M_REG_HOLDING_START;
-    	REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
-    	usRegHoldStart = usMRegHoldStart;
-    	//If mode is read,the master will wirte the received date to bufffer.
-    	eMode = MB_REG_WRITE;
-    }
-    else
-    {
-    	pusRegHoldingBuf = usSRegHoldBuf;
-    	REG_HOLDING_START = S_REG_HOLDING_START;
-    	REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
-    	usRegHoldStart = usSRegHoldStart;
-    }
+    pusRegHoldingBuf = usSRegHoldBuf;
+    REG_HOLDING_START = S_REG_HOLDING_START;
+    REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
+    usRegHoldStart = usSRegHoldStart;
 
-    if( ( usAddress >= REG_HOLDING_START ) &&
-        ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_HOLDING_START)
+            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
     {
-        iRegIndex = ( int )( usAddress - usRegHoldStart );
-        switch ( eMode )
+        iRegIndex = usAddress - usRegHoldStart;
+        switch (eMode)
         {
-            /* Pass current register values to the protocol stack. */
+        /* read current register values from the protocol stack. */
         case MB_REG_READ:
-            while( usNRegs > 0 )
+            while (usNRegs > 0)
             {
-				*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 );
-				*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF );
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                 iRegIndex++;
                 usNRegs--;
             }
             break;
 
-            /* Update current register values with new values from the
-             * protocol stack. */
+        /* write current register values with new values from the protocol stack. */
         case MB_REG_WRITE:
-            while( usNRegs > 0 )
+            while (usNRegs > 0)
             {
                 pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                 pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
@@ -182,83 +151,76 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi
     }
     return eStatus;
 }
-//****************************线圈状态寄存器回调函数********************************
-//函数定义: eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
-//描    述:线圈状态寄存器相关的功能(读、连续读、写、连续写)
-//入口参数:pucRegBuffer : 位组成一个字节,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
-//                         如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置位0。
-//			usAddress    : 第一个线圈地址。
-//			usNCoils     : 请求的线圈个数
-//          eMode        ;如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。
-//                         如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
+
+/**
+ * Modbus slave coils callback function.
+ *
+ * @param pucRegBuffer coils buffer
+ * @param usAddress coils address
+ * @param usNCoils coils number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNCoils, eMBRegisterMode eMode)
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-    int             iRegIndex , iRegBitIndex , iNReg;
-	UCHAR *         pucCoilBuf;
-    UCHAR           COIL_START;
-    UCHAR           COIL_NCOILS;
-    UCHAR           usCoilStart;
-    iNReg =  usNCoils / 8 + 1;        //占用寄存器数量
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucCoilBuf;
+    USHORT          COIL_START;
+    USHORT          COIL_NCOILS;
+    USHORT          usCoilStart;
+    iNReg =  usNCoils / 8 + 1;
 
+    pucCoilBuf = ucSCoilBuf;
+    COIL_START = S_COIL_START;
+    COIL_NCOILS = S_COIL_NCOILS;
+    usCoilStart = usSCoilStart;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress()];
-    	COIL_START = M_COIL_START;
-    	COIL_NCOILS = M_COIL_NCOILS;
-    	usCoilStart = usMCoilStart;
-    	//If mode is read,the master will wirte the received date to bufffer.
-    	eMode = MB_REG_WRITE;
-    }
-    else
-    {
-    	pucCoilBuf = ucSCoilBuf;
-    	COIL_START = S_COIL_START;
-    	COIL_NCOILS = S_COIL_NCOILS;
-    	usCoilStart = usSCoilStart;
-    }
+    /* it already plus one in modbus function method. */
+    usAddress--;
 
     if( ( usAddress >= COIL_START ) &&
         ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
     {
-        iRegIndex    = ( int )( usAddress - usCoilStart ) / 8 ;    //每个寄存器存8个
-		iRegBitIndex = ( int )( usAddress - usCoilStart ) % 8 ;	   //相对于寄存器内部的位地址
+        iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
         switch ( eMode )
         {
-            /* Pass current coil values to the protocol stack. */
+        /* read current coil values from the protocol stack. */
         case MB_REG_READ:
-            while( iNReg > 0 )
+            while (iNReg > 0)
             {
-				*pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8);
-                iNReg --;
+                *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
+                        iRegBitIndex, 8);
+                iNReg--;
             }
-			pucRegBuffer --;
-			usNCoils = usNCoils % 8;                        //余下的线圈数	
-			*pucRegBuffer = *pucRegBuffer <<(8 - usNCoils); //高位补零
-			*pucRegBuffer = *pucRegBuffer >>(8 - usNCoils);
+            pucRegBuffer--;
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* filling zero to high bit */
+            *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
+            *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
             break;
 
-            /* Update current coil values with new values from the
-             * protocol stack. */
+            /* write current coil values with new values from the protocol stack. */
         case MB_REG_WRITE:
-            while(iNReg > 1)									 //最后面余下来的数单独算
+            while (iNReg > 1)
             {
-				xMBUtilSetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex  , 8 , *pucRegBuffer++);
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
+                        *pucRegBuffer++);
                 iNReg--;
             }
-			usNCoils = usNCoils % 8;                            //余下的线圈数
-			if (usNCoils != 0)                                  //xMBUtilSetBits方法 在操作位数量为0时存在bug
-			{
-				xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
-						*pucRegBuffer++);
-			}
-			break;
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* xMBUtilSetBits has bug when ucNBits is zero */
+            if (usNCoils != 0)
+            {
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
+                        *pucRegBuffer++);
+            }
+            break;
         }
     }
     else
@@ -267,78 +229,52 @@ eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegis
     }
     return eStatus;
 }
-//****************************离散输入寄存器回调函数********************************
-//函数定义: eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
-//描    述:离散输入寄存器相关的功能(读、连续读)
-//入口参数:pucRegBuffer : 用当前的线圈数据更新这个寄存器,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
-//                         如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置为0。
-//			usAddress    : 离散输入的起始地址
-//			usNDiscrete  : 离散输入点数量
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
+
+/**
+ * Modbus slave discrete callback function.
+ *
+ * @param pucRegBuffer discrete buffer
+ * @param usAddress discrete address
+ * @param usNDiscrete discrete number
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-	int             iRegIndex , iRegBitIndex , iNReg;
-	UCHAR *         pucDiscreteInputBuf;
-    UCHAR           DISCRETE_INPUT_START;
-    UCHAR           DISCRETE_INPUT_NDISCRETES;
-    UCHAR           usDiscreteInputStart;
-	iNReg =  usNDiscrete / 8 + 1;        //占用寄存器数量
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucDiscreteInputBuf;
+    USHORT          DISCRETE_INPUT_START;
+    USHORT          DISCRETE_INPUT_NDISCRETES;
+    USHORT          usDiscreteInputStart;
+    iNReg =  usNDiscrete / 8 + 1;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress()];
-    	DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
-    	DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
-    	usDiscreteInputStart = usMDiscInStart;
-    }
-    else
-    {
-    	pucDiscreteInputBuf = ucSDiscInBuf;
-    	DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
-    	DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
-    	usDiscreteInputStart = usSDiscInStart;
-    }
+    pucDiscreteInputBuf = ucSDiscInBuf;
+    DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
+    DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
+    usDiscreteInputStart = usSDiscInStart;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
 
-    if( ( usAddress >= DISCRETE_INPUT_START )
-        && ( usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES ) )
+    if ((usAddress >= DISCRETE_INPUT_START)
+            && (usAddress + usNDiscrete    <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
     {
-        iRegIndex    = ( int )( usAddress - usDiscreteInputStart ) / 8 ;    //每个寄存器存8个
-		iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ;	   //相对于寄存器内部的位地址
+        iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; //每个寄存器存8个
+        iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; //相对于寄存器内部的位地址
 
-	    //Determine the master or slave
-	    if (xMBMasterGetCBRunInMasterMode())
-	    {
-			/* Update current coil values with new values from the
-			 * protocol stack. */
-			while(iNReg > 1)									 //最后面余下来的数单独算
-			{
-				xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex  , 8 , *pucRegBuffer++);
-				iNReg--;
-			}
-			usNDiscrete = usNDiscrete % 8;                        //余下的线圈数
-			if (usNDiscrete != 0)                                 //xMBUtilSetBits方法 在操作位数量为0时存在bug
-			{
-				xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
-						usNDiscrete, *pucRegBuffer++);
-			}
-	    }
-	    else
-	    {
-			while( iNReg > 0 )
-			{
-				*pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8);
-				iNReg --;
-			}
-			pucRegBuffer --;
-			usNDiscrete = usNDiscrete % 8;                     //余下的线圈数
-			*pucRegBuffer = *pucRegBuffer <<(8 - usNDiscrete); //高位补零
-			*pucRegBuffer = *pucRegBuffer >>(8 - usNDiscrete);
-	    }
+        while (iNReg > 0)
+        {
+            *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
+                    iRegBitIndex, 8);
+            iNReg--;
+        }
+        pucRegBuffer--;
+        /* last discrete */
+        usNDiscrete = usNDiscrete % 8;
+        /* filling zero to high bit */
+        *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete);
+        *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete);
     }
     else
     {
@@ -347,3 +283,4 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
 
     return eStatus;
 }
+

+ 27 - 33
components/net/freemodbus-v1.6.0/port/user_mb_app.h

@@ -1,4 +1,4 @@
-#ifndef	USER_APP
+#ifndef    USER_APP
 #define USER_APP
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
@@ -8,47 +8,41 @@
 #include "mbutils.h"
 
 /* -----------------------Slave Defines -------------------------------------*/
-#define S_DISCRETE_INPUT_START        1
+#define S_DISCRETE_INPUT_START        0
 #define S_DISCRETE_INPUT_NDISCRETES   16
-#define S_COIL_START                  1
+#define S_COIL_START                  0
 #define S_COIL_NCOILS                 64
-#define S_REG_INPUT_START             1
+#define S_REG_INPUT_START             0
 #define S_REG_INPUT_NREGS             100
-#define S_REG_HOLDING_START           1
+#define S_REG_HOLDING_START           0
 #define S_REG_HOLDING_NREGS           100
-//从机模式:在保持寄存器中,各个地址对应的功能定义
-#define          S_HD_RESERVE                     0		  //保留
-#define          S_HD_CPU_USAGE_MAJOR             1         //当前CPU利用率的整数位
-#define          S_HD_CPU_USAGE_MINOR             2         //当前CPU利用率的小数位
-
-//从机模式:在输入寄存器中,各个地址对应的功能定义
-#define          S_IN_RESERVE                     0		  //保留
-
-//从机模式:在线圈中,各个地址对应的功能定义
-#define          S_CO_RESERVE                     2		  //保留
-
-//从机模式:在离散输入中,各个地址对应的功能定义
-#define          S_DI_RESERVE                     1		  //保留
+/* salve mode: holding register's all address */
+#define          S_HD_RESERVE                     0
+#define          S_HD_CPU_USAGE_MAJOR             1
+#define          S_HD_CPU_USAGE_MINOR             2
+/* salve mode: input register's all address */
+#define          S_IN_RESERVE                     0
+/* salve mode: coil's all address */
+#define          S_CO_RESERVE                     0
+/* salve mode: discrete's all address */
+#define          S_DI_RESERVE                     0
 
 /* -----------------------Master Defines -------------------------------------*/
-#define M_DISCRETE_INPUT_START        1
+#define M_DISCRETE_INPUT_START        0
 #define M_DISCRETE_INPUT_NDISCRETES   16
-#define M_COIL_START                  1
+#define M_COIL_START                  0
 #define M_COIL_NCOILS                 64
-#define M_REG_INPUT_START             1
+#define M_REG_INPUT_START             0
 #define M_REG_INPUT_NREGS             100
-#define M_REG_HOLDING_START           1
+#define M_REG_HOLDING_START           0
 #define M_REG_HOLDING_NREGS           100
-//主机模式:在保持寄存器中,各个地址对应的功能定义
-#define          M_HD_RESERVE                     0		  //保留
-
-//主机模式:在输入寄存器中,各个地址对应的功能定义
-#define          M_IN_RESERVE                     0		  //保留
-
-//主机模式:在线圈中,各个地址对应的功能定义
-#define          M_CO_RESERVE                     2		  //保留
-
-//主机模式:在离散输入中,各个地址对应的功能定义
-#define          M_DI_RESERVE                     1		  //保留
+/* master mode: holding register's all address */
+#define          M_HD_RESERVE                     0
+/* master mode: input register's all address */
+#define          M_IN_RESERVE                     0
+/* master mode: coil's all address */
+#define          M_CO_RESERVE                     0
+/* master mode: discrete's all address */
+#define          M_DI_RESERVE                     0
 
 #endif

+ 294 - 0
components/net/freemodbus-v1.6.0/port/user_mb_app_m.c

@@ -0,0 +1,294 @@
+/*
+ * FreeModbus Libary: user callback functions and buffer define in master mode
+ * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
+ *
+ * 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: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $
+ */
+#include "user_mb_app.h"
+
+/*-----------------------Master mode use these variables----------------------*/
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+//Master mode:DiscreteInputs variables
+USHORT   usMDiscInStart                             = M_DISCRETE_INPUT_START;
+#if      M_DISCRETE_INPUT_NDISCRETES%8
+UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
+#else
+UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
+#endif
+//Master mode:Coils variables
+USHORT   usMCoilStart                               = M_COIL_START;
+#if      M_COIL_NCOILS%8
+UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
+#else
+UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
+#endif
+//Master mode:InputRegister variables
+USHORT   usMRegInStart                              = M_REG_INPUT_START;
+USHORT   usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
+//Master mode:HoldingRegister variables
+USHORT   usMRegHoldStart                            = M_REG_HOLDING_START;
+USHORT   usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
+
+/**
+ * Modbus master input register callback function.
+ *
+ * @param pucRegBuffer input register buffer
+ * @param usAddress input register address
+ * @param usNRegs input register number
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex;
+    USHORT *        pusRegInputBuf;
+    USHORT          REG_INPUT_START;
+    USHORT          REG_INPUT_NREGS;
+    USHORT          usRegInStart;
+
+    pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1];
+    REG_INPUT_START = M_REG_INPUT_START;
+    REG_INPUT_NREGS = M_REG_INPUT_NREGS;
+    usRegInStart = usMRegInStart;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_INPUT_START)
+            && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
+    {
+        iRegIndex = usAddress - usRegInStart;
+        while (usNRegs > 0)
+        {
+            pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
+            pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
+            iRegIndex++;
+            usNRegs--;
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+
+    return eStatus;
+}
+
+/**
+ * Modbus master holding register callback function.
+ *
+ * @param pucRegBuffer holding register buffer
+ * @param usAddress holding register address
+ * @param usNRegs holding register number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNRegs, eMBRegisterMode eMode)
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex;
+    USHORT *        pusRegHoldingBuf;
+    USHORT          REG_HOLDING_START;
+    USHORT          REG_HOLDING_NREGS;
+    USHORT          usRegHoldStart;
+
+    pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1];
+    REG_HOLDING_START = M_REG_HOLDING_START;
+    REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
+    usRegHoldStart = usMRegHoldStart;
+    /* if mode is read, the master will write the received date to buffer. */
+    eMode = MB_REG_WRITE;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_HOLDING_START)
+            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
+    {
+        iRegIndex = usAddress - usRegHoldStart;
+        switch (eMode)
+        {
+        /* read current register values from the protocol stack. */
+        case MB_REG_READ:
+            while (usNRegs > 0)
+            {
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
+                iRegIndex++;
+                usNRegs--;
+            }
+            break;
+        /* write current register values with new values from the protocol stack. */
+        case MB_REG_WRITE:
+            while (usNRegs > 0)
+            {
+                pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
+                pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
+                iRegIndex++;
+                usNRegs--;
+            }
+            break;
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+    return eStatus;
+}
+
+/**
+ * Modbus master coils callback function.
+ *
+ * @param pucRegBuffer coils buffer
+ * @param usAddress coils address
+ * @param usNCoils coils number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNCoils, eMBRegisterMode eMode)
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucCoilBuf;
+    USHORT          COIL_START;
+    USHORT          COIL_NCOILS;
+    USHORT          usCoilStart;
+    iNReg =  usNCoils / 8 + 1;
+
+    pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1];
+    COIL_START = M_COIL_START;
+    COIL_NCOILS = M_COIL_NCOILS;
+    usCoilStart = usMCoilStart;
+
+    /* if mode is read,the master will write the received date to buffer. */
+    eMode = MB_REG_WRITE;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= COIL_START)
+            && (usAddress + usNCoils <= COIL_START + COIL_NCOILS))
+    {
+        iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
+        switch (eMode)
+        {
+         /* read current coil values from the protocol stack. */
+        case MB_REG_READ:
+            while (iNReg > 0)
+            {
+                *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
+                        iRegBitIndex, 8);
+                iNReg--;
+            }
+            pucRegBuffer--;
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* filling zero to high bit */
+            *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
+            *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
+            break;
+
+        /* write current coil values with new values from the protocol stack. */
+        case MB_REG_WRITE:
+            while (iNReg > 1)
+            {
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
+                        *pucRegBuffer++);
+                iNReg--;
+            }
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* xMBUtilSetBits has bug when ucNBits is zero */
+            if (usNCoils != 0)
+            {
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
+                        *pucRegBuffer++);
+            }
+            break;
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+    return eStatus;
+}
+
+/**
+ * Modbus master discrete callback function.
+ *
+ * @param pucRegBuffer discrete buffer
+ * @param usAddress discrete address
+ * @param usNDiscrete discrete number
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucDiscreteInputBuf;
+    USHORT          DISCRETE_INPUT_START;
+    USHORT          DISCRETE_INPUT_NDISCRETES;
+    USHORT          usDiscreteInputStart;
+    iNReg =  usNDiscrete / 8 + 1;
+
+    pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1];
+    DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
+    DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
+    usDiscreteInputStart = usMDiscInStart;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= DISCRETE_INPUT_START)
+            && (usAddress + usNDiscrete    <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
+    {
+        iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
+
+        /* write current discrete values with new values from the protocol stack. */
+        while (iNReg > 1)
+        {
+            xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8,
+                    *pucRegBuffer++);
+            iNReg--;
+        }
+        /* last discrete */
+        usNDiscrete = usNDiscrete % 8;
+        /* xMBUtilSetBits has bug when ucNBits is zero */
+        if (usNDiscrete != 0)
+        {
+            xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
+                    usNDiscrete, *pucRegBuffer++);
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+
+    return eStatus;
+}
+#endif