FreeModBusRtu移植 --stm32L431RCT6(小熊派)

文章目录

  • 前言
  • 一、移植前需要的工作
  • 二、修改点讲解
    • 1.串口中断
    • 2.定时器
    • 3.保持寄存器
    • 4.测试
  • 总结


前言

最近需要做一个modbus485的传感器,主要是用来做从机。之前做过主机的是stm标准库,那这次做一个HAL的从机协议栈,方便大家直接获取数据。
移植成功的代码仓库如下:Freemodbus从机仓库代码


一、移植前需要的工作

1.了解modbus485协议(协议帧内容含义等等)
2.选一块stm32的开发板(随便选,能用stm32cubemx就行)
3.移植这个协议,主要关注3点,串口、定时器以及数据存储的寄存器缓冲区

二、修改点讲解

1.串口中断

portserial.c :


extern UART_HandleTypeDef huart1;


/* ----------------------- Start implementation -----------------------------*/
BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
                       eMBParity eParity)
{
    //这个是用stm32cubemx生成的函数名称,我增加了参数
	MX_USART1_UART_Init(ulBaudRate);
    return TRUE;
}

void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
{
   ENTER_CRITICAL_SECTION();
		  
  if (xRxEnable)
  {
  	  //使能串口接收中断
	 __HAL_UART_ENABLE_IT(&huart1, USART_IT_RXNE);
  }
  else
  {
     //关闭串口接收中断
	 __HAL_UART_DISABLE_IT(&huart1, USART_IT_RXNE);
  }


  if (xTxEnable)
  {
     //使能串口发送中断
	 __HAL_UART_ENABLE_IT(&huart1, USART_IT_TXE);
  }
  else
  {
 	 //关闭串口发送中断
	 __HAL_UART_DISABLE_IT(&huart1, USART_IT_TXE);
  }
	  
  EXIT_CRITICAL_SECTION();

}

void vMBPortClose(void)
{
	//不做函数处理
}

BOOL xMBPortSerialPutByte(CHAR ucByte)
{ 
	// 发送串口数据 一次发送一个数据
	HAL_UART_Transmit(&huart1, &ucByte,1,5);
    return TRUE;
}

BOOL xMBPortSerialGetByte(CHAR *pucByte)
{
	// 获取串口数据 一次拿一个数据
	HAL_UART_Receive(&huart1,pucByte,1, 0);	
    return TRUE;
}
void prvvUARTTxReadyISR(void)
{
    pxMBFrameCBTransmitterEmpty();
}

void prvvUARTRxISR(void)
{
    pxMBFrameCBByteReceived();

}

void USART1_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart1);
  if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
  {    //获取接收RXNE标志位是否被置位
	 prvvUARTRxISR();
	 __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);
	
  } 
  
  if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) == SET)
  {
	prvvUARTTxReadyISR();
	__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_TXE);
  }
 

}

2.定时器

代码如下:

BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
{
	//这个是用stm32cubemx生成的函数名称,我增加了参数
	MX_TIM2_Init(usTim1Timerout50us);
    return TRUE;
}

void vMBPortTimersEnable()
{
    // 开启定时器,计算是否超时
	__HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);  // 清除中断标志位
    __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE); //开启定时器自动更新中断
	__HAL_TIM_SET_COUNTER(&htim2, 0x0000);  // 设置计数器的值为0
	__HAL_TIM_ENABLE(&htim2);   // 开启定时器中断
}

void vMBPortTimersDisable()
{   
	__HAL_TIM_DISABLE(&htim2);    // 关闭定时器中断
	__HAL_TIM_SET_COUNTER(&htim2, 0x0000);  // 设置计数器的值为0
	__HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE); //关闭定时器自动更新中断
	__HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);  // 清除中断标志位
}

void prvvTIMERExpiredISR(void)
{
    (void)pxMBPortCBTimerExpired();
}

void TIM2_IRQHandler(void)
{
  HAL_TIM_IRQHandler(&htim2);
  if(__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET)
  {
    prvvTIMERExpiredISR();
  	__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);  // 清除中断标志位
  }
}

3.保持寄存器

在寄存器中,我们需要划分我们自己的寄存器的含义,从而达到数据传输的含义

#define S_REG_HOLDING_START           0
#这是一个倾角传感器的保持寄存器数据划分
/*----------------------------------------
*         划分保持寄存器的类型区域            
*========================================
* 0 |从机地址
*-----------------------------------------
* 1 |X轴角度 
*-----------------------------------------
* 2 |Y轴角度
*-----------------------------------------
* 3 |Z轴角度
*-----------------------------------------
*/
#define S_SLAVEID_REG_START S_REG_HOLDING_START
#define S_SLAVEID_REG_NUM  1
#define S_SLAVEID_REG_END S_SLAVEID_REG_START+S_SLAVEID_REG_NUM

#define S_XANGLE_REG_START S_SLAVEID_REG_END
#define S_XANGLE_REG_NUM 1
#define S_XANGLE_REG_END S_XANGLE_REG_START+S_XANGLE_REG_NUM

#define S_YANGLE_REG_START S_XANGLE_REG_END
#define S_YANGLE_REG_NUM 1
#define S_YANGLE_REG_END S_YANGLE_REG_START+S_YANGLE_REG_NUM

#define S_ZANGLE_REG_START S_YANGLE_REG_END
#define S_ZANGLE_REG_NUM 1
#define S_ZANGLE_REG_END S_ZANGLE_REG_START+S_ZANGLE_REG_NUM


//当你发送指令过来时,最终的解析在这里。这是一个关键的函数,要想理解这个函数,你要多参考前面的接口。
//usAddress 要查询的寄存器地址 usNRegs 寄存器数量  eMode 模式  pucRegBuffer 缓冲区
//这个函数就是根据usAddress ,从你的保持寄存器usSRegHoldBuf中读出想要的数据返回给主机。
eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
        USHORT usNRegs, eMBRegisterMode eMode)
{
    eMBErrorCode    eStatus = MB_ENOERR;
    USHORT          iRegIndex;
    USHORT 			*pusRegHoldingBuf;
    USHORT          reg_holding_start;
    USHORT          reg_holding_nregs;
    USHORT          usRegHoldStart;

    pusRegHoldingBuf = usSRegHoldBuf;
    reg_holding_start = S_REG_HOLDING_START;
    reg_holding_nregs = S_REG_HOLDING_NREGS;
    usRegHoldStart = usSRegHoldStart;

    /* it already plus one in modbus function method. */
    usAddress--;

    if ((usAddress >= reg_holding_start)
            && (usAddress + usNRegs <= reg_holding_start + reg_holding_nregs))
    {
        iRegIndex = usAddress - usRegHoldStart;
        switch (eMode)
        {
        /* read current register values from the protocol stack. */
        case MB_REG_READ:
            while (usNRegs > 0)
            {
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                iRegIndex++;
                usNRegs--;
            }
            break;

        /* write current register values with new values from the protocol stack. */
        case MB_REG_WRITE:
            while (usNRegs > 0)
            {
                pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                iRegIndex++;
                usNRegs--;
            }
            break;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}

4.测试

在这里插入图片描述
在这里插入图片描述

注意烧写的时候要擦除整片芯片

在这里插入图片描述


总结

多多指教

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/685070.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux驱动开发笔记(四)设备树进阶及GPIO、Pinctrl子系统

文章目录 前言一、设备树的进阶知识1. 追加/修改节点内容2.chosen子节点3. 获取设备树节点信息3.1 of_find_node_by_path( )函数3.2 of_find_node_by_name( )函数3.3 of_find_node_by_type( )函数3.4 of_find_compatible_node( )函数3.5 of_find_matching_node_and_match( )函数…

前端_调试工具_Chrome Devtools

目录 一、上左侧菜单功能 1.选择功能 2.手机/电脑 显示切换功能 3.内存 4.元素 5.控制台 6.源代码/来源 7.网络 8.应用 9.性能 10.安全 11.Lighthouse 12.记录器 13.性能数据分析 二、上右侧菜单功能 1.警告 2.设置 3....更多功能 谷歌浏览器自带了调试工具C…

TPC-H建表语句(MySQL语法)

TPC-H测试集介绍 TPC-H&#xff08;Transaction Processing Performance Council, Standard Specification, Decision Support Benchmark, 简称TPC-H&#xff09;是一个非常权威数据库基准测试程序&#xff0c;由TPC组织制定。 TPC-H定义了一个包含8个表的模式&#xff08;Sc…

亮数据代理IP助力高效数据采集

文章目录 &#x1f4d1;前言一、爬虫数据采集痛点二、代理IP解决爬虫痛点2.1 为什么可以2.2 本篇采用的代理IP 四、零代码获取数据4.1 前置背景4.2 亮数据浏览器自动抓取数据4.3 使用步骤&#xff1a; 五、数据集5.1 免费样本5.2 定制数据集 &#x1f324;️个人小结 &#x1f…

力扣 503. 下一个更大元素 II

题目来源&#xff1a;https://leetcode.cn/problems/next-greater-element-ii/description/ C题解&#xff1a;因为是循环数组&#xff0c;所以对数组进行了两次遍历&#xff0c;相当于循环。使用了栈&#xff0c;一个存放元素&#xff0c;一个存放索引&#xff0c;用来更新res…

龙迅LT8712X TYPE-C或者DP转HDMI加VGA输出,内置MCU,只是IIS以及4K60HZ分辨率

龙迅LT8712X描述&#xff1a; LT8712X是一种高性能的Type-C/DP1.2到HDMI2.0和VGA转换器&#xff0c;设计用于将USB Type-C源或DP1.2源连接到HDMI2.0和VGA接收器。LT8712X集成了一个DP1.2兼容的接收器&#xff0c;一个HDMI2.0兼容的发射机和一个高速三角机窝视频DAC。此外&…

AppInventor2有没有删除后的撤销功能?

问&#xff1a;不小心删除了组件&#xff0c;能撤回吗&#xff1f; 答&#xff1a;界面&#xff08;组件&#xff09;设计界面&#xff0c;没有撤销功能。代码&#xff08;逻辑&#xff09;设计视图&#xff0c;可以使用 CtrlZ 撤销&#xff0c;CtrlY 反撤销。 界面设计没有撤…

关于2024中国海洋装备博览会(福州)的参展通知

2024中国航洋装备博览会 2024世界航海装备大会 2024中国船舶供应链大会 2024中国航洋装备博览会2024世界航海装备大会 时间地点、规模、主题、定位 1.时间&#xff1a;2024年11月15日至18日 2.地点&#xff1a;福州海峡国际会展中心、冠城大通游艇码头 3.规模&#xff1…

【ROS2大白话】三、给turtlebot3安装realsense深度相机

系列文章目录 【ROS2大白话】一、ROS2 humble及cartorgrapher安装 【ROS2大白话】二、turtlebot3安装 【ROS2大白话】三、给turtlebot3安装realsense深度相机 【ROS2大白话】四、ROS2非常简单的传参方式 文章目录 系列文章目录效果展示一、修改model.sdf文件1. 路径位置2. 修改…

Day25 首页待办事项及备忘录添加功能

​ 本章节,完成首页待办事项及备忘录添加功能 一.修改待办事项和备忘录逻辑处理类,即AddMemoViewModel和AddTodoViewModel 在 AddMemoViewModel逻辑处理类中,为了支持与其关联的View视图文件的数据绑定,需要定义一个与视图文件相匹配的实体类 Model。这个Model将包含 View中…

冯喜运:6.6外汇黄金原油晚间行情预测及独家操作建议

【黄金消息面分析】&#xff1a;周三&#xff08;6月5日&#xff09;&#xff0c;黄金价格继续区间波动并上涨&#xff0c;与周二的价格走势形成鲜明对比&#xff0c;此前美国公布的经济数据好坏参半&#xff0c;可能促使美联储降低借贷成本。美国国债收益率下降&#xff0c;美…

支付宝小众玩法 爱溜达的人不容错过

创建一个简单的程序来帮助用户管理他们的图片&#xff0c;例如筛选分辨率合适、尺寸适中的图片来准备上传&#xff0c;这是一个技术上合理且有益的方向。例如&#xff0c;一个Python脚本使用Pillow库来检查文件夹中图片的尺寸&#xff1a; from PIL import Image import os# 根…

深圳比创达EMC|EMC电磁兼容性行业:技术前沿与市场挑战

在当今高度信息化的社会&#xff0c;电磁兼容性&#xff08;EMC&#xff09;技术已成为各行各业不可或缺的一部分。随着电子设备的日益增多和复杂化&#xff0c;电磁环境日益复杂&#xff0c;电磁兼容性行业面临着前所未有的挑战和机遇。 一、EMC电磁兼容性行业的技术基础 电…

Qt图像处理技术十一:得到QImage图像的马赛克图像

效果图 指数5 指数15 指数40 原理 马赛克的原理很简单&#xff0c;就是取一个值&#xff0c;让这个值作为一个方格子的长宽&#xff0c;如40*40px的格子&#xff0c;取这个区域的平均R G B值&#xff0c;然后这个区域的所有像素点都是这个RGB值即可 源码 QImage applyM…

新能源管理系统主要包括哪些方面的功能?

随着全球对可持续发展和环境保护的日益重视&#xff0c;新能源管理系统已成为现代能源领域的核心组成部分。这一系统不仅涉及对新能源的收集、存储和管理&#xff0c;还包括对整个能源网络进行高效、智能的监控和控制。以下是新能源管理系统主要包含的几方面功能&#xff1a; 一…

STM32 HAL库USART的接收数据方法实现

目录 概述 1 使用STM32Cube生成项目 1.1 软件版本信息 1.2 配置串口相关参数 1.3 生成工程 2 问题描述 3 解决问题 3.1 修改代码 3.2 编写新的回调函数 4 测试 概述 本文主要介绍STM32 HAL库USART的接收数据方法实现&#xff0c;笔者使用的HAL库为STM32Cube_FW_F1_V1.…

鸿蒙开发 之 Stage模型

1.介绍 2.工程目录以及配置文件说明 配置文件 3.UIAbility创建流程 注意&#xff1a;退出应用先销毁的是windowStage之后是ability 4.页面及生命周期 5.UIAbility启动模式

【Mybatis】INSERT INTO 遇到NULL怎么处理?

目录标题 背景-使用Mybatis手写批量插入Insert方法测试核心代码&#xff0c;author字段为null&#xff0c;插入条件怎么写&#xff1f; MybatisPlus解决方案自动填充字段 Mybatis解决方案if标签处理 问题&#xff1a;如果不在工程里面设置默认值&#xff1f;如何直接使用数据库…

Qt窗口与对话框

目录 Qt窗口 1.菜单栏 2.工具栏 3.状态栏 4.滑动窗口 QT对话框 1.基础对话框QDiaog 创建新的ui文件 模态对话框与非模态对话框 2.消息对话框 QMessageBox 3.QColorDialog 4.QFileDialog文件对话框 5.QFontDialog 6.QInputDialog Qt窗口 前言&#xff1a;之前以上…

Java Logback 基本操作

一、环境搭建 配置 maven &#xff1a; JavaWeb开发中的Maven使用_javaweb项目中如何使用manven项目-CSDN博客 配置 eclipse &#xff1a; eclipse新建Maven web项目全过程-CSDN博客 二、下载Logback 下载地址&#xff1a; Maven Repository: ch.qos.logback logback-clas…