前段时间了解了一下 Modbus 协议,移植了一次,不成功 http://www.openedv.com/thread-
67471-1-1.html,不过找到方法之后,再次完善
在官网上面下载源码,度娘上面有些被人家修改过的,喜欢原汁原味的朋友去官网上下载
本贴附件也附上源码
开发平台:原子哥探索者开发板 V2.2
编译环境:MDK5.17
STM32 官方库函数:V1.5.1
FreeModbu 版本:V1.5.0
一、解压源码后,看到文件目录结构
文件夹 demo 就是官方针对不同平台移植的测试代码
文件夹 doc 是一些说明性文档
文件夹 modbus 就是功能实现的源码所在了
文件夹 tools 是上位机软件
二、建立工程
2.1、新建一个工程(这个就随意了),建立文件夹 FreeModbus,将上面提到的 modbus 文
件夹整个拷贝到工程的 FreeModbus 文件夹中
2.2、进入 demo 文件夹,看到有各个平台的测试代码文件夹,没看到 STM32 的,但是看到
BARE 这个不带任何平台的代码文件,将里边的 port 文件夹拷贝到 FreeModbus 文件夹中
2.3、打开 MDK(用 IAR 也行,随意了),建立工程。。。(省略 1 万字)
三、添加代码
3.1、打开 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); //接收
}
else //失能
{
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); //失能接收中断
GPIO_SetBits(GPIOG, GPIO_Pin_8); //恢复发送
}
if (xTxEnable) //发送使能
{
USART_ITConfig(USART2, USART_IT_TC, ENABLE); //使能
GPIO_SetBits(GPIOG, GPIO_Pin_8); //发送
}
else //失能
{
USART_ITConfig(USART2, USART_IT_TC, DISABLE); //失能
GPIO_ResetBits(GPIOG, GPIO_Pin_8); //设置接收
}
}
3.1.1 、 串 口 初 始 化 函 数 BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate,
UCHAR ucDataBits, eMBParity eParity ),使用的是串口 2 进行通讯
BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity
eParity )
{
// return FALSE;
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;
}
3.1.2、发送一个字节函数 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;
}
3.1.3、接收一个字节函数 BOOL xMBPortSerialGetByte( CHAR * pucByte )
BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{