freemodbus下载地址:freemodbus-v1.6
开发环境说明
1、基于正点原子F429例程-实验28 RS485移植
2、采用致远485摸块(自收发)
完整工程文件下载地址
如果不想手动移植可以点击跳转下载->F429_HAL_Freemodbus_rtu
F407也移植了相应的HAL库的Freemodbus_rtu,也可以点击跳转下载->F407_HAL_Freemodbus_rtu
本人也移植了带操作系统的相应例程,和RTU_TCP共用的相应例程,如果有需要,评论留言我再上传。
移植前提
取freemodbus文件目录下两个文件夹,分别是modbus与demo-BARE-port
BARE下取port
Modbus下取以下文件
在keil project下声明相应的.c与.h文件
修改"RS485.c"文件
在RS485.c文件下初始化串口usart与定时器tim;
void RS485_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART2_CLK_ENABLE(); //使能USART2时钟
GPIO_Initure.Pin=GPIO_PIN_3; //PA3
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART2; //复用为USART2
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA3
GPIO_Initure.Pin=GPIO_PIN_5; //PD5
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART2; //复用为USART2
HAL_GPIO_Init(GPIOD,&GPIO_Initure); //初始化PD5
//USART 初始化设置
USART2_RS485Handler.Instance=USART2; //USART2
USART2_RS485Handler.Init.BaudRate=bound; //波特率
USART2_RS485Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
USART2_RS485Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
USART2_RS485Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
USART2_RS485Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
USART2_RS485Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
USART2_RS485Handler.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&USART2_RS485Handler); //HAL_UART_Init()会使能USART2
__HAL_UART_DISABLE_IT(&USART2_RS485Handler,UART_IT_TC);
#if EN_USART2_RX
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,UART_IT_RXNE);//开启接收中断
HAL_NVIC_SetPriority(USART2_IRQn,0,1); //抢占优先级3,子优先级3
HAL_NVIC_EnableIRQ(USART2_IRQn); //使能USART1中断
#endif
RS485_TX_Set(0); //设置为接收模式
}
void TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM2_Handler.Instance = TIM2;
TIM2_Handler.Init.Prescaler = (9000-1);
TIM2_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM2_Handler.Init.Period = 50;
TIM2_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&TIM2_Handler);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&TIM2_Handler, &sClockSourceConfig);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&TIM2_Handler, &sMasterConfig);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM2)
{
/* 基本定时器外设时钟使能 */
__HAL_RCC_TIM2_CLK_ENABLE();
/* 外设中断配置 */
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
}
/**
* 函数功能: 基本定时器硬件反初始化配置
* 输入参数: htim_base:基本定时器句柄类型指针
* 返 回 值: 无
* 说 明: 该函数被HAL库内部调用
*/
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM2)
{
/* 基本定时器外设时钟禁用 */
__HAL_RCC_TIM2_CLK_DISABLE();
/* 关闭外设中断 */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
}
}
修改"portserial.c"文件
#include "port.h"
#include "stm32f4xx_hal.h"
#include "rs485.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
/* ----------------------- static functions ---------------------------------*/
//void prvvUARTTxReadyISR( void );
//void prvvUARTRxISR( void );
extern UART_HandleTypeDef USART2_RS485Handler; //USART2句柄(用于RS485)
/* ----------------------- Start implementation -----------------------------*/
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
/* If xRXEnable enable serial receive interrupts. If xTxENable enable
* transmitter empty interrupts.
*/
if (xRxEnable)
{
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,UART_IT_RXNE);
}
else
{
__HAL_UART_DISABLE_IT(&USART2_RS485Handler,UART_IT_RXNE);
}
if (xTxEnable)
{
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,UART_IT_TXE);
}
else
{
__HAL_UART_DISABLE_IT(&USART2_RS485Handler,UART_IT_TXE);
}
}
BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
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. */
if(HAL_UART_Transmit(&USART2_RS485Handler ,(uint8_t *)&ucByte,1,0x01) != HAL_OK )
{
return FALSE ;
}
else
{
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.
*/
if(HAL_UART_Receive (&USART2_RS485Handler ,(uint8_t *)pucByte,1,0x01) != HAL_OK )
{
return FALSE ;
}
else
{
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.
*/
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.
*/
void prvvUARTRxISR( void )
{
pxMBFrameCBByteReceived( );
}
修改"porttimer.c"文件
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
#include "stm32f4xx_hal.h"
#include "rs485.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
extern TIM_HandleTypeDef TIM2_Handler; //定时器句柄
/* ----------------------- static functions ---------------------------------*/
//void prvvTIMERExpiredISR( void );
/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
TIM2_Init();
return TRUE;
}
inline void
vMBPortTimersEnable( )
{
/* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
__HAL_TIM_CLEAR_IT(&TIM2_Handler,TIM_IT_UPDATE);
__HAL_TIM_SetCounter(&TIM2_Handler,0);
/* 在中断模式下启动定时器 */
HAL_TIM_Base_Start_IT(&TIM2_Handler);
}
inline void
vMBPortTimersDisable( )
{
/* Disable any pending timers. */
HAL_TIM_Base_Stop_IT(&TIM2_Handler);
__HAL_TIM_SetCounter(&TIM2_Handler,0);
__HAL_TIM_CLEAR_IT(&TIM2_Handler,TIM_IT_UPDATE);
}
/* 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.
*/
void prvvTIMERExpiredISR( void )
{
( void )pxMBPortCBTimerExpired( );
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
prvvTIMERExpiredISR();
}
修改"port.h"
#include
#include
#include "stm32f4xx_hal.h" //添加声明
#define INLINE inline
#define PR_BEGIN_EXTERN_C extern "C" {
#define PR_END_EXTERN_C }
#define ENTER_CRITICAL_SECTION( ) __set_PRIMASK(1) //完善定义
#define EXIT_CRITICAL_SECTION( ) __set_PRIMASK(0) //完善定义
修改"main.c"文件
修改main.c函数,添加寄存器定义与modbus初始化
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"
#include "rs485.h"
#include "mb.h"
#include "mbport.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
#define REG_INPUT_START 0
#define REG_INPUT_NREGS 4
/* 私有变量 ------------------------------------------------------------------*/
static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(115200); //初始化USART
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
RS485_Init(9600); //初始化RS485
eMBInit(MB_RTU, 0x01, 3, 9600, MB_PAR_NONE);
/* Enable the Modbus Protocol Stack. */
eMBEnable();
while(1)
{
(void)eMBPoll();
}
}
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
printf("eMBRegInputCBn");
// 用作例子
usRegInputBuf[0] = 0x11;
usRegInputBuf[1] = 0x22;
usRegInputBuf[2] = 0x33;
usRegInputBuf[3] = 0x44;
// 例子结束
if((usAddress>=REG_INPUT_START)&&(usAddress+usNRegs<=REG_INPUT_START+REG_INPUT_NREGS))
{
iRegIndex=(int)(usAddress-usRegInputStart);
while( usNRegs > 0 )
{
*pucRegBuffer++ = (unsigned char)(usRegInputBuf[iRegIndex]>>8);
*pucRegBuffer++ = (unsigned char)(usRegInputBuf[iRegIndex]&0xFF);
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,eMBRegisterMode eMode )
{
printf("eMBRegHoldingCBn");
return MB_ENOREG;
}
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,eMBRegisterMode eMode )
{
printf("eMBRegCoilsCBn");
return MB_ENOREG;
}
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
printf("eMBRegDiscreteCBn");
return MB_ENOREG;
}
测试
使用串口调试助手发相应指令,返回相应寄存器值即移植成功。
************最后更新于2021-01-31********** ***************转载请注明出处***************
freemodbus下载地址:freemodbus-v1.6
开发环境说明
1、基于正点原子F429例程-实验28 RS485移植
2、采用致远485摸块(自收发)
完整工程文件下载地址
如果不想手动移植可以点击跳转下载->F429_HAL_Freemodbus_rtu
F407也移植了相应的HAL库的Freemodbus_rtu,也可以点击跳转下载->F407_HAL_Freemodbus_rtu
本人也移植了带操作系统的相应例程,和RTU_TCP共用的相应例程,如果有需要,评论留言我再上传。
移植前提
取freemodbus文件目录下两个文件夹,分别是modbus与demo-BARE-port
BARE下取port
Modbus下取以下文件
在keil project下声明相应的.c与.h文件
修改"RS485.c"文件
在RS485.c文件下初始化串口usart与定时器tim;
void RS485_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART2_CLK_ENABLE(); //使能USART2时钟
GPIO_Initure.Pin=GPIO_PIN_3; //PA3
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART2; //复用为USART2
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA3
GPIO_Initure.Pin=GPIO_PIN_5; //PD5
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART2; //复用为USART2
HAL_GPIO_Init(GPIOD,&GPIO_Initure); //初始化PD5
//USART 初始化设置
USART2_RS485Handler.Instance=USART2; //USART2
USART2_RS485Handler.Init.BaudRate=bound; //波特率
USART2_RS485Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
USART2_RS485Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
USART2_RS485Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
USART2_RS485Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
USART2_RS485Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
USART2_RS485Handler.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&USART2_RS485Handler); //HAL_UART_Init()会使能USART2
__HAL_UART_DISABLE_IT(&USART2_RS485Handler,UART_IT_TC);
#if EN_USART2_RX
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,UART_IT_RXNE);//开启接收中断
HAL_NVIC_SetPriority(USART2_IRQn,0,1); //抢占优先级3,子优先级3
HAL_NVIC_EnableIRQ(USART2_IRQn); //使能USART1中断
#endif
RS485_TX_Set(0); //设置为接收模式
}
void TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM2_Handler.Instance = TIM2;
TIM2_Handler.Init.Prescaler = (9000-1);
TIM2_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM2_Handler.Init.Period = 50;
TIM2_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&TIM2_Handler);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&TIM2_Handler, &sClockSourceConfig);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&TIM2_Handler, &sMasterConfig);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM2)
{
/* 基本定时器外设时钟使能 */
__HAL_RCC_TIM2_CLK_ENABLE();
/* 外设中断配置 */
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
}
/**
* 函数功能: 基本定时器硬件反初始化配置
* 输入参数: htim_base:基本定时器句柄类型指针
* 返 回 值: 无
* 说 明: 该函数被HAL库内部调用
*/
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM2)
{
/* 基本定时器外设时钟禁用 */
__HAL_RCC_TIM2_CLK_DISABLE();
/* 关闭外设中断 */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
}
}
修改"portserial.c"文件
#include "port.h"
#include "stm32f4xx_hal.h"
#include "rs485.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
/* ----------------------- static functions ---------------------------------*/
//void prvvUARTTxReadyISR( void );
//void prvvUARTRxISR( void );
extern UART_HandleTypeDef USART2_RS485Handler; //USART2句柄(用于RS485)
/* ----------------------- Start implementation -----------------------------*/
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
/* If xRXEnable enable serial receive interrupts. If xTxENable enable
* transmitter empty interrupts.
*/
if (xRxEnable)
{
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,UART_IT_RXNE);
}
else
{
__HAL_UART_DISABLE_IT(&USART2_RS485Handler,UART_IT_RXNE);
}
if (xTxEnable)
{
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,UART_IT_TXE);
}
else
{
__HAL_UART_DISABLE_IT(&USART2_RS485Handler,UART_IT_TXE);
}
}
BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
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. */
if(HAL_UART_Transmit(&USART2_RS485Handler ,(uint8_t *)&ucByte,1,0x01) != HAL_OK )
{
return FALSE ;
}
else
{
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.
*/
if(HAL_UART_Receive (&USART2_RS485Handler ,(uint8_t *)pucByte,1,0x01) != HAL_OK )
{
return FALSE ;
}
else
{
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.
*/
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.
*/
void prvvUARTRxISR( void )
{
pxMBFrameCBByteReceived( );
}
修改"porttimer.c"文件
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
#include "stm32f4xx_hal.h"
#include "rs485.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
extern TIM_HandleTypeDef TIM2_Handler; //定时器句柄
/* ----------------------- static functions ---------------------------------*/
//void prvvTIMERExpiredISR( void );
/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
TIM2_Init();
return TRUE;
}
inline void
vMBPortTimersEnable( )
{
/* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
__HAL_TIM_CLEAR_IT(&TIM2_Handler,TIM_IT_UPDATE);
__HAL_TIM_SetCounter(&TIM2_Handler,0);
/* 在中断模式下启动定时器 */
HAL_TIM_Base_Start_IT(&TIM2_Handler);
}
inline void
vMBPortTimersDisable( )
{
/* Disable any pending timers. */
HAL_TIM_Base_Stop_IT(&TIM2_Handler);
__HAL_TIM_SetCounter(&TIM2_Handler,0);
__HAL_TIM_CLEAR_IT(&TIM2_Handler,TIM_IT_UPDATE);
}
/* 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.
*/
void prvvTIMERExpiredISR( void )
{
( void )pxMBPortCBTimerExpired( );
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
prvvTIMERExpiredISR();
}
修改"port.h"
#include
#include
#include "stm32f4xx_hal.h" //添加声明
#define INLINE inline
#define PR_BEGIN_EXTERN_C extern "C" {
#define PR_END_EXTERN_C }
#define ENTER_CRITICAL_SECTION( ) __set_PRIMASK(1) //完善定义
#define EXIT_CRITICAL_SECTION( ) __set_PRIMASK(0) //完善定义
修改"main.c"文件
修改main.c函数,添加寄存器定义与modbus初始化
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"
#include "rs485.h"
#include "mb.h"
#include "mbport.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
#define REG_INPUT_START 0
#define REG_INPUT_NREGS 4
/* 私有变量 ------------------------------------------------------------------*/
static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(115200); //初始化USART
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
RS485_Init(9600); //初始化RS485
eMBInit(MB_RTU, 0x01, 3, 9600, MB_PAR_NONE);
/* Enable the Modbus Protocol Stack. */
eMBEnable();
while(1)
{
(void)eMBPoll();
}
}
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
printf("eMBRegInputCBn");
// 用作例子
usRegInputBuf[0] = 0x11;
usRegInputBuf[1] = 0x22;
usRegInputBuf[2] = 0x33;
usRegInputBuf[3] = 0x44;
// 例子结束
if((usAddress>=REG_INPUT_START)&&(usAddress+usNRegs<=REG_INPUT_START+REG_INPUT_NREGS))
{
iRegIndex=(int)(usAddress-usRegInputStart);
while( usNRegs > 0 )
{
*pucRegBuffer++ = (unsigned char)(usRegInputBuf[iRegIndex]>>8);
*pucRegBuffer++ = (unsigned char)(usRegInputBuf[iRegIndex]&0xFF);
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,eMBRegisterMode eMode )
{
printf("eMBRegHoldingCBn");
return MB_ENOREG;
}
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,eMBRegisterMode eMode )
{
printf("eMBRegCoilsCBn");
return MB_ENOREG;
}
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
printf("eMBRegDiscreteCBn");
return MB_ENOREG;
}
测试
使用串口调试助手发相应指令,返回相应寄存器值即移植成功。
************最后更新于2021-01-31********** ***************转载请注明出处***************
举报