本帖最后由 固桐 于 2013-5-27 22:27 编辑
这几天,研究了freemodbus通信协议,然后在stm32上移植。关于freemodbus通信原理,以及通信过程(状态机转换),这里就不说了。 freemodbus使用的库是最新版本freemodbus-v1.5.0,把相应的库文件加载在STM32工程中。移植时,需要用户改写的文件有两个,一个是porttimer.c文件,一个是portserial.c文件。porttimer.c文件主要用于超时判断,本例使用的是定时器2,portserial.c主要使用串口通信的实现,本例使用的是RS485.porttimer.c修改如下
- /* ----------------------- Platform includes --------------------------------*/
- #include "port.h"
- /* ----------------------- Modbus includes ----------------------------------*/
- #include "mb.h"
- #include "mbport.h"
- #include "..\..\include\nvic.h"
- #include "..\..\include\stm32f10x_reg.h"
- /* ----------------------- Start implementation -----------------------------*/
- BOOL
- xMBPortTimersInit( USHORT usTim1Timerout50us ) //配置50us时钟
- {
- uint16_t PrescalerValue = 0;
-
- /* TIM2 clock enable */
-
- RCC->CFGR.B.PPRE1 = 4; //APB1预分频系数
- //100:HCLK 2分频
- //APB1 不超过36MHz
- RCC->APB1ENR.B.TIM2EN = 1;
- /* Compute the prescaler value */
- PrescalerValue = (uint16_t) (36000000 / 20000) - 1; // 1/20000=50us
- /* Time base configuration */
- TIM2->ARR=(uint16_t) usTim1Timerout50us;
- TIM2->PSC= PrescalerValue;
- TIM2->CR1.B.URS = 1;
- MY_NVIC_Init(3,3,28,2);
-
- /* TIM IT DISABLE */
- TIM2->SR.B.UIF = 0;
- TIM2->DIER.B.UIE = 0;
- TIM2->CR1.B.CEN = 0;
- /* TIM2 DISABLE counter */
- return TRUE;;
- }
- void vMBPortTimersEnable( ) //打开时钟
- {
- TIM2->SR.B.UIF = 0;
- TIM2->DIER.B.UIE = 1;
- TIM2->CNT= 0;
- TIM2->CR1.B.CEN = 1;
-
- }
- void vMBPortTimersDisable( ) //关闭时钟
- {
- TIM2->CR1.B.CEN = 0;
- TIM2->CNT= 0;
- TIM2->DIER.B.TIE = 0;
- TIM2->DIER.B.UIE = 0;
- }
- /* 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 TIM2_IRQHandler(void)
- {
- /* Clear TIM4 Capture Compare1 interrupt pending bit*/
-
- TIM2->SR.B.UIF = 0;
- TIM2->SR.B.TIF = 0;
- prvvTIMERExpiredISR( );
- }
portserial.c文件修改如下
另外在主函数中,加入测试函数如下
- #include "mb.h"
- #include "..\..\include\adc.h"
- #include "..\..\include\lm75.h"
- #include "..\..\include\timer.h"
- #include "..\..\include\simulate.h"
- #include "..\..\include\encode.h"
- #include "..\..\include\hardware.h"
- #include "..\..\include\systick.h"
- unsigned short int usRegInputBuf[10]={0x0000,0xfe02,0x1203,0x1304,0x1405,0x1506,0x1607,0x1708,0x1809};
- unsigned short int *usRegHoldingBuf=usRegInputBuf; //一个测试用的 寄存器数组 地址0-7
- unsigned char REG_INPUT_START=0,REG_HOLDING_START=0;
- unsigned char REG_INPUT_NREGS=8,REG_HOLDING_NREGS=8;
- unsigned char usRegInputStart=0,usRegHoldingStart=0;
- //读数字寄存器 功能码0x04
- 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 - usRegInputStart );
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ =
- ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ =
- ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- // 寄存器的读写函数 支持的命令为读 0x03 和写0x06
- 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 - usRegHoldingStart );
- switch ( eMode )
- {
-
- case MB_REG_READ:
- if(usAddress==1)
- {
- *pucRegBuffer++ = ( unsigned char )( adc.read(1) >> 8 );
-
- *pucRegBuffer++ = ( unsigned char )( adc.read(1) & 0xFF );
- }
- if(usAddress==2)
- {
- *pucRegBuffer++ = ( unsigned char )( adc.read(0) >> 8 );
-
- *pucRegBuffer++ = ( unsigned char )( adc.read(0) & 0xFF );
- }
- if(usAddress==3)
- {
- *pucRegBuffer++ = ( unsigned char )( adc.read(7) >> 8 );
-
- *pucRegBuffer++ = ( unsigned char )( adc.read(7) & 0xFF );
- }
- if(usAddress==4)
- {
- *pucRegBuffer++ = ( unsigned char )( lm75.read() >> 8 );
-
- *pucRegBuffer++ = ( unsigned char )( lm75.read() & 0xFF );
- }
-
- if(usAddress==5)
- {
-
- timer.refresh();
- *pucRegBuffer++ = ( unsigned char )( tim_parameter.Position_relative >> 8 );
- *pucRegBuffer++ = ( unsigned char )( tim_parameter.Position_relative &0xFF );
-
-
- }
- if(usAddress==6)
- {
-
- timer.refresh();
- *pucRegBuffer++ = ( unsigned char )( TIM1->CCR2>> 8 );
- *pucRegBuffer++ = ( unsigned char )( TIM1->CCR2&0xFF );
-
-
- }
-
- break;
- case MB_REG_WRITE:
- while( usNRegs > 0 )
- {
-
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- //读/写开关寄存器 0x01 x05
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
- {
- ( void )pucRegBuffer;
- ( void )usAddress;
- ( void )usNCoils;
- ( void )eMode;
- return MB_ENOREG;
- }
- //读开关寄存器 0x02
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- ( void )pucRegBuffer;
- ( void )usAddress;
- ( void )usNDiscrete;
- return MB_ENOREG;
- }
经过,测试,本次移植可以读取节点的温度,AD转换值,等参数,实现了预期的效果。
|