打印
[应用相关]

STM32 上移植 FreeModbus RTU

[复制链接]
1978|39
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stm32jy|  楼主 | 2020-2-27 19:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
解压 freemodbus v1.6 源码 看到如下文件目录结构  




使用特权

评论回复
沙发
stm32jy|  楼主 | 2020-2-27 19:00 | 只看该作者
文件夹 demo 就是官方针对不同平台移植的测试代码
文件夹 doc 是一些说明性文档
文件夹 modbus 就是功能实现的源码所在了
文件夹 tools 是上位机软件

使用特权

评论回复
板凳
stm32jy|  楼主 | 2020-2-27 19:01 | 只看该作者
FREEMODBUS V1.6 压缩后 MODBUS 文件夹内容

使用特权

评论回复
地板
stm32jy|  楼主 | 2020-2-27 19:01 | 只看该作者
FREEMODBUS V1.6 压缩后 DEMO 文件夹内容

使用特权

评论回复
5
stm32jy|  楼主 | 2020-2-27 19:02 | 只看该作者
FREEMODBUS V1.6 压缩后 DEMO\BARE 文件夹内容

使用特权

评论回复
6
stm32jy|  楼主 | 2020-2-27 19:02 | 只看该作者
FREEMODBUS V1.6 压缩后 DEMO\BARE\port 文件夹内容

使用特权

评论回复
7
stm32jy|  楼主 | 2020-2-27 19:04 | 只看该作者
新 建 一 个 工 程 , 工 程 项 目 所 有 的 文 件 夹 名 为FreeModbus-STM32,在该文件夹内再建立一个文件夹 FreeModbus,然后
在文件夹 FreeModbus 下再分别建立一个 modbus 文件夹和 port 文件夹
工程项目所在文件夹下创建一个 FREEMODBUS 文件夹

使用特权

评论回复
8
stm32jy|  楼主 | 2020-2-27 19:04 | 只看该作者
工程项目所在文件夹 FREEMODBUS 下创建 modbus 文件夹和 port 文件夹

使用特权

评论回复
9
stm32jy|  楼主 | 2020-2-27 19:36 | 只看该作者
将 FreeModbusV1.6 下的 modbus 所有文件夹及文件拷贝到新建工程项目
FreeModbus 文件夹下的 modbus 子文件夹下

使用特权

评论回复
10
stm32jy|  楼主 | 2020-2-27 19:38 | 只看该作者
进入 FreeModbusV1.6 下的 demo 文件夹,看到有各个平台的测试代码文件夹,没
看到 STM32 的,但是看到 BARE 这个不带任何平台的代码文件,将 FreeModbusV1.6 下
\demo\BARE\port 下的所有文件拷贝到新建工程项目 FreeModbus 文件夹下\port 文件夹中

使用特权

评论回复
11
stm32jy|  楼主 | 2020-2-27 19:39 | 只看该作者
其中:
(1)、 port.h 需要修改。
(2)、 porteven.c 不需要任何修改
(3)、 portserial.c 需要修改
(4)、 porttimer.c 需要修改。
(5)、另外还需要在 main 函数增加 4 个回调函数。
(5.1)、操作输入寄存器的回调函数 eMBErrorCode eMBRegInputCB( UCHAR *
pucRegBuffer, USHORT usAddress, USHORT usNRegs )
(5.2)、操作保持寄存器的回调函数 eMBErrorCode eMBRegHoldingCB( UCHAR *
pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
(5.3 )、 操 作 线 圈 的 的 回 调 函 数 eMBErrorCode eMBRegCoilsCB( UCHAR *
pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
(5.4)、操作离散寄存器的的回调函数 eMBErrorCode eMBRegDiscreteCB( UCHAR *
pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )

使用特权

评论回复
12
stm32jy|  楼主 | 2020-2-27 19:39 | 只看该作者
打开 MDK,建立工程

使用特权

评论回复
13
stm32jy|  楼主 | 2020-2-27 19:40 | 只看该作者
打开 portserial.c 文件,这个是移植串口的,不管是 ASCII 模式还是 RTU 模式都需
要串口支持的, void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )函数,使能
或失能串口的,移植代码如下
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.
*/
if (xRxEnable) //接收使能
{
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能接收中断
GPIO_ResetBits(GPIOG, GPIO_Pin_8); //设置 RS485 接收
}
else //失能
{
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); //失能接收中断
GPIO_SetBits(GPIOG, GPIO_Pin_8); //设置 RS485 发送
}
if (xTxEnable) //发送使能
{
USART_ITConfig(USART2, USART_IT_TC, ENABLE); //使能
GPIO_SetBits(GPIOG, GPIO_Pin_8); //设置 RS485 发送
}
else //失能
{
USART_ITConfig(USART2, USART_IT_TC, DISABLE); //失能
GPIO_ResetBits(GPIOG, GPIO_Pin_8); //设置 RS485 接收
}
}


使用特权

评论回复
14
stm32jy|  楼主 | 2020-2-27 19:41 | 只看该作者
串口初始化函数 BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate,UCHAR ucDataBits, eMBParity eParity ),使用的是串口 2 进行通讯
BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
(void)ucPORT; //不修改串口号
(void)ucDataBits; //不修改数据位长度
(void)eParity; //不修改检验格式
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOG, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//
//管脚复用//
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
//
//发送管脚 PA.02
//接收管脚 PA.03
//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//
//485 芯片发送接收控制管脚
//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
//
//配置串口参数
//
USART_InitStructure.USART_BaudRate = ulBaudRate; //只修改波特率
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_Parity = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
//
//使能串口
//
USART_Cmd(USART2, ENABLE);
//
//配置中断优先级
//
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);return TRUE;
}


使用特权

评论回复
15
stm32jy|  楼主 | 2020-2-27 19:42 | 只看该作者
发送一个字节函数 BOOL xMBPortSerialPutByte( CHAR ucByte )
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. */
USART_SendData(USART2, ucByte); //发送一个字节
return TRUE;
}




使用特权

评论回复
16
stm32jy|  楼主 | 2020-2-27 19:43 | 只看该作者
接收一个字节函数 BOOL xMBPortSerialGetByte( CHAR * pucByte )
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;
}


使用特权

评论回复
17
stm32jy|  楼主 | 2020-2-27 19:44 | 只看该作者
串口中断服务函数 void USART2_IRQHandler(void)
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) //接收中断
{
prvvUARTRxISR();USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
if (USART_GetITStatus(USART2, USART_IT_TC) == SET) //发送中断
{
prvvUARTTxReadyISR();
USART_ClearITPendingBit(USART2, USART_IT_TC);
}
}




使用特权

评论回复
18
stm32jy|  楼主 | 2020-2-27 19:45 | 只看该作者
打开 porttimer.c 文件, RTU 模式需要定时器支持,定时器初始化函数
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
// return FALSE;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t PrescalerValue = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//
//HCLK 为 72MHz
//时基频率 72 / (1 + Prescaler) = 20KHz
//
PrescalerValue = (uint16_t)((SystemCoreClock / 20000) - 1);
//
//初始化定时器参数
//
TIM_TimeBaseStructure.TIM_Period = (uint16_t)usTim1Timerout50us;
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//
//使能预装
//
TIM_ARRPreloadConfig(TIM2, ENABLE);
//
//初始化中断优先级//
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
TIM_Cmd(TIM2, DISABLE);
return TRUE;
}




使用特权

评论回复
19
stm32jy|  楼主 | 2020-2-27 19:45 | 只看该作者
定时器使能函数 void vMBPortTimersEnable( )
void
vMBPortTimersEnable( )
{
/* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM2, 0x00000000);
TIM_Cmd(TIM2, ENABLE);
}


使用特权

评论回复
20
stm32jy|  楼主 | 2020-2-27 19:46 | 只看该作者
定时器失能函数 void vMBPortTimersDisable( )
void
vMBPortTimersDisable( )
{
/* Disable any pending timers. */
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
TIM_SetCounter(TIM2, 0x00000000);
TIM_Cmd(TIM2, DISABLE);
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

44

主题

1118

帖子

4

粉丝