FreeModbus-移植到stm32f103

本文介绍了FreeModbus库在STM32嵌入式系统中的应用,重点讨论了如何通过串口收发数据,以及如何判断帧结束。FreeModbus利用串口发送完成中断进行数据传输,并依赖定时器来判断帧结束。同时,展示了如何初始化串口、定时器,以及实现中断服务函数。此外,还提供了读取输入、保持、线圈和离散寄存器的回调函数示例。遇到的问题包括寄存器地址理解及波特率设置,通过调整解决了问题。

参考:
https://www.amobbs.com/thread-5491615-1-1.html
https://wenku.baidu.com/view/fdae481db52acfc789ebc982.html

简介

FreeModbus是一款适合嵌入式系统使用,只具有从机功能的开源库。

运行机制

  1. 如何通过串口收发数据

freemodbus通过串口中断的方式接收和发送数据。串口中断接收毋庸置疑,在中断服务函数中把数据保存在数组中,以便稍后处理。但是串口发送中断使用哪种形式?
串口发送中断至少有两种方式,第一种,数据寄存器空中断,只要数据寄存器为空并且中断屏蔽位置位,那么中断就会发生;第二种,发送完成中断,若数据寄存器的数据发送完成并且中断屏蔽位置位,那么中断也会发送。建议各位使用串口发送完成中断。freemodbus多使用RS485通信中,从机要么接收要么发送,多数情况下从机处于接收状态,要有数据发送时才进入发送状态。进入发送状态时,数据被一个一个字节发送出去,当最后一个字节被发送出去之后,从机再次进入接收状态。如果使用发送寄存器为空中断,还需要使用其他的方法才可以判断最后一个字节的数据是否发送完成。如果使用数据寄存器为空中断,那么将很有可能丢失最后一个字节。

  1. 如何判断帧结束

Modbus协议中没有明显的开始符和结束符,而是通过帧与帧之间的间隔时间来判断的。如果在指定的时间内(3.5个字符时间),没有接收到新的字符数据,那么就认为收到了新的帧。Modbus通过时间来判断帧是否接受完成,自然需要单片机中的定时器配合。

需改动文件

  1. portserial.c
#include "port.h"
#include "stm32f10x.h"
#include "bsp_usart.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.
     */

    if (xRxEnable)
    {
   
   
        //使能串口接收中断
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    }
    else
    {
   
   
        USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
    }

    if (xTxEnable)
    {
   
   
        //使能串口发送完成中断
        USART_ITConfig(USART1, USART_IT_TC, ENABLE);
    }
    else
    {
   
   
        USART_ITConfig(USART1, USART_IT_TC, DISABLE);
    }


}

BOOL
xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity)//适配串口初始化
{
   
   
    USART_Config(ulBaudRate);
    return TRUE;
}

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(USART1, 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(USART1);
    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();
}

//串口中断服务函数
void USART1_IRQHandler(void)//适配中断服务函数
{
   
   
    if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//接收中断
    {
   
   
        prvvUARTRxISR();
        USART_ClearITPendingBit(USART1, USART_IT_RXNE)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tangYi0_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值