/**********************************freemodbus移植文件**************************
1、 这个文件依赖于uart.c文件,作为uart.c文件的补充,当不使用modbus时,单独使用
uart.c文件就可以完成串口通信
2、 当使用modbus时,使用此文件中的modbusInit初始化函数初始化串口
3、 寄存器在这个文件里定义,如果要在主程序里使用,则要在主程序里extern引用
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "modbus.h"
#include "uart.h"
#include "mb.h"
#include "mbport.h"
#include "mbutils.h"
TIM_HandleTypeDef TimHandle;
extern UART_HandleTypeDef UartHandle;
extern void prvvUARTTxReadyISR(void);
extern void prvvUARTRxISR(void);
extern void TIMERExpiredISR(void);
#define TYPECOIL 1
#define TYPEREG 2
//Modbus更新标志,用来被其他程序使用
uint8_t flagUpdate = 0;
uint8_t regType = 0; //1,写的线圈,2,写的保持寄存器
uint8_t regIndex = 0; //修改的寄存器的索引
uint8_t regNum = 0; //修改的寄存器的数量
eMBErrorCode eStatus; //Modbus错误状态相关变量
eMBParity mbparity = MB_PAR_NONE; //modbus初始化用的parity
//线圈输出控制寄存器
#define REG_COILS_START 1000
#define REG_COILS_SIZE 8 //这里代表的是8个点,所以只需要/8个寄存器
unsigned char ucRegCoilsBuf[REG_COILS_SIZE/8] = {0x00};
//离散输入
#define REG_DISC_START 1000
#define REG_DISC_SIZE 8 //这里代表的是8个点,所以只需要/8个寄存器
static unsigned char ucRegDiscBuf[REG_DISC_SIZE / 8] = {0x08}; //MSB是第8号,LSB是IN0
//输入寄存器变量
#define REG_INPUT_START 1000 //输入寄存器起始地址
#define REG_INPUT_NREGS 2 //输入寄存器总长度
uint16_t usRegInputStart = REG_INPUT_START; //输入寄存器变量
uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x0100,0x0100}; //硬件版本1.00,软件版本1.00
//保持寄存器变量
#define REG_HOLDING_START 1000 //保持寄存器起始地址
#define REG_HOLDING_NREGS 16 //保持寄存器总长度
uint16_t usRegHoldingStart = REG_HOLDING_START;
uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x1111,0x2222,0x3333,0x4444,0x5555,0x6666};
///-----------------modbus配置函数--------------------------------------------
//描述:配置串口为中断模式
void ModbusInit(uint8_t devaddr,uint32_t baudrate,uint32_t datlen,uint32_t parity)
{
//初始化串口
UART_Init_para(&UartHandle,baudrate,datlen,parity);
Modbus_TR_Init();
Modbus_Rx();
//初始化Modbus,参数分别是:模式、从机地址、端口、波特率、校验模式
eStatus = eMBInit( MB_RTU, devaddr, 0, baudrate, mbparity );
/* 使能Modbus堆栈 */
eStatus = eMBEnable();
if(eStatus != MB_ENOERR)
{
//出错了
printf("err");
}
}
///--------------------------------读输入寄存器------------------------------------------------------------
//返回的错误代码的取值范围
//MB_ENOERR, /*!< no error. */
//MB_ENOREG, /*!< illegal register address. */
//MB_EINVAL, /*!< illegal argument. */
///--------------------------------------------------------------------------------------------------------
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;
}
///--------------------------------读写保持寄存器------------------------------------------------------------
//eMode的取值
//MB_REG_READ, /*!< Read register values and pass to protocol stack. */
//MB_REG_WRITE /*!< Update register values. */
///----------------------------------------------------------------------------------------------------------
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:
{
//返回读取的寄存器的内容,先返高字节,再返低字节
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
break;
}
//写操作
case MB_REG_WRITE:
{
//-------------------------------------------------------
//标记标志,提供给其他程序使用
flagUpdate = 1;
regType = TYPEREG;
//记录索引,提供给其他程序使用
regIndex = iRegIndex;
regNum = usNRegs;
//-------------------------------------------------------
//先写入高字节,再写入低字节
while( usNRegs > 0 )
{
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
break;
}
}
}
else
{
eStatus = MB_ENOREG;
}
//返回错误代码
return eStatus;
}
///--------------------------------读写线圈-----------------------------------------------------------------
//线圈,读写,单个比特
///---------------------------------------------------------------------------------------------------------
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
short iNCoils = ( short )usNCoils;
unsigned short usBitOffset;
/* Check if we have registers mapped at this block. */
if( ( usAddress >= REG_COILS_START ) && ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
{
usBitOffset = ( unsigned short )( usAddress - REG_COILS_START );
switch ( eMode )
{
/* Read current values and pass to protocol stack. */
case MB_REG_READ:
while( iNCoils > 0 )
{
*pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
( unsigned char )( iNCoils >
8 ? 8 :
iNCoils ) );
iNCoils -= 8;
usBitOffset += 8;
}
break;
/* Update current register values. */
case MB_REG_WRITE:
//-------------------------------------------------------
//标记标志
flagUpdate = 1;
regType = TYPECOIL;
//-------------------------------------------------------
while( iNCoils > 0 )
{
xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
( unsigned char )( iNCoils > 8 ? 8 : iNCoils ),
*pucRegBuffer++ );
iNCoils -= 8;
}
break;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
///-------