在STM32上移植FreeModbus RTU的一点经验总结
来源:互联网 发布:js获取div文本内容 编辑:程序博客网 时间:2024/05/19 23:23
这几天因为工作需要,移植了modbus RTU到STM32来,之前也听说过modbus,但是没有深入了解过,还以为会像usb 那样复杂的,经过这几天的折腾,发现真的太简单了。为了防止过段时间又忘记了怎么移植,在这里把移植过程记录下来,也为了方便初次接触modbus的人。
废话少说,首先去下载源码,我下载的是freemodbus-v1.5.0,解压后如图所示:
在demo文件夹中有很多移植好的例子,但是没有STM32的,不要紧,我们参考已有的例子来操作就可以了。在demo文件夹下新建一个文件夹,命名为STM32,将BARE文件夹里的文件全部复制过来。
然后,我们建立一个STM32的工程,我用的是mdk4.72,关于怎么建立工程我就不啰嗦了,在工程里添加modbus 和 port两个文件夹,并在文件夹里添加需要的文件,这些modbus的是在modbus文件夹下面,port的是在刚才新建的那个stm32文件夹下,port.c是我从别的地方弄过来的,里面就是一个开中断和一个关中断的函数,可以不要,我的工程如图:
乍一看,也有十几个文件,其实这些文件内容不多,很好理解,而且需要修改的只有port文件夹下的portserial.c 和 porttimer.c 。这两个文件里面有几个空函数,我们看名字就知道这些函数的作用了。
portserial.c 如下:
根据注释,可以知道vMBPortSerialEnable是串口发送和接收中断的控制的,包括发送中断和接收中断,在这里,我们用的是RXNE 和 TXE中断,代码如下:
而 xMBPortSerialInit 函数显然是串口初始化的了,因为我在usart.c已经有一个串口初始化函数,这里直接调用该初始化函数usart_init(ulBaudRate);同时将return FALSE 改成 return TRUE; 注意这里我们只用了波特率这个参数,其他参数直接忽略,你也可以根据自己需要改一下。
然后 xMBPortSerialPutByte 和 xMBPortSerialGetByte 分别是发送和接收一个字节数据的函数,这里我直接调用库函数;
最后还有两个中断处理函数,把前面的static 去掉,因为我不想把我的串口中断函数放到这个文件。然后我们在stm32f10x_it.c添加串口中断函数,如下:
至此,portserial.c处理完毕。
porttimer.c的移植和portserial.c十分相似,但是要特别注意定时器中断的时间长度应该是3.5个字符时间,我这里只是简单粗暴的按照波特率是9600时候计算的。文件很短,直接上代码
同样,在stm32f10x_it.c添加定时器中断处理函数,
然后,我们还需要自己写四个回调函数,分别是读输入寄存器函数、读写保持寄存器函数、读写线圈函数和读离散寄存器函数,一般只用读写保持寄存器函数即可,具体怎么实现可以参考demo文件夹里面众多的demo.c文件。
附近是我的代码,屡试不爽,大家可以参考一下
在demo文件夹中有很多移植好的例子,但是没有STM32的,不要紧,我们参考已有的例子来操作就可以了。在demo文件夹下新建一个文件夹,命名为STM32,将BARE文件夹里的文件全部复制过来。
然后,我们建立一个STM32的工程,我用的是mdk4.72,关于怎么建立工程我就不啰嗦了,在工程里添加modbus 和 port两个文件夹,并在文件夹里添加需要的文件,这些modbus的是在modbus文件夹下面,port的是在刚才新建的那个stm32文件夹下,port.c是我从别的地方弄过来的,里面就是一个开中断和一个关中断的函数,可以不要,我的工程如图:
乍一看,也有十几个文件,其实这些文件内容不多,很好理解,而且需要修改的只有port文件夹下的portserial.c 和 porttimer.c 。这两个文件里面有几个空函数,我们看名字就知道这些函数的作用了。
portserial.c 如下:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include \"port.h\"
/* ----------------------- Modbus includes ----------------------------------*/
#include \"mb.h\"
#include \"mbport.h\"
/* ----------------------- static functions ---------------------------------*/
static
void
prvvUARTTxReadyISR(
void
);
static
void
prvvUARTRxISR(
void
);
/* ----------------------- Start implementation -----------------------------*/
void
vMBPortSerialEnable(
BOOL
xRxEnable,
BOOL
xTxEnable )
{
/* If xRXEnable enable serial receive interrupts. If xTxENable enable
* transmitter empty interrupts.
*/
}
BOOL
xMBPortSerialInit(
UCHAR
ucPORT,
ULONG
ulBaudRate,
UCHAR
ucDataBits, eMBParity eParity )
{
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. */
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.
*/
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( );
}
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
void
vMBPortSerialEnable(
BOOL
xRxEnable,
BOOL
xTxEnable )
{
if
(TRUE==xRxEnable)
{
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
else
{
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
}
if
(TRUE==xTxEnable)
{
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}
else
{
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
}
然后 xMBPortSerialPutByte 和 xMBPortSerialGetByte 分别是发送和接收一个字节数据的函数,这里我直接调用库函数;
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
BOOL
xMBPortSerialPutByte(
CHAR
ucByte )
{
USART_SendData(USART1, ucByte);
while
(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
/*????·????ê??*/
{
}
return
TRUE;
}
BOOL
xMBPortSerialGetByte(
CHAR
* pucByte )
{
*pucByte = USART_ReceiveData(USART1);
return
TRUE;
}
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
void
USART1_IRQHandler(
void
)
{
if
(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
prvvUARTRxISR();
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
if
(USART_GetITStatus(USART1, USART_IT_TXE) == SET)
{
prvvUARTTxReadyISR();
// USART_ClearITPendingBit(USART1, USART_IT_TXE);
}
}
porttimer.c的移植和portserial.c十分相似,但是要特别注意定时器中断的时间长度应该是3.5个字符时间,我这里只是简单粗暴的按照波特率是9600时候计算的。文件很短,直接上代码
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
BOOL
xMBPortTimersInit(
USHORT
usTim1Timerout50us )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_DeInit(TIM2);
#if 0
TIM_TimeBaseStructure.TIM_Period = 0x7E54;
//CLK==24MHz ((1000000000/9600)*11*3.5)/(1000/24) == 0x7e54
TIM_TimeBaseStructure.TIM_Prescaler = 0x3;
#endif
// ?????????¤·?????????7200/72M = 0.0001,????100us????????1
//10us x 50 = 5ms,??5ms????????
TIM_TimeBaseStructure.TIM_Period = 50;
TIM_TimeBaseStructure.TIM_Prescaler = (7200 - 1);
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
return
TRUE;
}
void
vMBPortTimersEnable( )
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_SetCounter(TIM2, 0);
//TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}
void
vMBPortTimersDisable( )
{
TIM_SetCounter(TIM2, 0);
//TIM_Cmd(TIM2, DISABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
}
void
TIMERExpiredISR(
void
)
{
(
void
)pxMBPortCBTimerExpired();
}
[C] 纯文本查看 复制代码
1
2
3
4
5
void
TIM2_IRQHandler(
void
)
{
TIMERExpiredISR();
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
然后,我们还需要自己写四个回调函数,分别是读输入寄存器函数、读写保持寄存器函数、读写线圈函数和读离散寄存器函数,一般只用读写保持寄存器函数即可,具体怎么实现可以参考demo文件夹里面众多的demo.c文件。
附近是我的代码,屡试不爽,大家可以参考一下
3 0
- 在STM32上移植FreeModbus RTU的一点经验总结
- 在STM32上移植FreeModbus RTU的一点经验总结
- Freemodbus RTU在stm32上的移植分析
- Freemodbus RTU在stm32上的移植分析
- Freemodbus RTU在stm32上的移植分析
- Freemodbus RTU在stm32上的移植分析
- Freemodbus RTU在stm32上的移植分析
- freemodbus 在STM32上的移植
- FreeModbus在STM32上移植。
- freemodbus 在stm32+W5500平台上的移植
- FreeModbus 移植于STM32 实现Modbus RTU通信
- FreeModbus 移植于STM32 实现Modbus RTU通信
- STM32 FreeModbus RTU从机移植以及UART配置
- freemodbus在STM32F100C8上的移植
- 基于EncEthernet的FreeModbus-TCP 在stm32上的移植与测试
- 基于EncEthernet的FreeModbus-TCP 在stm32上的移植与测试
- STM32F103/107 移植Freemodbus RTU
- STM32 上移植FreeModbus详细过程(学习总结)
- RecyclerView初步认识
- VMware建立一个裸机linux
- jsp国际化/格式化标签库
- Linux周期性自动发送邮件
- Cocos2d Android项目手动编译日记之SDK版本(一)
- 在STM32上移植FreeModbus RTU的一点经验总结
- 【Unity】 相机移动脚本
- 获取tableView当前选中的cell
- JAVA逻辑运算符
- dbscan聚类算法的R实现
- java动态代理
- 向h文件拖属性不要偷懒
- java书籍合集
- C语言模拟加载及获取可执行文件目录