1、【增加】FreeModbus主机轮训线程;

2、【增加】Modbus主机写寄存器功能,目前测试暂未通过;
3、【修改】串口2时钟配置错误,导致无法发送数据的Bug;
4、【增加】FreeModbus主机发送数据缓冲区;

Signed-off-by: armink <armink.ztl@gmail.com>
This commit is contained in:
armink 2013-08-29 16:45:56 +08:00
parent 5cece07cd7
commit a23f9528fb
13 changed files with 744 additions and 674 deletions

View File

@ -39,6 +39,7 @@
#define DELAY_SYS_RUN_LED DELAY_MS(500) //系统指示灯延时500ms
#define DELAY_SYS_SLEEP_LED DELAY_MS(1000) //系统指示灯延时1s
#define DELAY_MB_SLAVE_POLL DELAY_MS(10) //Modbus从机轮训时间
#define DELAY_MB_MASTER_POLL DELAY_MS(10) //Modbus主机轮训时间
#endif

View File

@ -13,13 +13,16 @@ uint8_t CpuUsageMajor, CpuUsageMinor; //CPUʹ
//====================操作系统各线程优先级==================================
#define thread_SysMonitor_Prio 11
#define thread_ModbusSlavePoll_Prio 10
#define thread_ModbusMasterPoll_Prio 9
ALIGN(RT_ALIGN_SIZE)
//====================操作系统各线程堆栈====================================
static rt_uint8_t thread_SysMonitor_stack[256];
static rt_uint8_t thread_ModbusSlavePoll_stack[512];
static rt_uint8_t thread_ModbusMasterPoll_stack[512];
struct rt_thread thread_SysMonitor;
struct rt_thread thread_ModbusSlavePoll;
struct rt_thread thread_ModbusMasterPoll;
//***************************系统监控线程***************************
//函数定义: void thread_entry_SysRunLed(void* parameter)
@ -29,6 +32,8 @@ struct rt_thread thread_ModbusSlavePoll;
//******************************************************************
void thread_entry_SysMonitor(void* parameter)
{
extern void vMBMasterReadHoldReg(UCHAR ucSlaveAddress, USHORT usRegAddress, USHORT ucRegValue);
while (1)
{
cpu_usage_get(&CpuUsageMajor, &CpuUsageMinor);
@ -41,10 +46,12 @@ void thread_entry_SysMonitor(void* parameter)
LED_LED2_OFF;
rt_thread_delay(DELAY_SYS_RUN_LED);
IWDG_Feed(); //喂狗
//Test Modbus Master
vMBMasterReadHoldReg(1,1,rt_tick_get()%65535);
}
}
//*************************** Modbus从机线程***************************
//************************ Modbus从机轮训线程***************************
//函数定义: void thread_entry_ModbusSlavePoll(void* parameter)
//入口参数:无
//出口参数:无
@ -61,6 +68,23 @@ void thread_entry_ModbusSlavePoll(void* parameter)
}
}
//************************ Modbus主机轮训线程***************************
//函数定义: void thread_entry_ModbusMasterPoll(void* parameter)
//入口参数:无
//出口参数:无
//备 注EditorArmink 2013-08-28 Company: BXXJS
//******************************************************************
void thread_entry_ModbusMasterPoll(void* parameter)
{
eMBMasterInit(MB_RTU, 2, 115200, MB_PAR_EVEN);
eMBMasterEnable();
while (1)
{
eMBMasterPoll();
rt_thread_delay(DELAY_MB_MASTER_POLL);
}
}
//**********************系统初始化函数********************************
//函数定义: int rt_application_init(void)
//入口参数:无
@ -75,12 +99,17 @@ int rt_application_init(void)
rt_thread_startup(&thread_SysMonitor);
rt_thread_init(&thread_ModbusSlavePoll, "MBSlavePoll",
thread_entry_ModbusSlavePoll, RT_NULL,
thread_ModbusSlavePoll_stack,
thread_entry_ModbusSlavePoll, RT_NULL, thread_ModbusSlavePoll_stack,
sizeof(thread_ModbusSlavePoll_stack), thread_ModbusSlavePoll_Prio,
5);
rt_thread_startup(&thread_ModbusSlavePoll);
rt_thread_init(&thread_ModbusMasterPoll, "MBMasterPoll",
thread_entry_ModbusMasterPoll, RT_NULL, thread_ModbusMasterPoll_stack,
sizeof(thread_ModbusMasterPoll_stack), thread_ModbusMasterPoll_Prio,
5);
rt_thread_startup(&thread_ModbusMasterPoll);
return 0;
}

View File

@ -67,8 +67,6 @@ static void RCC_Configuration(void)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//配置ADC转换时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div8); //9M
//启动USART1 USART4
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//启动DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟
/* Enable ADC1 and GPIOC clock */
@ -93,8 +91,6 @@ static void NVIC_Configuration(void)
// Set the Vector Table base location at 0x08000000
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}
/*******************************************************************************
* Function Name : GPIO_Configuration
@ -126,31 +122,6 @@ static void GPIO_Configuration(void)
}
/*******************************************************************************
* Function Name : USART1_Configuration
* Description : NUSART1设置
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void USART1_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//使能串口1的接收中断
USART_Cmd(USART1, ENABLE);
}
//*******************初始化独立看门狗*************************************
//函数定义: void IWDG_Configuration(void)
//描 述:初始化独立看门狗

View File

@ -62,11 +62,11 @@
/* ----------------------- Static variables ---------------------------------*/
volatile UCHAR ucMBMasterSendAddress;
volatile UCHAR ucMBMasterSndAddress;
volatile BOOL bMBRunInMasterMode = FALSE;
static eMBMode eMBCurrentMode;
static UCHAR ucMasterRTUBuf[MB_PDU_SIZE_MAX];
static UCHAR * pucMasterPUDBuf = ucMasterRTUBuf + 1;
UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX];
static UCHAR * pucMasterPUDSndBuf = ucMasterRTUSndBuf + 1;
static UCHAR ucMasterSendPDULength;
static enum
@ -253,6 +253,7 @@ eMBMasterDisable( void )
eMBErrorCode
eMBMasterPoll( void )
{
static UCHAR *ucMBFrame;
static UCHAR ucRcvAddress;
static UCHAR ucFunctionCode;
static USHORT usLength;
@ -278,9 +279,9 @@ eMBMasterPoll( void )
break;
case EV_MASTER_FRAME_RECEIVED:
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &pucMasterPUDBuf, &usLength );
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
/* Check if the frame is for us. If not ,send an error process event. */
if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterSendAddress ) )
if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterSndAddress ) )
{
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
}
@ -291,7 +292,7 @@ eMBMasterPoll( void )
break;
case EV_MASTER_EXECUTE:
ucFunctionCode = (ucMasterRTUBuf + 1)[MB_PDU_FUNC_OFF];
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
eException = MB_EX_ILLEGAL_FUNCTION;
for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
{
@ -303,7 +304,7 @@ eMBMasterPoll( void )
else if( xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode )
{
bMBRunInMasterMode = TRUE;
eException = xMasterFuncHandlers[i].pxHandler( pucMasterPUDBuf, &usLength );
eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
bMBRunInMasterMode = FALSE;
break;
}
@ -311,7 +312,7 @@ eMBMasterPoll( void )
break;
case EV_MASTER_FRAME_SENT:
eStatus = peMBMasterFrameSendCur( ucMBMasterSendAddress, pucMasterPUDBuf, ucMasterSendPDULength );
eStatus = peMBMasterFrameSendCur( ucMBMasterSndAddress, pucMasterPUDSndBuf, ucMasterSendPDULength );
break;
case EV_MASTER_ERROR_PROCESS:
@ -321,4 +322,16 @@ eMBMasterPoll( void )
return MB_ENOERR;
}
//Test Modbus Master
void vMBMasterReadHoldReg(UCHAR ucSlaveAddress, USHORT usRegAddress, USHORT ucRegValue)
{
ucMBMasterSndAddress = ucSlaveAddress;
pucMasterPUDSndBuf[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER;
pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 0] = usRegAddress / 256;
pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 1] = usRegAddress % 256;
pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 3] = ucRegValue / 256;
pucMasterPUDSndBuf[MB_PDU_DATA_OFF + 4] = ucRegValue % 256;
ucMasterSendPDULength = 5;
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
}
#endif

View File

@ -71,7 +71,8 @@ typedef enum
static volatile eMBMasterSndState eSndState;
static volatile eMBMasterRcvState eRcvState;
static volatile UCHAR ucMasterRTUBuf[MB_SER_PDU_SIZE_MAX];
extern UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX];
volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX];
static volatile UCHAR *pucMasterSndBufferCur;
static volatile USHORT usMasterSndBufferCount;
@ -158,12 +159,12 @@ eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLengt
/* Length and CRC check */
if( ( usMasterRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
&& ( usMBCRC16( ( UCHAR * ) ucMasterRTUBuf, usMasterRcvBufferPos ) == 0 ) )
&& ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) )
{
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*pucRcvAddress = ucMasterRTUBuf[MB_SER_PDU_ADDR_OFF];
*pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
@ -171,7 +172,7 @@ eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLengt
*pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
/* Return the start of the Modbus PDU to the caller. */
*pucFrame = ( UCHAR * ) & ucMasterRTUBuf[MB_SER_PDU_PDU_OFF];
*pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF];
}
else
{
@ -208,8 +209,8 @@ eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount );
ucMasterRTUBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
ucMasterRTUBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
/* Activate the transmitter. */
eSndState = STATE_M_TX_XMIT;
@ -263,7 +264,7 @@ xMBMasterRTUReceiveFSM( void )
eSndState = STATE_M_TX_IDLE;
usMasterRcvBufferPos = 0;
ucMasterRTUBuf[usMasterRcvBufferPos++] = ucByte;
ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
eRcvState = STATE_M_RX_RCV;
/* Enable t3.5 timers. */
@ -278,7 +279,7 @@ xMBMasterRTUReceiveFSM( void )
case STATE_M_RX_RCV:
if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX )
{
ucMasterRTUBuf[usMasterRcvBufferPos++] = ucByte;
ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
}
else
{
@ -316,8 +317,7 @@ xMBMasterRTUTransmitFSM( void )
}
else
{
bFrameIsBroadcast = ( ucMasterRTUBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
xNeedPoll = xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
bFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
/* Disable transmitter. This prevents another transmit buffer
* empty interrupt. */
vMBMasterPortSerialEnable( TRUE, FALSE );

View File

@ -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: portevent.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions, $
* File: $Id: portevent.c,v 1.60 2013/08/13 15:07:05 Armink $
*/
/* ----------------------- Modbus includes ----------------------------------*/

View File

@ -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: portserial.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$
* File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $
*/
#include "port.h"
@ -107,7 +107,7 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
if (ucPORT > 1)
if (ucPORT != 1)
return FALSE;
ENTER_CRITICAL_SECTION(); //¹ØÈ«¾ÖÖжÏ

View File

@ -58,7 +58,7 @@ void vMBMasterPortClose(void)
USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE);
USART_Cmd(USART2, DISABLE);
}
//默认一个机 串口2 波特率可设置 奇偶检验可设置
//默认一个机 串口2 波特率可设置 奇偶检验可设置
BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
eMBParity eParity)
{
@ -66,9 +66,8 @@ BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//======================时钟初始化=======================================
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB1Periph_USART2,
ENABLE);
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;
@ -109,7 +108,7 @@ BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
if (ucPORT > 1)
if (ucPORT != 2)
return FALSE;
ENTER_CRITICAL_SECTION(); //关全局中断

View File

@ -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: porttimer.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $
* File: $Id: porttimer.c,v 1.60 2013/08/13 15:07:05 Armink $
*/
/* ----------------------- Platform includes --------------------------------*/

View File

@ -20,7 +20,7 @@ USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
USHORT usMRegHoldStart = M_REG_HOLDING_START;
USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
extern volatile UCHAR ucMBMasterSendAddress;
extern volatile UCHAR ucMBMasterSndAddress;
extern volatile BOOL bMBRunInMasterMode;
#endif
//******************************ÊäÈë¼Ä´æÆ÷»Øµ÷º¯Êý**********************************
@ -45,7 +45,7 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
//Determine the master or slave
if (bMBRunInMasterMode)
{
pusRegInputBuf = usMRegInBuf[ucMBMasterSendAddress];
pusRegInputBuf = usMRegInBuf[ucMBMasterSndAddress];
REG_INPUT_START = M_REG_INPUT_START;
REG_INPUT_NREGS = M_REG_INPUT_NREGS;
usRegInStart = usMRegInStart;
@ -111,7 +111,7 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi
//Determine the master or slave
if (bMBRunInMasterMode)
{
pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterSendAddress];
pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterSndAddress];
REG_HOLDING_START = M_REG_HOLDING_START;
REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
usRegHoldStart = usMRegHoldStart;
@ -179,16 +179,17 @@ eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegis
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex , iRegBitIndex , iNReg;
iNReg = usNCoils / 8 + 1; //占用寄存器数量
UCHAR * pucCoilBuf;
UCHAR COIL_START;
UCHAR COIL_NCOILS;
UCHAR usCoilStart;
iNReg = usNCoils / 8 + 1; //占用寄存器数量
//Determine the master or slave
if (bMBRunInMasterMode)
{
pucCoilBuf = ucMCoilBuf[ucMBMasterSendAddress];
pucCoilBuf = ucMCoilBuf[ucMBMasterSndAddress];
COIL_START = M_COIL_START;
COIL_NCOILS = M_COIL_NCOILS;
usCoilStart = usMCoilStart;
@ -257,16 +258,16 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex , iRegBitIndex , iNReg;
iNReg = usNDiscrete / 8 + 1; //占用寄存器数量
UCHAR * pucDiscreteInputBuf;
UCHAR DISCRETE_INPUT_START;
UCHAR DISCRETE_INPUT_NDISCRETES;
UCHAR usDiscreteInputStart;
iNReg = usNDiscrete / 8 + 1; //占用寄存器数量
//Determine the master or slave
if (bMBRunInMasterMode)
{
pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterSendAddress];
pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterSndAddress];
DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
usDiscreteInputStart = usMDiscInStart;

File diff suppressed because one or more lines are too long

View File

@ -741,9 +741,9 @@
<FilePath>..\FreeModbus\port\porttimer.c</FilePath>
</File>
<File>
<FileName>user_app_s.c</FileName>
<FileName>user_mb_app.c</FileName>
<FileType>1</FileType>
<FilePath>..\FreeModbus\port\user_app_s.c</FilePath>
<FilePath>..\FreeModbus\port\user_mb_app.c</FilePath>
</File>
</Files>
</Group>
@ -1514,9 +1514,9 @@
<FilePath>..\FreeModbus\port\porttimer.c</FilePath>
</File>
<File>
<FileName>user_app_s.c</FileName>
<FileName>user_mb_app.c</FileName>
<FileType>1</FileType>
<FilePath>..\FreeModbus\port\user_app_s.c</FilePath>
<FilePath>..\FreeModbus\port\user_mb_app.c</FilePath>
</File>
</Files>
</Group>

File diff suppressed because it is too large Load Diff