|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
FreeMODBUS一个奥地利人写的Modbus协议。它是一个针对嵌入式应用的一个免费(自由)的通用MODBUS协议的移植。Modbus是一个工业制造环境中应用的一个通用协议.。
FreeMODBUS最新版本V1.5。下载地址:http://www.freemodbus.org/index.php?idx=5
下面进行的移植基于STM8S单片机的官方固件库
1、物理层接口文件修改(具体应修改接口文件portserial.c及porttimer.c)
portserial.c文件中:
void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable)函数设置串口状态。当xRxEnable为真时,应使能串口接收及接收中断。在RS485通讯系统中,还要注意将RS485接口芯片设为接收使能状态;当xTxEnable为真时,应使能串口发送及发送中断。在RS485通讯系统中,还要注意将RS485接口芯片设为发送使能状态。voidvMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ) //控制串口的收发中断
{
if(TRUE==xRxEnable)
{
UART1_ITConfig(UART1_IT_RXNE, ENABLE);
}
else
{
UART1_ITConfig(UART1_IT_RXNE, DISABLE);
}
if(TRUE==xTxEnable)
{
UART1_ITConfig(UART1_IT_TXE,ENABLE);
}
else
{
UART1_ITConfig(UART1_IT_TXE, DISABLE);
}
}
BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHARucDataBits, eMBParity eParity)函数初始化串行通讯端口。参数ucPORT可以忽略;参数ulBaudRate是通讯端口的波特率,应根据此数值设置所使用硬件端口的波特率;参数ucDataBits为通讯时所使用的数据位宽,注意,若使用RTU模式,则有ucDataBits=8,若使用ASCII模式,则有ucDataBits=7,应根据此参数设置所使用硬件端口的数据位宽;eParity为校验方式,eParity=MB_PAR_NONE为无校验,此时硬件端口应设置为无校验方式及两个停止位,eParity=MB_PAR_ODD为奇校验,此时硬件端口应设置为奇校验方式及一个停止位,eParity= MB_PAR_EVEN为偶校验,此时硬件端口应设置为偶校验方式及一个停止位。函数返回值务必为TRUE。
BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
UART1_WordLength_TypeDef databit;
UART1_Parity_TypeDef parity;
UART1_DeInit();
if(8==ucDataBits)
{
databit = UART1_WORDLENGTH_8D;
}
else
{
databit = UART1_WORDLENGTH_9D;
}
if(MB_PAR_NONE == eParity)
{
parity = UART1_PARITY_NO;
}
else if(MB_PAR_ODD == eParity)
{
parity = UART1_PARITY_ODD;
}
else
{
parity = UART1_PARITY_EVEN;
}
UART1_Init((uint32_t)ulBaudRate,databit, UART1_STOPBITS_1, parity,
UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
/* ENABLE the USARTx */
UART1_ITConfig(UART1_IT_TXE, ENABLE);
return TRUE;
}
BOOL xMBPortSerialPutByte( CHAR ucByte )通讯端口发送一字节数据函数。在此函数中编写发送一字节数据的函数。注意,由于使用的是中断发送,故只需将数据放到发送寄存器即可。函数返回值务必为TRUE。
BOOLxMBPortSerialPutByte( CHAR ucByte )
{
UART1_SendData8(ucByte);
return TRUE;
}
BOOL xMBPortSerialGetByte( CHAR * pucByte )通讯端口接收一字节数据函数。在此函数中编写接收的函数。由于使用的是中断接收,只需将接收寄存器的值放到* pucByte即可。函数返回值务必为TRUE。
BOOL xMBPortSerialGetByte( CHAR * pucByte )
{
*pucByte = UART1_ReceiveData8();
return TRUE;
}
void prvvUARTRxISR( void )和void prvvUARTTxReadyISR( void )无需修改。
portserial.c文件修改
BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )初始化超时定时器播函数。根据所使用的硬件初始化超时定时器,使之能产生中断时间为usTim1Timerout50us*50us的中断,本例移植采用单片机的TIM4定时器。函数返回值务必为TRUE。
BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )
{
/* TIM4 configuration:
- TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
clock used is 16 MHz / 128 = 125 000 Hz
- With 125 000 Hz we can generate time base:
max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
min time base is 0.016 ms if TIM4_PERIOD = 1 --> ( 1 + 1) / 125000 = 0.016 ms
--> 16us
- In this example we need to generate a time base equal to 50us
so TIM4_PERIOD = (0.00005 * 125000 - 1) = 5 */
/* Time base configuration */
TIM4_TimeBaseInit(TIM4_PRESCALER_128, 5);
/* Clear TIM4 update flag */
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
/* Enable update interrupt */
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
/* enable interrupts */
// enableInterrupts();
/* Enable TIM4 */
TIM4_Cmd(ENABLE);
return TRUE;;
}
void vMBPortTimersEnable( )使能超时定时器函数。需在此函数中清除中断标志位、清零定时器计数值,并重新使能定时器中断。
void vMBPortTimersEnable( ) //打开时钟
{
/* Clear TIM4 update flag */
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
/* Enable update interrupt */
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
TIM4_SetCounter(0x00);
/* Enable TIM4 */
TIM4_Cmd(ENABLE);
}
void vMBPortTimersDisable( )关闭超时定时器函数。在此函数中清零定时器计数值,并关闭定时器中断。
void vMBPortTimersDisable( ) //关闭时钟
{
TIM4_Cmd(DISABLE);
TIM4_SetCounter(0x00);
TIM4_ITConfig(TIM4_IT_UPDATE, DISABLE);
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
}
void prvvTIMERExpiredISR( void )函数不需修改。
2、 应用层回函数的修改
在应用层,用户需要定义所需要使用的寄存器,并修改对应的回函数。
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,USHORT usNRegs)输入寄存器回函数。* pucRegBuffer为协议中所需的数据,usAddress为输入寄存器地址,usNRegs为访问寄存器的个数,eMode为访问类型(MB_REG_READ为读保持寄存器,MB_REG_WRITE为写保持寄存器)。用户应根据要访问的寄存器地址usAddress将相应输入寄存器的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的寄存器地址usAddress放到相应保持寄存器中。
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;
}
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,USHORT usNRegs, eMBRegisterMode eMode)保持寄存器回函数。* pucRegBuffer为要协议中的数据,usAddress为输入寄存器地址,usNRegs为访问寄存器的个数,eMode为访问类型(MB_REG_READ为读保持寄存器,MB_REG_WRITE为写保持寄存器)。用户应根据要访问的寄存器地址usAddress将相应输入寄存器的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的寄存器地址usAddress放到相应保持寄存器中。
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
u16 *PRT=(u16*)pucRegBuffer;
if( ( usAddress >= REG_HOLDING_START ) && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegHoldingStart );
switch ( eMode )
{
case MB_REG_READ:
while( usNRegs > 0 )
{
//// *PRT++ = __REV16(usRegHoldingBuf[iRegIndex++]); //数据序转 REV16.W
*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
break;
case MB_REG_WRITE:
while( usNRegs > 0 )
{
//// usRegHoldingBuf[iRegIndex++] = __REV16(*PRT++); //数据序转 REV16.W
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,USHORT usNCoils, eMBRegisterMode eMode )读/写开关寄存器函数。* pucRegBuffer为要添加到协议中的数据,usAddress为地址,usNCoils为要访问的个数,eMode为访问类型(MB_REG_READ为读状态,MB_REG_WRITE为写)。用户应根据要访问的地址usAddress将相应的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的地址usAddress放到相应地址中。
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
( void )pucRegBuffer;
( void )usAddress;
( void )usNCoils;
( void )eMode;
return MB_ENOREG;
}
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )读开关寄存器函数。
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
( void )pucRegBuffer;
( void )usAddress;
( void )usNDiscrete;
return MB_ENOREG;
}
官方网站下载出问题,为了方便大家,附上FreeMODBUS源码
freemodbus-v1.5.0.zip
(5.9 MB, 下载次数: 0)
|
|