- /* ----------------------- Start implementation -----------------------------*/
- void
- vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
- {
- /* If xRXEnable enable serial receive interrupts. If xTxENable enable
- * transmitter empty interrupts.
- */
-
- if(xRxEnable == TRUE)//串口接收中断使能
- {
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//UART中断使能
- }
- else
- {
- USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//禁止接收和接收中断
- }
- if(xTxEnable == TRUE) //串口发送中断使能
- {
- USART_ITConfig(USART2, USART_IT_TC, ENABLE);//使能发送中断
- }
- else
- {
- USART_ITConfig(USART2, USART_IT_TC, DISABLE);//禁止发送中断
- }
- }
- BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,UCHAR ucDataBits, eMBParity eParity,UCHAR ucStopBits )
- {
- USART2_Init();//初始化串口
- return FALSE;
- }
- 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. */
- while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
- USART_SendData(USART2, ucByte);
- 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.
- */
- *pucByte = USART_ReceiveData(USART2);
- 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.
- */
- static 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.
- */
- static void prvvUARTRxISR( void )
- {
- pxMBFrameCBByteReceived( );
- }
- /*********************************************************************
- * @fn USART2_IRQHandler
- *
- * [url=/u/brief]@brief[/url] This function handles USART2 global interrupt request.
- *
- * [url=/u/return]@return[/url] none
- */
- void USART2_IRQHandler(void)
- {
- if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
- {
- prvvUARTRxISR(); //串口接收中断调用函数
- USART_ClearITPendingBit(USART2,USART_FLAG_RXNE);
- }
- if(USART_GetITStatus(USART2, USART_IT_ORE) != RESET)
- {
- prvvUARTRxISR(); //串口接收中断调用函数
- USART_ClearITPendingBit(USART2,USART_IT_ORE);
- }
- if(USART_GetITStatus(USART2, USART_IT_TC) != RESET)
- {
- prvvUARTTxReadyISR(); //串口接收中断调用函数
- USART_ClearITPendingBit(USART2, USART_IT_TC);
- }
- }
7、修改porttimer.c文件
modbus工作时需要一个定时器来周期工作,定时器时基是50us,周期做为参数输入,去掉前面的inline,具体代码如下:
- /* ----------------------- Platform includes --------------------------------*/
- #include "port.h"
- #include "debug.h"
- /* ----------------------- Modbus includes ----------------------------------*/
- #include "mb.h"
- #include "mbport.h"
- void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- /* ----------------------- static functions ---------------------------------*/
- static void prvvTIMERExpiredISR( void );
- /* ----------------------- Start implementation -----------------------------*/
- BOOL
- xMBPortTimersInit( USHORT usTim1Timerout50us )
- {
- TIM1_INT_Init( usTim1Timerout50us);
- return TRUE;
- }
- void vMBPortTimersEnable( )
- {
- /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
- TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
- TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
- TIM_SetCounter(TIM1,0x0000);
- TIM_Cmd(TIM1, ENABLE);
- }
- void vMBPortTimersDisable( )
- {
- /* Disable any pending timers. */
- TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
- TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE);
- TIM_SetCounter(TIM1,0x0000);
- TIM_Cmd(TIM1, DISABLE);
- }
- /* 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.
- */
- static void prvvTIMERExpiredISR( void )
- {
- ( void )pxMBPortCBTimerExpired( );
- }
- void TIM1_UP_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM1, TIM_IT_Update)==SET)
- {
- prvvTIMERExpiredISR();
- TIM_ClearITPendingBit( TIM1, TIM_IT_Update );
- }
- }
8、修改mbconfig.h文件
如图修改,主要修改支持RTU形式
9、在主函数初始定时器和串口,代码如下
- /*********************************************************************
- * @fn main
- *
- * @brief Main program.
- *
- * @return none
- */
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- SystemCoreClockUpdate();
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d\r\n",SystemCoreClock);
- printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
- printf("This is printf example\r\n");
- modbus_task();
- }
- /*********************************************************************
- * @fn USART2_Init
- *
- * @brief Initializes the USART2 peripheral.
- *
- * @return none
- */
- void USART2_Init(void) {
- GPIO_InitTypeDef GPIO_InitStructure = {0};
- USART_InitTypeDef USART_InitStructure = {0};
- NVIC_InitTypeDef NVIC_InitStructure = {0};
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- /* USART2 TX-->A.2 RX-->A.3 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- USART_InitStructure.USART_BaudRate = 115200;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- USART_Init(USART2, &USART_InitStructure);
- // USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//UART中断使能
- // USART_ITConfig(USART2, USART_IT_TC, ENABLE);//使能发送中断
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- USART_Cmd(USART2, ENABLE);
- }
- /*********************************************************************
- * @fn TIM1_INT_Init
- *
- * @brief Initializes TIM1 output compare.
- *
- * @param arr - the period value.
- * psc - the prescaler value.
- *
- * @return none
- */
- void TIM1_INT_Init(u16 psc)
- {
- NVIC_InitTypeDef NVIC_InitStructure={0};
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE );
- TIM_TimeBaseInitStructure.TIM_Period = psc * 50;
- TIM_TimeBaseInitStructure.TIM_Prescaler = 95;
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);
- TIM_ClearITPendingBit( TIM1, TIM_IT_Update );
- NVIC_InitStructure.NVIC_IRQChannel =TIM1_UP_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;
- NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
10、在新建mbtask.c文件添加modbus相关寄存器和函数
代码如下:
- #include "stdio.h"
- #include "mbtask.h"
- #include "debug.h"
- /* ----------------------- Static variables ---------------------------------*/
- static USHORT usRegInputStart = REG_INPUT_START;
- static USHORT usRegInputBuf[REG_INPUT_NREGS] = {0x1234, 0x5678, 0x9ABC, 0xDEF0};
- static USHORT usRegHoldingStart = REG_HOLDING_START;
- static USHORT usRegHoldingBuf[REG_HOLDING_NREGS] = {0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
- //coils buffer
- static UCHAR ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x01, 0x02};
- //discrete Inputs buffer
- static UCHAR ucRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x80, 0x90};
- void modbus_task(void)
- {
- eMBErrorCode eStatus;
-
- /* ucPort: select port_uart.
- * this parameter can be one of the following values:
- * 0: USART2: tx--PA2, rx--PA3, de--PA1;
- * 1: USART3: tx--PB10, rx--PB11, de--PB14;
- * other: invalid.
- */
- eStatus = eMBInit(MB_RTU, MB_SLAVE_ADDRESS, 0, MB_BAUDRATE, MB_PAR_NONE);
- if(MB_ENOERR == eStatus)
- {
- printf("modbus init ok\r\n");
- eStatus = eMBEnable();
- if(MB_ENOERR == eStatus)
- {
- printf("modbus enable ok\r\n");
- }
- else
- {
- printf("modbus enable fail, error code: %u\r\n", eStatus);
- }
- }
- else
- {
- printf("modbus init fail, error code: %u\r\n", eStatus);
- }
-
- if(MB_ENOERR != eStatus)
- {
- printf("exit modbus task.\r\n");
- return;
- }
-
- printf("start modbus pooling..\r\n");
- for(;;){
- eMBPoll();
- }
- }
- /****************************************************************************
- * brief: read input register;
- * responsive function code:
- * 04 (Read Input Register).
- * param: pucRegBuffer: data buffer, used for respond master;
- * usAddress: register address;
- * usNRegs: register number.
- * retval: eStatus: error code.
- ****************************************************************************/
- 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;
- }
- /****************************************************************************
- * brief: read/write holding register;
- * responsive function code:
- * 06 (Write Holding Register);
- * 16 (Write Multiple Holding Register);
- * 03 (Read Holding Register);
- * 23 (Read/Write Multiple Holding Register).
- * param: pucRegBuffer: data buffer, used for respond master;
- * usAddress: register address;
- * usNRegs: register number;
- * eMode: access register mode.
- * retval: eStatus: error code.
- ****************************************************************************/
- 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:
- while( usNRegs > 0 )
- {
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- extern void xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits, UCHAR ucValue );
- extern UCHAR xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits );
- /****************************************************************************
- * brief: read/write coils;
- * responsive function code:
- * 01 (Read Coils);
- * 05 (Write Coil);
- * 15 (Write Multiple Coils).
- * param: pucRegBuffer: data buffer, used for respond master;
- * usAddress: coils address;
- * usNCoils: coils number;
- * eMode: access register mode.
- * retval: eStatus: error code.
- ****************************************************************************/
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
- eMBRegisterMode eMode )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int16_t iNCoils = ( int16_t )usNCoils;
- int16_t usBitOffset;
-
- if( ( (int16_t)usAddress >= REG_COILS_START ) &&
- ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
- {
- usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
- switch ( eMode )
- {
- case MB_REG_READ:
- while( iNCoils > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
- iNCoils -= 8;
- usBitOffset += 8;
- }
- break;
-
- case MB_REG_WRITE:
- while( iNCoils > 0 )
- {
- xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
- *pucRegBuffer++ );
- iNCoils -= 8;
- }
- break;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /****************************************************************************
- * brief: read discrete inputs;
- * responsive function code:
- * 02 (read discrete inputs).
- * param: pucRegBuffer: data buffer, used for respond master;
- * usAddress: discrete inputs address;
- * usNDiscrete: discrete inputs number.
- * retval: eStatus: error code.
- ****************************************************************************/
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int16_t iNDiscrete = ( int16_t )usNDiscrete;
- uint16_t usBitOffset;
-
- if( ( (int16_t)usAddress >= REG_DISCRETE_START ) &&
- ( usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISCRETE_SIZE ) )
- {
- usBitOffset = ( uint16_t )( usAddress - REG_DISCRETE_START );
-
- while( iNDiscrete > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits( ucRegDiscreteBuf, usBitOffset,
- ( uint8_t)( iNDiscrete > 8 ? 8 : iNDiscrete ) );
- iNDiscrete -= 8;
- usBitOffset += 8;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
mbtask.h文件
- #ifndef __MBTASK_H
- #define __MBTASK_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* ----------------------- Modbus includes ----------------------------------*/
- #include "mb.h"
- #include "mbport.h"
- /* ----------------------- Defines ------------------------------------------*/
- #define MB_SLAVE_ADDRESS ( 0x01 )
- #define MB_BAUDRATE ( 115200 )
- //input register start address
- #define REG_INPUT_START ( 1 )
- //input register number
- #define REG_INPUT_NREGS ( 16 )
- //holding register start address
- #define REG_HOLDING_START ( 1 )
- //holding register number
- #define REG_HOLDING_NREGS ( 16 )
- //coils start address
- #define REG_COILS_START ( 1 )
- //coils number
- #define REG_COILS_SIZE ( 16 )
- //discrete inputs start address
- #define REG_DISCRETE_START ( 1 )
- //discrete inputs number
- #define REG_DISCRETE_SIZE ( 16 )
- void modbus_task(void);
- #ifdef __cplusplus
- }
- #endif
- #endif
11、移植成功后,编译无误,下载验证
日志打印
MODBUS初始化成功
读保持寄存器测试
写保持寄存器测试
移植modbus-rtu完成