完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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********** ***************转载请注明出处*************** |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1618 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1545 浏览 1 评论
979 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1597 浏览 2 评论
1864浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
645浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
516浏览 3评论
532浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
505浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 16:52 , Processed in 0.747943 second(s), Total 47, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号