首先将FreeModbus移植到自己工程中,如下图所示:
然后修改portserial.c和porttimer.c文件:
portserial.c
- /*
- * FreeModbus Libary: BARE Port
- * Copyright (C) 2006 Christian Walter
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * File: $Id: portserial.c,v 1.1 2006/08/22 21:35:13 wolti Exp $
- */
- #include "port.h"
- #include "stm32f10x.h"
- #include "modbus.h"
- /* ----------------------- Modbus includes ----------------------------------*/
- #include "mb.h"
- #include "mbport.h"
- /* ----------------------- static functions ---------------------------------*/
- static void prvvUARTTxReadyISR( void );
- static void prvvUARTRxISR( void );
- /* ----------------------- Start implementation -----------------------------*/
- void
- vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
- {
- /* If xRXEnable enable serial receive interrupts. If xTxENable enable
- * transmitter empty interrupts.
- */
- if(xRxEnable == TRUE)
- {
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
- }
- else
- {
- USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
- }
-
- if(xTxEnable == TRUE)
- {
- USART_ITConfig(USART2, USART_IT_TC, ENABLE);
- }
- else
- {
- USART_ITConfig(USART2, USART_IT_TC, DISABLE);
- }
- }
- BOOL
- xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
- {
- modbus_uart_init((uint16_t)ulBaudRate);
- return TRUE;
- }
- BOOL
- xMBPortSerialPutByte( CHAR ucByte )
- {
- /* Put a byte in the UARTs transmit buffer. This function is called
- * by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been
- * called. */
-
- USART_SendData(USART2, ucByte);
- return TRUE;
- }
- BOOL
- xMBPortSerialGetByte( CHAR * pucByte )
- {
- /* Return the byte in the UARTs receive buffer. This function is called
- * by the protocol stack after pxMBFrameCBByteReceived( ) has been called.
- */
- *pucByte = USART_ReceiveData(USART2);
- return TRUE;
- }
- /* Create an interrupt handler for the transmit buffer empty interrupt
- * (or an equivalent) for your target processor. This function should then
- * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
- * a new character can be sent. The protocol stack will then call
- * xMBPortSerialPutByte( ) to send the character.
- */
- static void prvvUARTTxReadyISR( void )
- {
- pxMBFrameCBTransmitterEmpty( );
- }
- /* Create an interrupt handler for the receive interrupt for your target
- * processor. This function should then call pxMBFrameCBByteReceived( ). The
- * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
- * character.
- */
- static void prvvUARTRxISR( void )
- {
- pxMBFrameCBByteReceived( );
- }
- /**
- * @brief This function handles usart1 Handler.
- * @param None
- * @retval None
- */
- void USART2_IRQHandler(void)
- {
- //发生接收中断
- if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
- {
- prvvUARTRxISR();
- //清除中断标志位
- USART_ClearITPendingBit(USART2, USART_IT_RXNE);
- }
- if(USART_GetITStatus(USART2, USART_IT_ORE) == SET)
- {
- USART_ClearITPendingBit(USART2, USART_IT_ORE);
- prvvUARTRxISR();
- }
- //发生完成中断
- if(USART_GetITStatus(USART2, USART_IT_TC) == SET)
- {
- prvvUARTTxReadyISR();
- //清除中断标志
- USART_ClearITPendingBit(USART2, USART_IT_TC);
- }
- }
复制代码
porttimer.c
- ```c
- /*
- * FreeModbus Libary: BARE Port
- * Copyright (C) 2006 Christian Walter <<a href="mailto:wolti@sil.at">wolti@sil.at</a>>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * File: $Id: porttimer.c,v 1.1 2006/08/22 21:35:13 wolti Exp $
- */
- /* ----------------------- Platform includes --------------------------------*/
- #include "port.h"
- #include "modbus.h"
- /* ----------------------- Modbus includes ----------------------------------*/
- #include "mb.h"
- #include "mbport.h"
- /* ----------------------- static functions ---------------------------------*/
- static void prvvTIMERExpiredISR( void );
- /* ----------------------- Start implementation -----------------------------*/
- BOOL
- xMBPortTimersInit( USHORT usTim1Timerout50us )
- {
- modbus_timer_init(usTim1Timerout50us);
- return TRUE;
- }
- void
- vMBPortTimersEnable( )
- {
- /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
- TIM_SetCounter(TIM3,0x0000);
- TIM_Cmd(TIM3, ENABLE);
- }
- void
- vMBPortTimersDisable( )
- {
- /* Disable any pending timers. */
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
- TIM_SetCounter(TIM3,0x0000);
- TIM_Cmd(TIM3, DISABLE);
- }
- /* Create an ISR which is called whenever the timer has expired. This function
- * must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that
- * the timer has expired.
- */
- static void prvvTIMERExpiredISR( void )
- {
- ( void )pxMBPortCBTimerExpired( );
- }
- void TIM3_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
- {
- prvvTIMERExpiredISR();
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- }
- }
复制代码
然后主函数中调用
- int main(void)
- {
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
- uart_init(115200);
- eMBInit(MB_RTU, 0x01, 0x01, 9600, MB_PAR_NONE);
- eMBEnable();
- while(1)
- {
- (void)eMBPoll();
- delay_ms(5);
-
- }
- }
复制代码
其次还要实现读线圈、写线圈、读离散输入、写保持寄存器、读保持寄存器、读输入寄存器等功能,如下:
- #define REG_INPUT_START 0x0001 //输入寄存器起始地址
- #define REG_INPUT_NREGS 8 //输入寄存器数量
- #define REG_HOLDING_START 0x0001 //保持寄存器起始地址
- #define REG_HOLDING_NREGS 8 //保持寄存器数量
- #define REG_COILS_START 0x0001 //线圈起始地址
- #define REG_COILS_SIZE 16 //线圈数量
- #define REG_DISCRETE_START 0x0001 //开关寄存器其实地址
- #define REG_DISCRETE_SIZE 16 //开关寄存器数量
- //输入寄存器内容
- uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
- //保持寄存器内容
- uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007};
- //线圈状态
- uint8_t ucRegCoilsBuf[REG_COILS_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
- //离散寄存器内容
- uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x01};
- /****************************************************************************
- * 名 称:eMBRegInputCB
- * 功 能:读取输入寄存器,对应功能码是 04 eMBFuncReadInputRegister
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 寄存器地址
- * usNRegs: 要读取的寄存器个数
- * 出口参数:
- * 注 意:上位机发来的 帧格式是: SlaveAddr(1 Byte)+FuncCode(1 Byte)
- * +StartAddrHiByte(1 Byte)+StartAddrLoByte(1 Byte)
- * +LenAddrHiByte(1 Byte)+LenAddrLoByte(1 Byte)+
- * +CRCAddrHiByte(1 Byte)+CRCAddrLoByte(1 Byte)
- * 3 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- if( ( usAddress >= REG_INPUT_START )
- && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
- {
- iRegIndex = ( int )( usAddress - REG_INPUT_START );
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /****************************************************************************
- * 名 称:eMBRegHoldingCB
- * 功 能:对应功能码有:06 写保持寄存器 eMBFuncWriteHoldingRegister
- * 16 写多个保持寄存器 eMBFuncWriteMultipleHoldingRegister
- * 03 读保持寄存器 eMBFuncReadHoldingRegister
- * 23 读写多个保持寄存器 eMBFuncReadWriteMultipleHoldingRegister
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 寄存器地址
- * usNRegs: 要读写的寄存器个数
- * eMode: 功能码
- * 出口参数:
- * 注 意:4 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- if((usAddress >= REG_HOLDING_START)&&\
- ((usAddress+usNRegs) <= (REG_HOLDING_START + REG_HOLDING_NREGS)))
- {
- iRegIndex = (int)(usAddress - REG_HOLDING_START);
- switch(eMode)
- {
- case MB_REG_READ://读 MB_REG_READ = 0
- while(usNRegs > 0)
- {
- *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] >> 8);
- *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] & 0xFF);
- iRegIndex++;
- usNRegs--;
- }
- break;
- case MB_REG_WRITE://写 MB_REG_WRITE = 0
- while(usNRegs > 0)
- {
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- break;
- }
- }
- else//错误
- {
- eStatus = MB_ENOREG;
- }
-
- return eStatus;
- }
- /****************************************************************************
- * 名 称:eMBRegCoilsCB
- * 功 能:对应功能码有:01 读线圈 eMBFuncReadCoils
- * 05 写线圈 eMBFuncWriteCoil
- * 15 写多个线圈 eMBFuncWriteMultipleCoils
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 线圈地址
- * usNCoils: 要读写的线圈个数
- * eMode: 功能码
- * 出口参数:
- * 注 意:如继电器
- * 0 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- u8 i;
- USHORT readNumber=usNCoils;
- USHORT coilValue=0x0000;
- if((usAddress >= REG_COILS_START)&&\
- ((usAddress+usNCoils) <= (REG_COILS_START + REG_COILS_SIZE)))
- {
- iRegIndex = (int)(usAddress + usNCoils-REG_COILS_START);
- switch(eMode)
- {
- case MB_REG_READ://读 MB_REG_READ = 0
- for(i=0;i<usNCoils;i++)
- {
- readNumber--;
- iRegIndex--;
- coilValue|=ucRegCoilsBuf[iRegIndex]<<readNumber;
- }
- if(usNCoils<=8)
- {
- * pucRegBuffer=coilValue;
- }
- else
- {
- * pucRegBuffer++ = (coilValue)&0x00ff;
- * pucRegBuffer++ = (coilValue>>8)&0x00ff;
- }
- break;
- case MB_REG_WRITE://写 MB_REG_WRITE = 1
- while(usNCoils > 0)
- {
- // usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- // usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNCoils--;
- }
- break;
- }
- }
- else//错误
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /****************************************************************************
- * 名 称:eMBRegDiscreteCB
- * 功 能:读取离散寄存器,对应功能码有:02 读离散寄存器 eMBFuncReadDiscreteInputs
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 寄存器地址
- * usNDiscrete: 要读取的寄存器个数
- * 出口参数:
- * 注 意:1 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- u8 i;
- USHORT readNumber=usNDiscrete;
- USHORT coilValue=0x0000;
- iRegIndex = (int)(usAddress + usNDiscrete-REG_DISCRETE_START);
- if((usAddress >= REG_DISCRETE_START)&&\
- ((usAddress+usNDiscrete) <= (REG_DISCRETE_START + REG_DISCRETE_SIZE)))
- {
- for(i=0;i<usNDiscrete;i++)
- {
- readNumber--;
- iRegIndex--;
- coilValue|=ucRegDiscreteBuf[iRegIndex]<<readNumber;
- }
- if(usNDiscrete<=8)
- {
- * pucRegBuffer=coilValue;
- }
- else
- {
- * pucRegBuffer++ = (coilValue)&0x00ff;
- * pucRegBuffer++ = (coilValue>>8)&0x00ff;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
复制代码
|