添加文件
- 获取原始free modbus library(官网)
- 将...\freemodbus-v1.5.0\demo\BARE中的所有文件复制到...\freemodbus-v1.5.0\modbus中,修改demo.c文件名为user_mb_app.c
- 将...\freemodbus-v1.5.0\modbus中的所有.c文件全部添加到项目中
- 在项目路径中添加所有.c、.h文件路径
添加完成后项目结构图:
移植修改
需要修改的文件:
- port.h:补全开关总中断的宏定义、宏定义串口和定时器
#define ENTER_CRITICAL_SECTION( ) __set_PRIMASK(1); //关闭中断 #define EXIT_CRITICAL_SECTION( ) __set_PRIMASK(0); //开启中断
- portserial.c:补全串口相关函数(串口中断使能选择、串口初始化、发送1字节、接收1字节、串口中断服务函数)
- 注意事项:
- 使能中断:发送中断应使用TC而非TXE,否则可能会出现最后一个字节不能成功发送的情况。此外由于是用485发送,所以在使能中断时,应同时转换485收发转换引脚。使能中断前,应判断对应的标志位是否为1,为1则清除该标志位。
- 串口初始化:初始化前用USART_DeInit重置寄存器;引脚初始化(GPIO)->串口初始化(USART)->中断初始化(NVIC);参数中的ucPORT和eParity都应该忽略。
- 发送1字节:不用循环等待发送完成,因为已经有发送完成中断了
- 串口中断服务函数:在stm32f0xx_it.c中添加USART3_4_IRQHandler函数,跳转到本文件中的prvvModbusUARTISR函数。
-
portserial.c
1 /* 2 * FreeModbus Libary: BARE Port 3 * Copyright (C) 2006 Christian Walter <wolti@sil.at> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 * File: $Id: portserial.c,v 1.1 2006/08/22 21:35:13 wolti Exp $ 20 */ 21 22 #include "port.h" 23 24 /* ----------------------- Modbus includes ----------------------------------*/ 25 #include "mb.h" 26 #include "mbport.h" 27 28 /* ----------------------- static functions ---------------------------------*/ 29 static void prvvUARTTxReadyISR( void ); 30 static void prvvUARTRxISR( void ); 31 32 #define MODBUS_SEND() (GPIO_SetBits(MODBUS_USART_CTRL_PORT, MODBUS_USART_CTRL_PIN)) 33 #define MODBUS_RECIEVE() (GPIO_ResetBits(MODBUS_USART_CTRL_PORT, MODBUS_USART_CTRL_PIN)) 34 35 /* ----------------------- Start implementation -----------------------------*/ 36 void 37 vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ) 38 { 39 /* If xRXEnable enable serial receive interrupts. If xTxENable enable 40 * transmitter empty interrupts. 41 */ 42 if(xRxEnable==TRUE) { 43 MODBUS_RECIEVE(); 44 if(USART_GetFlagStatus(MODBUS_USART, USART_FLAG_RXNE) == SET) { 45 USART_ClearFlag(MODBUS_USART, USART_FLAG_RXNE); 46 } 47 USART_ITConfig(MODBUS_USART, USART_IT_RXNE, ENABLE); 48 } else if(xRxEnable == FALSE) { 49 MODBUS_SEND(); 50 USART_ITConfig(MODBUS_USART, USART_IT_RXNE, DISABLE); 51 } 52 53 if(xTxEnable==TRUE) { 54 MODBUS_SEND(); 55 if(USART_GetFlagStatus(MODBUS_USART, USART_FLAG_TC) == SET) { 56 USART_ClearFlag(MODBUS_USART, USART_FLAG_TC); 57 } 58 USART_ITConfig(MODBUS_USART, USART_IT_TC, ENABLE); 59 } else if(xTxEnable == FALSE) { 60 MODBUS_RECIEVE(); 61 USART_ITConfig(MODBUS_USART, USART_IT_TC, DISABLE); 62 } 63 } 64 65 BOOL 66 xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) 67 { 68 /*****************************引脚初始化*************************************/ 69 GPIO_InitTypeDef GPIO_InitStructure; 70 71 //时钟使能 72 RCC_AHBPeriphClockCmd(MODBUS_USART_TX_CLK | MODBUS_USART_RX_CLK | MODBUS_USART_CTRL_CLK, ENABLE); 73 MODBUS_USART_CLK_INIT(MODBUS_USART_CLK, ENABLE); 74 75 //复用功能定义 76 GPIO_PinAFConfig(MODBUS_USART_TX_PORT, MODBUS_USART_TX_SOURCE, MODBUS_USART_TX_AF); 77 GPIO_PinAFConfig(MODBUS_USART_RX_PORT, MODBUS_USART_RX_SOURCE, MODBUS_USART_RX_AF); 78 79 //引脚功能定义 80 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 81 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 82 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; 83 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; //50MHz 84 85 //TX 86 GPIO_InitStructure.GPIO_Pin = MODBUS_USART_TX_PIN; 87 GPIO_Init(MODBUS_USART_TX_PORT, &GPIO_InitStructure); 88 89 //RX 90 GPIO_InitStructure.GPIO_Pin = MODBUS_USART_RX_PIN; 91 GPIO_Init(MODBUS_USART_RX_PORT, &GPIO_InitStructure); 92 93 //CTRL 94 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 95 GPIO_InitStructure.GPIO_Pin = MODBUS_USART_CTRL_PIN; 96 GPIO_Init(MODBUS_USART_CTRL_PORT, &GPIO_InitStructure); 97 MODBUS_RECIEVE(); //接收模式 98 99 /*****************************串口初始化*************************************/ 100 USART_InitTypeDef USART_InitStructure; 101 102 USART_InitStructure.USART_BaudRate = ulBaudRate; 103 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 104 USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; 105 USART_InitStructure.USART_Parity = USART_Parity_No; 106 USART_InitStructure.USART_StopBits = USART_StopBits_1; 107 USART_InitStructure.USART_WordLength = USART_WordLength_8b; 108 109 USART_Init(MODBUS_USART, &USART_InitStructure); 110 USART_Cmd(MODBUS_USART, ENABLE); 111 vMBPortSerialEnable(FALSE, FALSE); 112 113 /*****************************中断初始化*************************************/ 114 NVIC_InitTypeDef NVIC_InitStructure; 115 116 NVIC_InitStructure.NVIC_IRQChannel = USART3_4_IRQn; 117 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 118 NVIC_InitStructure.NVIC_IRQChannelPriority = 1; 119 120 NVIC_Init(&NVIC_InitStructure); 121 122 return TRUE; 123 } 124 125 BOOL 126 xMBPortSerialPutByte( CHAR ucByte ) 127 { 128 /* Put a byte in the UARTs transmit buffer. This function is called 129 * by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been 130 * called. */ 131 MODBUS_USART->TDR = ucByte; //此处不用等待发送完毕(TC),因为有发送完成中断 132 return TRUE; 133 } 134 135 BOOL 136 xMBPortSerialGetByte( CHAR * pucByte ) 137 { 138 /* Return the byte in the UARTs receive buffer. This function is called 139 * by the protocol stack after pxMBFrameCBByteReceived( ) has been called. 140 */ 141 *pucByte = MODBUS_USART->RDR; 142 return TRUE; 143 } 144 145 /* Create an interrupt handler for the transmit buffer empty interrupt 146 * (or an equivalent) for your target processor. This function should then 147 * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that 148 * a new character can be sent. The protocol stack will then call 149 * xMBPortSerialPutByte( ) to send the character. 150 */ 151 static void prvvUARTTxReadyISR( void ) 152 { 153 pxMBFrameCBTransmitterEmpty( ); 154 } 155 156 /* Create an interrupt handler for the receive interrupt for your target 157 * processor. This function should then call pxMBFrameCBByteReceived( ). The 158 * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the 159 * character. 160 */ 161 static void prvvUARTRxISR( void ) 162 { 163 pxMBFrameCBByteReceived( ); 164 } 165 166 void prvvModbusUARTISR( void ) 167 { 168 if(USART_GetITStatus(MODBUS_USART, USART_IT_TC) == SET) { 169 prvvUARTTxReadyISR(); 170 USART_ClearITPendingBit(MODBUS_USART, USART_IT_TC); 171 } 172 173 if(USART_GetITStatus(MODBUS_USART, USART_IT_RXNE) == SET) { 174 prvvUARTRxISR(); 175 USART_ClearITPendingBit(MODBUS_USART, USART_IT_RXNE); 176 } 177 }
- 注意事项: