官方下载freemodbus-v1.6.zip源码,然后把源码中的modbus文件夹、demo\BARE\port文件夹导入工程。
先是一波无脑导,把文件夹里所有文件导入。
存储区配置,单片机上定义的起始地址要比实际通信过程中读写的地址+1。
- #include "mb.h"
- #include "mbport.h"
- #include "mbutils.h"
- //输入寄存器
- #define REG_INPUT_START 1001
- #define REG_INPUT_NREGS 2
- static USHORT usRegInputStart = REG_INPUT_START;
- static USHORT usRegInputBuf[REG_INPUT_NREGS];
- //保持寄存器
- #define REG_HOLDING_START 2001
- #define REG_HOLDING_NREGS 1
- static USHORT usRegHoldingStart = REG_HOLDING_START;
- static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
- //输出线圈点
- #define REG_COILS_START 3001
- #define REG_COILS_SIZE 4
- static USHORT usRegCoilsStart = REG_COILS_START;
- static UCHAR ucRegCoilsBuf[REG_COILS_SIZE/8+(REG_COILS_SIZE%8?1:0)];
- //离散输入点
- #define REG_DISCRETE_START 4001
- #define REG_DISCRETE_SIZE 8
- static USHORT usRegDiscreteStart = REG_DISCRETE_START;
- static UCHAR ucRegDiscreteBuf[REG_DISCRETE_SIZE/8+(REG_DISCRETE_SIZE%8?1:0)];
复制代码
主程序就是标准的运行三连+IO读写。
- eStatus = eMBInit( MB_RTU, addr, 0, 9600, MB_PAR_EVEN );
- /* Enable the Modbus Protocol Stack. */
- eStatus = eMBEnable( );
- for( ;; )
- {
- ( void )eMBPoll( );
- usRegInputBuf[0]=Get_Adc_Average(8,10);
- usRegInputBuf[1]=Get_Adc_Average(9,10);
-
- ucRegDiscreteBuf[0]=(GPIOB->IDR&0xFFFFFF00)>>8;
- GPIOB->ODR=GPIOB->ODR&0xFFFFFF0F;
- GPIOB->ODR=GPIOB->ODR|ucRegCoilsBuf[0]<<4;
- }
复制代码
支持的4种读写function扔在主函数后面就行了。
- /**
- * @brief 输入寄存器处理函数,输入寄存器可读,但不可写。
- * @param pucRegBuffer 返回数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int16_t iRegIndex;
- //查询是否在寄存器范围内
- //为了避免警告,修改为有符号整数
- if( ( (int16_t)usAddress >= REG_INPUT_START ) \
- && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
- {
- //获得操作偏移量,本次操作起始地址-输入寄存器的初始地址
- iRegIndex = ( int16_t )( usAddress - REG_INPUT_START );
- //逐个赋值
- while( usNRegs > 0 )
- {
- //赋值高字节
- *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] >> 8 );
- //赋值低字节
- *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] & 0xFF );
- //偏移量增加
- iRegIndex++;
- //被操作寄存器数量递减
- usNRegs--;
- }
- }
- else
- {
- //返回错误状态,无寄存器
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /**
- * @brief 保持寄存器处理函数,保持寄存器可读,可读可写
- * @param pucRegBuffer 读操作时--返回数据指针,写操作时--输入数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * eMode 操作方式,读或者写
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
- eMBRegisterMode eMode )
- {
- //错误状态
- eMBErrorCode eStatus = MB_ENOERR;
- //偏移量
- int16_t iRegIndex;
- //判断寄存器是不是在范围内
- if( ( (int16_t)usAddress >= REG_HOLDING_START ) \
- && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
- {
- //计算偏移量
- iRegIndex = ( int16_t )( usAddress - REG_HOLDING_START );
- switch ( eMode )
- {
- //读处理函数
- case MB_REG_READ:
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- break;
- //写处理函数
- case MB_REG_WRITE:
- while( usNRegs > 0 )
- {
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- break;
- }
- }
- else
- {
- //返回错误状态
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /**
- * @brief 线圈寄存器处理函数,线圈寄存器可读,可读可写
- * @param pucRegBuffer 读操作---返回数据指针,写操作--返回数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * eMode 操作方式,读或者写
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
- eMBRegisterMode eMode )
- {
- //错误状态
- eMBErrorCode eStatus = MB_ENOERR;
- //寄存器个数
- int16_t iNCoils = ( int16_t )usNCoils;
- //寄存器偏移量
- int16_t usBitOffset;
- //检查寄存器是否在指定范围内
- if( ( (int16_t)usAddress >= REG_COILS_START ) &&
- ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
- {
- //计算寄存器偏移量
- usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
- switch ( eMode )
- {
- //读操作
- case MB_REG_READ:
- while( iNCoils > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
- iNCoils -= 8;
- usBitOffset += 8;
- }
- break;
- //写操作
- case MB_REG_WRITE:
- while( iNCoils > 0 )
- {
- xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
- *pucRegBuffer++ );
- iNCoils -= 8;
- usBitOffset += 8;
- }
- break;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /**
- * @brief 开关输入寄存器处理函数,开关输入寄存器,可读
- * @param pucRegBuffer 读操作---返回数据指针,写操作--返回数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * eMode 操作方式,读或者写
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- //错误状态
- eMBErrorCode eStatus = MB_ENOERR;
- //操作寄存器个数
- int16_t iNDiscrete = ( int16_t )usNDiscrete;
- //偏移量
- uint16_t usBitOffset;
- //判断寄存器时候再指定范围内
- if( ( (int16_t)usAddress >= REG_DISCRETE_START ) &&
- ( usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISCRETE_SIZE ) )
- {
- //获得偏移量
- usBitOffset = ( uint16_t )( usAddress - REG_DISCRETE_START );
- while( iNDiscrete > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits( ucRegDiscreteBuf, usBitOffset,
- ( uint8_t)( iNDiscrete > 8 ? 8 : iNDiscrete ) );
- iNDiscrete -= 8;
- usBitOffset += 8;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
复制代码
porttimer.c是和定时器相关的实现接口,计算好预分频与装载值之后,可以直接调用原子例程。
- /*
- * FreeModbus Libary: BARE Port
- * Copyright (C) 2006 Christian Walter <wolti@sil.at>
- *
- * 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$
- */
- #include "port.h"
- /* ----------------------- Modbus includes ----------------------------------*/
- #include "mb.h"
- #include "mbport.h"
- #include "rs485.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)
- {
- //使能接收和接收中断
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
- //MAX485操作 低电平为接收模式
- //GPIO_ResetBits(GPIOD,GPIO_Pin_8);
- RS485_TX_EN=0;
- }
- else
- {
- USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
- //MAX485操作 高电平为发送模式
- //GPIO_SetBits(GPIOD,GPIO_Pin_8);
- RS485_TX_EN=1;
- }
- if(xTxEnable)
- {
- //使能发送完成中断
- 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 )
- {
- RS485_Init(9600); //初始化RS485
- return TRUE;
- //return FALSE;
- }
- 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( );
- }
- 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_TC) == SET)
- {
- prvvUARTTxReadyISR();
- //清除中断标志
- USART_ClearITPendingBit(USART2, USART_IT_TC);
- }
- }
复制代码
modbus移植过程基本就完成了。
————————————————
版权声明:小盼你最萌哒
如有侵权请联系删除
|