mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-02-21 01:07:18 +08:00
[modbus]port modbus master and slave by rtt device framework.
This commit is contained in:
parent
d8bbb5f126
commit
2a14e4071c
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: LPC214X Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2007 Tiago Prado Lone <tiago@maxwellbohr.com.br>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* 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
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* 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 --------------------------------*/
|
/* ----------------------- System includes --------------------------------*/
|
||||||
@ -24,16 +24,15 @@
|
|||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
/* ----------------------- Variables ----------------------------------------*/
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
|
static rt_base_t level;
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
void EnterCriticalSection(void)
|
void EnterCriticalSection(void)
|
||||||
{
|
{
|
||||||
//关闭全局中断
|
level = rt_hw_interrupt_disable();
|
||||||
__disable_irq();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExitCriticalSection(void)
|
void ExitCriticalSection(void)
|
||||||
{
|
{
|
||||||
//开启全局中断
|
rt_hw_interrupt_enable(level);
|
||||||
__enable_irq();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: BARE Port
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -34,18 +34,9 @@
|
|||||||
#define PR_BEGIN_EXTERN_C extern "C" {
|
#define PR_BEGIN_EXTERN_C extern "C" {
|
||||||
#define PR_END_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 ENTER_CRITICAL_SECTION() EnterCriticalSection()
|
||||||
#define EXIT_CRITICAL_SECTION() ExitCriticalSection()
|
#define EXIT_CRITICAL_SECTION() ExitCriticalSection()
|
||||||
|
|
||||||
void EnterCriticalSection(void);
|
|
||||||
void ExitCriticalSection(void);
|
|
||||||
|
|
||||||
typedef uint8_t BOOL;
|
typedef uint8_t BOOL;
|
||||||
|
|
||||||
typedef unsigned char UCHAR;
|
typedef unsigned char UCHAR;
|
||||||
@ -65,4 +56,7 @@ typedef int32_t LONG;
|
|||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void EnterCriticalSection(void);
|
||||||
|
void ExitCriticalSection(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: STM32 Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -24,35 +24,45 @@
|
|||||||
#include "mbport.h"
|
#include "mbport.h"
|
||||||
|
|
||||||
/* ----------------------- Variables ----------------------------------------*/
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
static eMBEventType eQueuedEvent;
|
static struct rt_event xSlaveOsEvent;
|
||||||
static BOOL xEventInQueue;
|
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
BOOL
|
BOOL
|
||||||
xMBPortEventInit( void )
|
xMBPortEventInit( void )
|
||||||
{
|
{
|
||||||
xEventInQueue = FALSE;
|
rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
xMBPortEventPost( eMBEventType eEvent )
|
xMBPortEventPost( eMBEventType eEvent )
|
||||||
{
|
{
|
||||||
xEventInQueue = TRUE;
|
rt_event_send(&xSlaveOsEvent, eEvent);
|
||||||
eQueuedEvent = eEvent;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
xMBPortEventGet( eMBEventType * eEvent )
|
xMBPortEventGet( eMBEventType * eEvent )
|
||||||
{
|
{
|
||||||
BOOL xEventHappened = FALSE;
|
rt_uint32_t recvedEvent;
|
||||||
|
/* waiting forever OS event */
|
||||||
if( xEventInQueue )
|
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;
|
case EV_READY:
|
||||||
xEventInQueue = FALSE;
|
*eEvent = EV_READY;
|
||||||
xEventHappened = TRUE;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: STM32 Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -21,41 +21,219 @@
|
|||||||
|
|
||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "mb.h"
|
#include "mb.h"
|
||||||
|
#include "mb_m.h"
|
||||||
#include "mbport.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 ----------------------------------------*/
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
static eMBMasterEventType eMasterQueuedEvent;
|
static struct rt_semaphore xMasterRunRes;
|
||||||
static BOOL xMasterEventInQueue;
|
static struct rt_event xMasterOsEvent;
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
BOOL
|
BOOL
|
||||||
xMBMasterPortEventInit( void )
|
xMBMasterPortEventInit( void )
|
||||||
{
|
{
|
||||||
xMasterEventInQueue = FALSE;
|
rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
xMBMasterPortEventPost( eMBMasterEventType eEvent )
|
xMBMasterPortEventPost( eMBMasterEventType eEvent )
|
||||||
{
|
{
|
||||||
xMasterEventInQueue = TRUE;
|
rt_event_send(&xMasterOsEvent, eEvent);
|
||||||
eMasterQueuedEvent = eEvent;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
xMBMasterPortEventGet( eMBMasterEventType * eEvent )
|
xMBMasterPortEventGet( eMBMasterEventType * eEvent )
|
||||||
{
|
{
|
||||||
BOOL xEventHappened = FALSE;
|
rt_uint32_t recvedEvent;
|
||||||
|
/* waiting forever OS event */
|
||||||
if( xMasterEventInQueue )
|
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)
|
||||||
{
|
{
|
||||||
*eEvent = eMasterQueuedEvent;
|
case EV_MASTER_READY:
|
||||||
xMasterEventInQueue = FALSE;
|
*eEvent = EV_MASTER_READY;
|
||||||
xEventHappened = TRUE;
|
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 xEventHappened;
|
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. */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
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 eErrStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: STM32 Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -24,122 +24,148 @@
|
|||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "mb.h"
|
#include "mb.h"
|
||||||
#include "mbport.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 functions ---------------------------------*/
|
||||||
static void prvvUARTTxReadyISR(void);
|
static void prvvUARTTxReadyISR(void);
|
||||||
static void prvvUARTRxISR(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 -----------------------------*/
|
/* ----------------------- 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)
|
void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
|
||||||
{
|
{
|
||||||
if (xRxEnable)
|
rt_uint32_t recved_event;
|
||||||
{
|
if (xRxEnable)
|
||||||
SLAVE_RS485_RECEIVE_MODE;
|
{
|
||||||
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
|
/* enable RX interrupt */
|
||||||
}
|
serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
|
||||||
else
|
/* switch 485 to receive mode */
|
||||||
{
|
rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW);
|
||||||
SLAVE_RS485_SEND_MODE;
|
}
|
||||||
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
|
else
|
||||||
}
|
{
|
||||||
if (xTxEnable)
|
/* switch 485 to transmit mode */
|
||||||
{
|
rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH);
|
||||||
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
|
/* disable RX interrupt */
|
||||||
}
|
serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
|
||||||
else
|
}
|
||||||
{
|
if (xTxEnable)
|
||||||
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
|
{
|
||||||
}
|
/* 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)
|
void vMBPortClose(void)
|
||||||
{
|
{
|
||||||
USART_ITConfig(USART1, USART_IT_TXE | USART_IT_RXNE, DISABLE);
|
serial->parent.close(&(serial->parent));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL xMBPortSerialPutByte(CHAR ucByte)
|
BOOL xMBPortSerialPutByte(CHAR ucByte)
|
||||||
{
|
{
|
||||||
USART_SendData(USART1, ucByte);
|
serial->parent.write(&(serial->parent), 0, &ucByte, 1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL xMBPortSerialGetByte(CHAR * pucByte)
|
BOOL xMBPortSerialGetByte(CHAR * pucByte)
|
||||||
{
|
{
|
||||||
*pucByte = USART_ReceiveData(USART1);
|
serial->parent.read(&(serial->parent), 0, pucByte, 1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -151,7 +177,7 @@ BOOL xMBPortSerialGetByte(CHAR * pucByte)
|
|||||||
*/
|
*/
|
||||||
void prvvUARTTxReadyISR(void)
|
void prvvUARTTxReadyISR(void)
|
||||||
{
|
{
|
||||||
pxMBFrameCBTransmitterEmpty();
|
pxMBFrameCBTransmitterEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -162,28 +188,35 @@ void prvvUARTTxReadyISR(void)
|
|||||||
*/
|
*/
|
||||||
void prvvUARTRxISR(void)
|
void prvvUARTRxISR(void)
|
||||||
{
|
{
|
||||||
pxMBFrameCBByteReceived();
|
pxMBFrameCBByteReceived();
|
||||||
}
|
}
|
||||||
/*******************************************************************************
|
|
||||||
* Function Name : USART1_IRQHandler
|
/**
|
||||||
* Description : This function handles USART1 global interrupt request.
|
* Software simulation serial transmit IRQ handler.
|
||||||
* Input : None
|
*
|
||||||
* Output : None
|
* @param parameter parameter
|
||||||
* Return : None
|
*/
|
||||||
*******************************************************************************/
|
static void serial_soft_trans_irq(void* parameter) {
|
||||||
void USART1_IRQHandler(void)
|
rt_uint32_t recved_event;
|
||||||
{
|
while (1)
|
||||||
rt_interrupt_enter();
|
{
|
||||||
//接收中断
|
/* waiting for serial transmit start */
|
||||||
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
|
rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
|
||||||
{
|
RT_WAITING_FOREVER, &recved_event);
|
||||||
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
|
/* execute modbus callback */
|
||||||
prvvUARTRxISR();
|
prvvUARTTxReadyISR();
|
||||||
}
|
}
|
||||||
//发送中断
|
}
|
||||||
if (USART_GetITStatus(USART1, USART_IT_TXE) == SET)
|
|
||||||
{
|
/**
|
||||||
prvvUARTTxReadyISR();
|
* This function is serial receive callback function
|
||||||
}
|
*
|
||||||
rt_interrupt_leave();
|
* @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;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: STM32 Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -24,123 +24,149 @@
|
|||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "mb.h"
|
#include "mb.h"
|
||||||
#include "mbport.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 functions ---------------------------------*/
|
||||||
static void prvvUARTTxReadyISR(void);
|
static void prvvUARTTxReadyISR(void);
|
||||||
static void prvvUARTRxISR(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 -----------------------------*/
|
/* ----------------------- 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)
|
void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
|
||||||
{
|
{
|
||||||
if (xRxEnable)
|
rt_uint32_t recved_event;
|
||||||
{
|
if (xRxEnable)
|
||||||
MASTER_RS485_RECEIVE_MODE;
|
{
|
||||||
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
|
/* enable RX interrupt */
|
||||||
}
|
serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
|
||||||
else
|
/* switch 485 to receive mode */
|
||||||
{
|
rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW);
|
||||||
MASTER_RS485_SEND_MODE;
|
}
|
||||||
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
|
else
|
||||||
}
|
{
|
||||||
if (xTxEnable)
|
/* switch 485 to transmit mode */
|
||||||
{
|
rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH);
|
||||||
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
|
/* disable RX interrupt */
|
||||||
}
|
serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
|
||||||
else
|
}
|
||||||
{
|
if (xTxEnable)
|
||||||
USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
|
{
|
||||||
}
|
/* 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)
|
void vMBMasterPortClose(void)
|
||||||
{
|
{
|
||||||
USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE);
|
serial->parent.close(&(serial->parent));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
|
BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
|
||||||
{
|
{
|
||||||
USART_SendData(USART2, ucByte);
|
serial->parent.write(&(serial->parent), 0, &ucByte, 1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
|
BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
|
||||||
{
|
{
|
||||||
*pucByte = USART_ReceiveData(USART2);
|
serial->parent.read(&(serial->parent), 0, pucByte, 1);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,7 +178,7 @@ BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
|
|||||||
*/
|
*/
|
||||||
void prvvUARTTxReadyISR(void)
|
void prvvUARTTxReadyISR(void)
|
||||||
{
|
{
|
||||||
pxMBMasterFrameCBTransmitterEmpty();
|
pxMBMasterFrameCBTransmitterEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -163,30 +189,37 @@ void prvvUARTTxReadyISR(void)
|
|||||||
*/
|
*/
|
||||||
void prvvUARTRxISR(void)
|
void prvvUARTRxISR(void)
|
||||||
{
|
{
|
||||||
pxMBMasterFrameCBByteReceived();
|
pxMBMasterFrameCBByteReceived();
|
||||||
}
|
}
|
||||||
/*******************************************************************************
|
|
||||||
* Function Name : USART2_IRQHandler
|
/**
|
||||||
* Description : This function handles USART2 global interrupt request.
|
* Software simulation serial transmit IRQ handler.
|
||||||
* Input : None
|
*
|
||||||
* Output : None
|
* @param parameter parameter
|
||||||
* Return : None
|
*/
|
||||||
*******************************************************************************/
|
static void serial_soft_trans_irq(void* parameter) {
|
||||||
void USART2_IRQHandler(void)
|
rt_uint32_t recved_event;
|
||||||
{
|
while (1)
|
||||||
rt_interrupt_enter();
|
{
|
||||||
//接收中断
|
/* waiting for serial transmit start */
|
||||||
if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
|
rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
|
||||||
{
|
RT_WAITING_FOREVER, &recved_event);
|
||||||
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
|
/* execute modbus callback */
|
||||||
prvvUARTRxISR();
|
prvvUARTTxReadyISR();
|
||||||
}
|
}
|
||||||
//发送中断
|
}
|
||||||
if (USART_GetITStatus(USART2, USART_IT_TXE) == SET)
|
|
||||||
{
|
/**
|
||||||
prvvUARTTxReadyISR();
|
* This function is serial receive callback function
|
||||||
}
|
*
|
||||||
rt_interrupt_leave();
|
* @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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: STM32 Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -27,81 +27,37 @@
|
|||||||
#include "mbport.h"
|
#include "mbport.h"
|
||||||
|
|
||||||
/* ----------------------- static functions ---------------------------------*/
|
/* ----------------------- static functions ---------------------------------*/
|
||||||
|
static struct rt_timer timer;
|
||||||
static void prvvTIMERExpiredISR(void);
|
static void prvvTIMERExpiredISR(void);
|
||||||
|
static void timer_timeout_ind(void* parameter);
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
|
BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
|
||||||
{
|
{
|
||||||
|
rt_timer_init(&timer, "slave timer",
|
||||||
uint16_t PrescalerValue = 0;
|
timer_timeout_ind, /* bind timeout callback function */
|
||||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
RT_NULL,
|
||||||
NVIC_InitTypeDef NVIC_InitStructure;
|
(50*usTim1Timerout50us)/(1000*1000/RT_TICK_PER_SECOND),
|
||||||
//====================================时钟初始化===========================
|
RT_TIMER_FLAG_ONE_SHOT); /* one shot */
|
||||||
//使能定时器3时钟
|
return TRUE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBPortTimersEnable()
|
void vMBPortTimersEnable()
|
||||||
{
|
{
|
||||||
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
|
rt_timer_start(&timer);
|
||||||
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
|
|
||||||
TIM_SetCounter(TIM3, 0);
|
|
||||||
TIM_Cmd(TIM3, ENABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBPortTimersDisable()
|
void vMBPortTimersDisable()
|
||||||
{
|
{
|
||||||
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
|
rt_timer_stop(&timer);
|
||||||
TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
|
|
||||||
TIM_SetCounter(TIM3, 0);
|
|
||||||
TIM_Cmd(TIM3, DISABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void prvvTIMERExpiredISR(void)
|
void prvvTIMERExpiredISR(void)
|
||||||
{
|
{
|
||||||
(void) pxMBPortCBTimerExpired();
|
(void) pxMBPortCBTimerExpired();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIM3_IRQHandler(void)
|
static void timer_timeout_ind(void* parameter)
|
||||||
{
|
{
|
||||||
rt_interrupt_enter();
|
prvvTIMERExpiredISR();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* FreeModbus Libary: STM32 Port
|
* FreeModbus Libary: RT-Thread Port
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -27,10 +27,12 @@
|
|||||||
#include "mb_m.h"
|
#include "mb_m.h"
|
||||||
#include "mbport.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 ----------------------------------------*/
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
static USHORT usT35TimeOut50us;
|
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 functions ---------------------------------*/
|
||||||
static void prvvTIMERExpiredISR(void);
|
static void prvvTIMERExpiredISR(void);
|
||||||
@ -38,120 +40,68 @@ static void prvvTIMERExpiredISR(void);
|
|||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
|
BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
|
||||||
{
|
{
|
||||||
NVIC_InitTypeDef NVIC_InitStructure;
|
/* backup T35 ticks */
|
||||||
//====================================时钟初始化===========================
|
usT35TimeOut50us = usTimeOut50us;
|
||||||
//使能定时器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;
|
|
||||||
|
|
||||||
//预装载使能
|
rt_timer_init(&timer, "master timer",
|
||||||
TIM_ARRPreloadConfig(TIM2, ENABLE);
|
timer_timeout_ind, /* bind timeout callback function */
|
||||||
//====================================中断初始化===========================
|
RT_NULL,
|
||||||
//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
|
(50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND),
|
||||||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
|
RT_TIMER_FLAG_ONE_SHOT); /* one shot */
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
|
||||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
return TRUE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersT35Enable()
|
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.*/
|
/* Set current timer mode, don't change it.*/
|
||||||
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
||||||
|
|
||||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
|
rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
|
||||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
|
||||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
|
||||||
TIM_TimeBaseStructure.TIM_Period = (uint16_t) usT35TimeOut50us;
|
|
||||||
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
|
|
||||||
|
|
||||||
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
rt_timer_start(&timer);
|
||||||
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
|
||||||
TIM_SetCounter(TIM2, 0);
|
|
||||||
TIM_Cmd(TIM2, ENABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersConvertDelayEnable()
|
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.*/
|
/* Set current timer mode, don't change it.*/
|
||||||
vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
|
vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
|
||||||
|
|
||||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
|
rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
|
||||||
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);
|
|
||||||
|
|
||||||
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
rt_timer_start(&timer);
|
||||||
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
|
||||||
TIM_SetCounter(TIM2, 0);
|
|
||||||
TIM_Cmd(TIM2, ENABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersRespondTimeoutEnable()
|
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.*/
|
/* Set current timer mode, don't change it.*/
|
||||||
vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
|
vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
|
||||||
|
|
||||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
|
rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
|
||||||
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);
|
|
||||||
|
|
||||||
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
rt_timer_start(&timer);
|
||||||
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
|
||||||
TIM_SetCounter(TIM2, 0);
|
|
||||||
TIM_Cmd(TIM2, ENABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vMBMasterPortTimersDisable()
|
void vMBMasterPortTimersDisable()
|
||||||
{
|
{
|
||||||
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
rt_timer_stop(&timer);
|
||||||
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
|
|
||||||
TIM_SetCounter(TIM2, 0);
|
|
||||||
TIM_Cmd(TIM2, DISABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void prvvTIMERExpiredISR(void)
|
void prvvTIMERExpiredISR(void)
|
||||||
{
|
{
|
||||||
(void) pxMBMasterPortCBTimerExpired();
|
(void) pxMBMasterPortCBTimerExpired();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIM2_IRQHandler(void)
|
static void timer_timeout_ind(void* parameter)
|
||||||
{
|
{
|
||||||
rt_interrupt_enter();
|
prvvTIMERExpiredISR();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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"
|
#include "user_mb_app.h"
|
||||||
|
|
||||||
/*------------------------Slave mode use these variables----------------------*/
|
/*------------------------Slave mode use these variables----------------------*/
|
||||||
//Slave mode:DiscreteInputs variables
|
//Slave mode:DiscreteInputs variables
|
||||||
USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
|
USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
|
||||||
@ -20,81 +41,41 @@ USHORT usSRegInBuf[S_REG_INPUT_NREGS] ;
|
|||||||
//Slave mode:HoldingRegister variables
|
//Slave mode:HoldingRegister variables
|
||||||
USHORT usSRegHoldStart = S_REG_HOLDING_START;
|
USHORT usSRegHoldStart = S_REG_HOLDING_START;
|
||||||
USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ;
|
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
|
* Modbus slave input register callback function.
|
||||||
USHORT usMDiscInStart = M_DISCRETE_INPUT_START;
|
*
|
||||||
#if M_DISCRETE_INPUT_NDISCRETES%8
|
* @param pucRegBuffer input register buffer
|
||||||
UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
|
* @param usAddress input register address
|
||||||
#else
|
* @param usNRegs input register number
|
||||||
UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
|
*
|
||||||
#endif
|
* @return result
|
||||||
//Master mode:Coils variables
|
*/
|
||||||
USHORT usMCoilStart = M_COIL_START;
|
eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
|
||||||
#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 )
|
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
int iRegIndex;
|
USHORT iRegIndex;
|
||||||
USHORT * pusRegInputBuf;
|
USHORT * pusRegInputBuf;
|
||||||
UCHAR REG_INPUT_START;
|
USHORT REG_INPUT_START;
|
||||||
UCHAR REG_INPUT_NREGS;
|
USHORT REG_INPUT_NREGS;
|
||||||
UCHAR usRegInStart;
|
USHORT usRegInStart;
|
||||||
|
|
||||||
//Determine the master or slave
|
pusRegInputBuf = usSRegInBuf;
|
||||||
if (xMBMasterGetCBRunInMasterMode())
|
REG_INPUT_START = S_REG_INPUT_START;
|
||||||
{
|
REG_INPUT_NREGS = S_REG_INPUT_NREGS;
|
||||||
pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress()];
|
usRegInStart = usSRegInStart;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( usAddress >= REG_INPUT_START )
|
/* it already plus one in modbus function method. */
|
||||||
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
|
usAddress--;
|
||||||
|
|
||||||
|
if ((usAddress >= REG_INPUT_START)
|
||||||
|
&& (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
|
||||||
{
|
{
|
||||||
iRegIndex = ( int )( usAddress - usRegInStart );
|
iRegIndex = usAddress - usRegInStart;
|
||||||
while( usNRegs > 0 )
|
while (usNRegs > 0)
|
||||||
{
|
{
|
||||||
//Determine the master or slave
|
*pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8);
|
||||||
if (xMBMasterGetCBRunInMasterMode())
|
*pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF);
|
||||||
{
|
|
||||||
pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
|
|
||||||
pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] >> 8 );
|
|
||||||
*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] & 0xFF );
|
|
||||||
}
|
|
||||||
iRegIndex++;
|
iRegIndex++;
|
||||||
usNRegs--;
|
usNRegs--;
|
||||||
}
|
}
|
||||||
@ -106,67 +87,55 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
|
|||||||
|
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
//******************************保持寄存器回调函数**********************************
|
|
||||||
//函数定义: eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
|
/**
|
||||||
//描 述:保持寄存器相关的功能(读、连续读、写、连续写)
|
* Modbus slave holding register callback function.
|
||||||
//入口参数:pucRegBuffer : 如果需要更新用户寄存器数值,这个缓冲区必须指向新的寄存器数值。
|
*
|
||||||
// 如果协议栈想知道当前的数值,回调函数必须将当前值写入这个缓冲区
|
* @param pucRegBuffer holding register buffer
|
||||||
// usAddress : 寄存器的起始地址。
|
* @param usAddress holding register address
|
||||||
// usNRegs : 寄存器数量
|
* @param usNRegs holding register number
|
||||||
// eMode : 如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。
|
* @param eMode read or write
|
||||||
// 如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中
|
*
|
||||||
//出口参数:eMBErrorCode : 这个函数将返回的错误码
|
* @return result
|
||||||
//备 注:Editor:Armink 2010-10-31 Company: BXXJS
|
*/
|
||||||
//**********************************************************************************
|
eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
|
||||||
eMBErrorCode
|
USHORT usNRegs, eMBRegisterMode eMode)
|
||||||
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
|
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
int iRegIndex;
|
USHORT iRegIndex;
|
||||||
USHORT * pusRegHoldingBuf;
|
USHORT * pusRegHoldingBuf;
|
||||||
UCHAR REG_HOLDING_START;
|
USHORT REG_HOLDING_START;
|
||||||
UCHAR REG_HOLDING_NREGS;
|
USHORT REG_HOLDING_NREGS;
|
||||||
UCHAR usRegHoldStart;
|
USHORT usRegHoldStart;
|
||||||
|
|
||||||
//Determine the master or slave
|
pusRegHoldingBuf = usSRegHoldBuf;
|
||||||
if (xMBMasterGetCBRunInMasterMode())
|
REG_HOLDING_START = S_REG_HOLDING_START;
|
||||||
{
|
REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
|
||||||
pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress()];
|
usRegHoldStart = usSRegHoldStart;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( usAddress >= REG_HOLDING_START ) &&
|
/* it already plus one in modbus function method. */
|
||||||
( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
|
usAddress--;
|
||||||
|
|
||||||
|
if ((usAddress >= REG_HOLDING_START)
|
||||||
|
&& (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
|
||||||
{
|
{
|
||||||
iRegIndex = ( int )( usAddress - usRegHoldStart );
|
iRegIndex = usAddress - usRegHoldStart;
|
||||||
switch ( eMode )
|
switch (eMode)
|
||||||
{
|
{
|
||||||
/* Pass current register values to the protocol stack. */
|
/* read current register values from the protocol stack. */
|
||||||
case MB_REG_READ:
|
case MB_REG_READ:
|
||||||
while( usNRegs > 0 )
|
while (usNRegs > 0)
|
||||||
{
|
{
|
||||||
*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 );
|
*pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
|
||||||
*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF );
|
*pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
|
||||||
iRegIndex++;
|
iRegIndex++;
|
||||||
usNRegs--;
|
usNRegs--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Update current register values with new values from the
|
/* write current register values with new values from the protocol stack. */
|
||||||
* protocol stack. */
|
|
||||||
case MB_REG_WRITE:
|
case MB_REG_WRITE:
|
||||||
while( usNRegs > 0 )
|
while (usNRegs > 0)
|
||||||
{
|
{
|
||||||
pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
|
pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
|
||||||
pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
|
pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
|
||||||
@ -182,83 +151,76 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi
|
|||||||
}
|
}
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
//****************************线圈状态寄存器回调函数********************************
|
|
||||||
//函数定义: eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
|
/**
|
||||||
//描 述:线圈状态寄存器相关的功能(读、连续读、写、连续写)
|
* Modbus slave coils callback function.
|
||||||
//入口参数:pucRegBuffer : 位组成一个字节,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
|
*
|
||||||
// 如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置位0。
|
* @param pucRegBuffer coils buffer
|
||||||
// usAddress : 第一个线圈地址。
|
* @param usAddress coils address
|
||||||
// usNCoils : 请求的线圈个数
|
* @param usNCoils coils number
|
||||||
// eMode ;如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。
|
* @param eMode read or write
|
||||||
// 如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中
|
*
|
||||||
//出口参数:eMBErrorCode : 这个函数将返回的错误码
|
* @return result
|
||||||
//备 注:Editor:Armink 2010-10-31 Company: BXXJS
|
*/
|
||||||
//**********************************************************************************
|
eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
|
||||||
eMBErrorCode
|
USHORT usNCoils, eMBRegisterMode eMode)
|
||||||
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
|
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
int iRegIndex , iRegBitIndex , iNReg;
|
USHORT iRegIndex , iRegBitIndex , iNReg;
|
||||||
UCHAR * pucCoilBuf;
|
UCHAR * pucCoilBuf;
|
||||||
UCHAR COIL_START;
|
USHORT COIL_START;
|
||||||
UCHAR COIL_NCOILS;
|
USHORT COIL_NCOILS;
|
||||||
UCHAR usCoilStart;
|
USHORT usCoilStart;
|
||||||
iNReg = usNCoils / 8 + 1; //占用寄存器数量
|
iNReg = usNCoils / 8 + 1;
|
||||||
|
|
||||||
|
pucCoilBuf = ucSCoilBuf;
|
||||||
|
COIL_START = S_COIL_START;
|
||||||
|
COIL_NCOILS = S_COIL_NCOILS;
|
||||||
|
usCoilStart = usSCoilStart;
|
||||||
|
|
||||||
//Determine the master or slave
|
/* it already plus one in modbus function method. */
|
||||||
if (xMBMasterGetCBRunInMasterMode())
|
usAddress--;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( usAddress >= COIL_START ) &&
|
if( ( usAddress >= COIL_START ) &&
|
||||||
( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
|
( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
|
||||||
{
|
{
|
||||||
iRegIndex = ( int )( usAddress - usCoilStart ) / 8 ; //每个寄存器存8个
|
iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
|
||||||
iRegBitIndex = ( int )( usAddress - usCoilStart ) % 8 ; //相对于寄存器内部的位地址
|
iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
|
||||||
switch ( eMode )
|
switch ( eMode )
|
||||||
{
|
{
|
||||||
/* Pass current coil values to the protocol stack. */
|
/* read current coil values from the protocol stack. */
|
||||||
case MB_REG_READ:
|
case MB_REG_READ:
|
||||||
while( iNReg > 0 )
|
while (iNReg > 0)
|
||||||
{
|
{
|
||||||
*pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8);
|
*pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
|
||||||
iNReg --;
|
iRegBitIndex, 8);
|
||||||
}
|
|
||||||
pucRegBuffer --;
|
|
||||||
usNCoils = usNCoils % 8; //余下的线圈数
|
|
||||||
*pucRegBuffer = *pucRegBuffer <<(8 - usNCoils); //高位补零
|
|
||||||
*pucRegBuffer = *pucRegBuffer >>(8 - usNCoils);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Update current coil values with new values from the
|
|
||||||
* protocol stack. */
|
|
||||||
case MB_REG_WRITE:
|
|
||||||
while(iNReg > 1) //最后面余下来的数单独算
|
|
||||||
{
|
|
||||||
xMBUtilSetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++);
|
|
||||||
iNReg--;
|
iNReg--;
|
||||||
}
|
}
|
||||||
usNCoils = usNCoils % 8; //余下的线圈数
|
pucRegBuffer--;
|
||||||
if (usNCoils != 0) //xMBUtilSetBits方法 在操作位数量为0时存在bug
|
/* last coils */
|
||||||
{
|
usNCoils = usNCoils % 8;
|
||||||
xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
|
/* filling zero to high bit */
|
||||||
*pucRegBuffer++);
|
*pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
|
||||||
}
|
*pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
|
||||||
break;
|
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
|
else
|
||||||
@ -267,78 +229,52 @@ eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegis
|
|||||||
}
|
}
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
//****************************离散输入寄存器回调函数********************************
|
|
||||||
//函数定义: eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
/**
|
||||||
//描 述:离散输入寄存器相关的功能(读、连续读)
|
* Modbus slave discrete callback function.
|
||||||
//入口参数:pucRegBuffer : 用当前的线圈数据更新这个寄存器,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
|
*
|
||||||
// 如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置为0。
|
* @param pucRegBuffer discrete buffer
|
||||||
// usAddress : 离散输入的起始地址
|
* @param usAddress discrete address
|
||||||
// usNDiscrete : 离散输入点数量
|
* @param usNDiscrete discrete number
|
||||||
//出口参数:eMBErrorCode : 这个函数将返回的错误码
|
*
|
||||||
//备 注:Editor:Armink 2010-10-31 Company: BXXJS
|
* @return result
|
||||||
//**********************************************************************************
|
*/
|
||||||
eMBErrorCode
|
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
||||||
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
int iRegIndex , iRegBitIndex , iNReg;
|
USHORT iRegIndex , iRegBitIndex , iNReg;
|
||||||
UCHAR * pucDiscreteInputBuf;
|
UCHAR * pucDiscreteInputBuf;
|
||||||
UCHAR DISCRETE_INPUT_START;
|
USHORT DISCRETE_INPUT_START;
|
||||||
UCHAR DISCRETE_INPUT_NDISCRETES;
|
USHORT DISCRETE_INPUT_NDISCRETES;
|
||||||
UCHAR usDiscreteInputStart;
|
USHORT usDiscreteInputStart;
|
||||||
iNReg = usNDiscrete / 8 + 1; //占用寄存器数量
|
iNReg = usNDiscrete / 8 + 1;
|
||||||
|
|
||||||
//Determine the master or slave
|
pucDiscreteInputBuf = ucSDiscInBuf;
|
||||||
if (xMBMasterGetCBRunInMasterMode())
|
DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
|
||||||
{
|
DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
|
||||||
pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress()];
|
usDiscreteInputStart = usSDiscInStart;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( usAddress >= DISCRETE_INPUT_START )
|
/* it already plus one in modbus function method. */
|
||||||
&& ( usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES ) )
|
usAddress--;
|
||||||
{
|
|
||||||
iRegIndex = ( int )( usAddress - usDiscreteInputStart ) / 8 ; //每个寄存器存8个
|
|
||||||
iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ; //相对于寄存器内部的位地址
|
|
||||||
|
|
||||||
//Determine the master or slave
|
if ((usAddress >= DISCRETE_INPUT_START)
|
||||||
if (xMBMasterGetCBRunInMasterMode())
|
&& (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
|
||||||
{
|
{
|
||||||
/* Update current coil values with new values from the
|
iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; //每个寄存器存8个
|
||||||
* protocol stack. */
|
iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; //相对于寄存器内部的位地址
|
||||||
while(iNReg > 1) //最后面余下来的数单独算
|
|
||||||
{
|
while (iNReg > 0)
|
||||||
xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++);
|
{
|
||||||
iNReg--;
|
*pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
|
||||||
}
|
iRegBitIndex, 8);
|
||||||
usNDiscrete = usNDiscrete % 8; //余下的线圈数
|
iNReg--;
|
||||||
if (usNDiscrete != 0) //xMBUtilSetBits方法 在操作位数量为0时存在bug
|
}
|
||||||
{
|
pucRegBuffer--;
|
||||||
xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
|
/* last discrete */
|
||||||
usNDiscrete, *pucRegBuffer++);
|
usNDiscrete = usNDiscrete % 8;
|
||||||
}
|
/* filling zero to high bit */
|
||||||
}
|
*pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete);
|
||||||
else
|
*pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete);
|
||||||
{
|
|
||||||
while( iNReg > 0 )
|
|
||||||
{
|
|
||||||
*pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8);
|
|
||||||
iNReg --;
|
|
||||||
}
|
|
||||||
pucRegBuffer --;
|
|
||||||
usNDiscrete = usNDiscrete % 8; //余下的线圈数
|
|
||||||
*pucRegBuffer = *pucRegBuffer <<(8 - usNDiscrete); //高位补零
|
|
||||||
*pucRegBuffer = *pucRegBuffer >>(8 - usNDiscrete);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -347,3 +283,4 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
|||||||
|
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#ifndef USER_APP
|
#ifndef USER_APP
|
||||||
#define USER_APP
|
#define USER_APP
|
||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "mb.h"
|
#include "mb.h"
|
||||||
@ -8,47 +8,41 @@
|
|||||||
#include "mbutils.h"
|
#include "mbutils.h"
|
||||||
|
|
||||||
/* -----------------------Slave Defines -------------------------------------*/
|
/* -----------------------Slave Defines -------------------------------------*/
|
||||||
#define S_DISCRETE_INPUT_START 1
|
#define S_DISCRETE_INPUT_START 0
|
||||||
#define S_DISCRETE_INPUT_NDISCRETES 16
|
#define S_DISCRETE_INPUT_NDISCRETES 16
|
||||||
#define S_COIL_START 1
|
#define S_COIL_START 0
|
||||||
#define S_COIL_NCOILS 64
|
#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_INPUT_NREGS 100
|
||||||
#define S_REG_HOLDING_START 1
|
#define S_REG_HOLDING_START 0
|
||||||
#define S_REG_HOLDING_NREGS 100
|
#define S_REG_HOLDING_NREGS 100
|
||||||
//从机模式:在保持寄存器中,各个地址对应的功能定义
|
/* salve mode: holding register's all address */
|
||||||
#define S_HD_RESERVE 0 //保留
|
#define S_HD_RESERVE 0
|
||||||
#define S_HD_CPU_USAGE_MAJOR 1 //当前CPU利用率的整数位
|
#define S_HD_CPU_USAGE_MAJOR 1
|
||||||
#define S_HD_CPU_USAGE_MINOR 2 //当前CPU利用率的小数位
|
#define S_HD_CPU_USAGE_MINOR 2
|
||||||
|
/* salve mode: input register's all address */
|
||||||
//从机模式:在输入寄存器中,各个地址对应的功能定义
|
#define S_IN_RESERVE 0
|
||||||
#define S_IN_RESERVE 0 //保留
|
/* salve mode: coil's all address */
|
||||||
|
#define S_CO_RESERVE 0
|
||||||
//从机模式:在线圈中,各个地址对应的功能定义
|
/* salve mode: discrete's all address */
|
||||||
#define S_CO_RESERVE 2 //保留
|
#define S_DI_RESERVE 0
|
||||||
|
|
||||||
//从机模式:在离散输入中,各个地址对应的功能定义
|
|
||||||
#define S_DI_RESERVE 1 //保留
|
|
||||||
|
|
||||||
/* -----------------------Master Defines -------------------------------------*/
|
/* -----------------------Master Defines -------------------------------------*/
|
||||||
#define M_DISCRETE_INPUT_START 1
|
#define M_DISCRETE_INPUT_START 0
|
||||||
#define M_DISCRETE_INPUT_NDISCRETES 16
|
#define M_DISCRETE_INPUT_NDISCRETES 16
|
||||||
#define M_COIL_START 1
|
#define M_COIL_START 0
|
||||||
#define M_COIL_NCOILS 64
|
#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_INPUT_NREGS 100
|
||||||
#define M_REG_HOLDING_START 1
|
#define M_REG_HOLDING_START 0
|
||||||
#define M_REG_HOLDING_NREGS 100
|
#define M_REG_HOLDING_NREGS 100
|
||||||
//主机模式:在保持寄存器中,各个地址对应的功能定义
|
/* master mode: holding register's all address */
|
||||||
#define M_HD_RESERVE 0 //保留
|
#define M_HD_RESERVE 0
|
||||||
|
/* master mode: input register's all address */
|
||||||
//主机模式:在输入寄存器中,各个地址对应的功能定义
|
#define M_IN_RESERVE 0
|
||||||
#define M_IN_RESERVE 0 //保留
|
/* master mode: coil's all address */
|
||||||
|
#define M_CO_RESERVE 0
|
||||||
//主机模式:在线圈中,各个地址对应的功能定义
|
/* master mode: discrete's all address */
|
||||||
#define M_CO_RESERVE 2 //保留
|
#define M_DI_RESERVE 0
|
||||||
|
|
||||||
//主机模式:在离散输入中,各个地址对应的功能定义
|
|
||||||
#define M_DI_RESERVE 1 //保留
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
294
components/net/freemodbus-v1.6.0/port/user_mb_app_m.c
Normal file
294
components/net/freemodbus-v1.6.0/port/user_mb_app_m.c
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user