用stm32库函数编写的modbus源代码
基于STM32处理器的ModbusTCP/RTU网关设计
![基于STM32处理器的ModbusTCP/RTU网关设计](https://img.taocdn.com/s3/m/b97b9708cc17552707220894.png)
2系统硬件设计
本设 计 的处 理 器采 用S T M3 2 F1 0 3 V E, 它是 意 法 半 导 体 推 出 的 基 F A R M C o r t e x— M 3 内 核 的高性 能 微 处理 器 。 C o r t e x - M3 处理 器 是 行业 领 先 的3 2 位 处 理 器 ,适 用于具 有高 确定性 的 实时应 用 ,已专 门开 发 为 允 许 合 作 伙伴 为范 围广 泛 的 设 备 ( 包括微 控制 器 ,汽车车 体 系统 ,工 业控 制 系统 以及无 线网络 和传 感器 )开发 高性 能低 成 本的平 台 。整体 的硬件 结构 如 图2 所示 。 如 图3 所 示 , 网 关 和 客 户 机 之 间 采 用 Mo d b u s TCP 协 议 通讯 ,相 对 于 客 户 机 言 , 网关 工 作 在 服 务 器 模式 , 它通 过 以 太 网接 收 来 自客 户 机 的数 据 包 ,并 解 析 该 数 据 包 ,从 而 根 据 不 同 的 数据 指 令 执 行 相 应 的处 理 。 网关f l J Mo d b u s 串 口设备 之 间 采用 Mo d b u s RT U协议 通讯 ,相 对 于 从 设 备 而 言它 又具 有Mo d b u s 主 站功 能 。 网关 将接 收 到的 Mo d b u s TC P 协议 包 进 行协 议转 换 之后 将Mo d b u s R TU协议 帧通过 串 口发 送到 从设 备 ,并 接受 来 自从 设备 的响 应。
关键 词
S T M 3 2 F 1 0 3:M o d b u s T C P;M o d b u s E T U ; 协 议 转
换 ;u 『 P
中 图分类 号 :T P 2 4 文献标 识 码 :B
FreemodbusRTU在stm32上的移植分析
![FreemodbusRTU在stm32上的移植分析](https://img.taocdn.com/s3/m/dcc4d8923086bceb19e8b8f67c1cfad6195fe917.png)
FreemodbusRTU在stm32上的移植分析在物联网时代,工业自动化领域的发展日益迅猛。
作为一种常见的通信协议,Modbus被广泛应用于工业控制系统中。
而在嵌入式系统中,STM32是一种常见的微控制器,其强大的性能和丰富的外设使其成为了工业自动化领域的首选。
本文将探讨如何将FreemodbusRTU协议移植到STM32上,并分析移植过程中的关键问题。
一、FreemodbusRTU简介FreemodbusRTU是一种基于Modbus协议的开源库,它提供了一套完整的Modbus通信接口函数,方便用户在嵌入式系统中实现Modbus通信功能。
与其他商业化的Modbus库相比,FreemodbusRTU具有开源免费的优势,同时其轻量级的特点使得它适合于资源有限的嵌入式系统。
二、STM32的特点与优势STM32是意法半导体(STMicroelectronics)推出的一款32位微控制器系列,它基于ARM Cortex-M内核,拥有丰富的外设资源和强大的性能。
STM32系列微控制器广泛应用于工业自动化、智能家居、电力电子等领域。
其中,STM32F4系列是性能最强大的一款,具有高性能的浮点运算单元和大容量的闪存,适合于对性能要求较高的应用场景。
三、移植FreemodbusRTU到STM32的步骤1. 硬件连接在移植前,需要将STM32的串口与Modbus从站设备进行连接。
通过串口,STM32可以与其他设备进行数据交换。
在连接时,需要注意串口的波特率、数据位、校验位和住手位等参数的设置,确保与Modbus从站设备保持一致。
2. 引入FreemodbusRTU库将FreemodbusRTU库的源码添加到STM32的工程中。
可以通过将源码文件直接添加到工程目录下,或者使用版本控制工具进行管理。
在引入库的同时,需要根据具体的硬件平台和编译器进行相应的配置。
3. 配置Modbus参数在移植过程中,需要根据具体的应用场景配置Modbus参数。
freemodbus在stm32上的移植
![freemodbus在stm32上的移植](https://img.taocdn.com/s3/m/e8b542f3941ea76e58fa0452.png)
portother.c
//负责一个串口的配置 为了省事我只支持了波特率的修改
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )负责控制串口【收/发】中断的禁止与使能 pxMBFrameCBByteReceived( ); //在串口接收中断内调用 用于通讯侦测 pxMBFrameCBTransmitterEmpty( ); //在串口发送中断内调用 用于告知完成了发送 发送缓冲为空 xMBPortSerialGetByte( CHAR * pucByte ) xMBPortSerialPutByte( CHAR ucByte ) 两个为 串口字节的收发
//
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
//Βιβλιοθήκη iRegIndex++;
usNRegs--;
}
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
受到 freeModbus 作者使用“assert()”的影响在这个里我用了__REV16()这个函数
Modbus 中文协议.PDF
STM32移植 FreeModbus 的步骤:
首先去 下载文件 一定要是官方可靠的才行,我起先为了图方便网上随便下载了一个,结果白白 浪费了一下午的时间
不知道是哪里被改动了。目前最新的版本是1.5。
stm32modbusrtu代码
![stm32modbusrtu代码](https://img.taocdn.com/s3/m/90c44e43a517866fb84ae45c3b3567ec112ddc4e.png)
stm32modbusrtu代码STM32 Modbus RTU代码概述Modbus是一种串行通信协议,用于在工业自动化系统中传输数据。
Modbus RTU是一种基于串行通信的Modbus协议版本,它使用二进制编码来传输数据。
STM32是一款微控制器,它可以通过编程来实现Modbus RTU通信。
本文将介绍如何使用STM32编写Modbus RTU代码。
硬件要求- STM32微控制器- 串口模块- Modbus RTU从机设备软件要求- Keil MDK集成开发环境- STM32CubeMX代码生成工具- Modbus库文件步骤1.创建新项目首先,在Keil MDK中创建一个新的STM32项目。
2.配置MCU参数使用STM32CubeMX配置MCU参数,包括时钟频率、GPIO引脚等。
3.添加库文件和头文件将Modbus库文件和头文件添加到项目中。
4.初始化串口模块使用STM32CubeMX初始化串口模块,并设置波特率、数据位、停止位等参数。
5.初始化Modbus从机设备使用Modbus库文件初始化从机设备,并设置地址、函数码等参数。
6.编写读取数据函数编写函数以读取从机设备的数据。
该函数应该发送一个读取请求并接收响应数据。
7.编写写入数据函数编写函数以写入数据到从机设备。
该函数应该发送一个写入请求并接收响应数据。
8.编写主函数在主函数中调用读取数据和写入数据函数。
9.编译和烧录程序使用Keil MDK编译程序,并将其烧录到STM32微控制器中。
总结本文介绍了如何使用STM32编写Modbus RTU代码。
通过按照上述步骤,您可以创建一个可靠的Modbus RTU通信系统,用于在工业自动化系统中传输数据。
发个STM32的MODBUS主节点程序
![发个STM32的MODBUS主节点程序](https://img.taocdn.com/s3/m/275361d7240c844769eaee3e.png)
发个STM32的MODBUS主节点程序由于课题的原因被强迫用了STM32(本来打算2440的),因此认识阿莫电子,看到了版上一众高手,并学了不少知识。
在课题中很多芯片资料的细节都是来源于阿莫电子,快毕业了,潜水了太久,就分享一点STM32的程序,反正很多都是从坛子里学的,我只是整理下拿来用了,献丑了。
处理器STM32F103ZET6是买论坛上一摄像头大师的(感谢免费帮我修了次3232),软件用的KEIL3.5。
我的MODBUS是驱动变频器的,做主节点用,主要实现03功能号和06功能号。
#define RS485Read (GPIO_WriteBit(GPIOG, GPIO_Pin_13,Bit_RESET))#define RS485Write (GPIO_WriteBit(GPIOG, GPIO_Pin_13,Bit_SET))//MODBUS的06功能号,读多个寄存器void ReadInverter(UINT16 Addr,UINT8 N,UINT16 *Values){UINT8 i,l;UINT16 tmp;UINT16 *p;//在发送缓冲里面填数据Inverter.SendBuf[0]=InverterAddr;Inverter.SendBuf[1]=ReadID;Inverter.SendBuf[2]=Addr>>8;Inverter.SendBuf[3]=Addr&0XFF;Inverter.SendBuf[4]=0;Inverter.SendBuf[5]=N;//计算CRC16,填入发送缓冲尾CalCRC(Inverter.SendBuf,6,Inverter.SendBuf+6);//置RS485发送状态RS485Write();//发送数据缓冲Uart_Send(InverterUart,Inverter.SendBuf,8);//清发送缓冲PurgeRecvBuf();m=LISTENING;//关定时器TIM5TIM_Cmd(TIM5, DISABLE);USART_ITConfig(InverterUart,USART_IT_RXNE,ENABLE);RS485Read();Delay(200,m);//既定延时400ms,若m的值变化则退出ResetInverterComm();m=TIME_OUT;//接收缓冲中数据长度为0,则表示超时无应答if(Inverter.Length==0){Inverter.Error=TIME_OUT; //("变频器应答超时");return ;}m=FINISHED;//长度校验if(Inverter.RecvBuf[2]!=Inverter.Length-5){Inverter.Error=FrameErr;return ;//("变频器数据长度错误");}CalCRC(Inverter.RecvBuf,Inverter.Length-2,CRC16);//CRC校验if(*(UINT16 *)(CRC16)!=*(UINT16 *)(Inverter.RecvBuf+Inverter.Length-2)) {Inverter.Error=CheckErr;return ;//("变频器校验错误");}else if(Inverter.RecvBuf[1]==ReadID+0X80){//("变频器读错误,错误号在第三个字节");switch(Inverter.RecvBuf[2]){case Invalid_Func:i =Invalid_Func; break;case Invalid_Addr:i =Invalid_Addr; break;case Invalid_Data:i =Invalid_Data; break;case InverterErr :i =InverterErr ; break;case InverterBusy:i =InverterBusy; break;case CheckErr :i =CheckErr ; break;default :i =UnknowErr ; break;}Inverter.Error=i;return ;}//校验一切正常,变频器操作成功else if(Inverter.RecvBuf[1]==ReadID){l=Inverter.RecvBuf[2]+3;p=(UINT16 *)Values;//接收数据for(i=3;i<l;i+=2){tmp=Inverter.RecvBuf[i];tmp=tmp<<8;tmp=tmp+Inverter.RecvBuf[i+1];*p=tmp;p++;}Inverter.Error=MODBUS_OK;//("读入参数成功:");return ;}//校验一切正常,变频器操作失败else if(Inverter.RecvBuf[1]!=ReadID&&Inverter.RecvBuf[1]!=ReadID+0X80) {Inverter.Error=UnknowErr;//("变频器应答错误");return ;}return ;}void TIM5_IRQHandler(void){if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET){TIM_ClearITPendingBit(TIM5, TIM_IT_Update);TIM_ClearFlag(TIM5, TIM_IT_Update);m=FINISHED;TIM_Cmd(TIM5, DISABLE);USART_ITConfig(InverterUart,USART_IT_RXNE,DISABLE);}}void USART3_IRQHandler(void){if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){USART_ClearITPendingBit(USART3, USART_IT_RXNE);if(Inverter.Length<=17){Inverter.RecvBuf[Inverter.Length]=USART_ReceiveData(USART3);Inverter.Length++;}TIM_Cmd(TIM5, ENABLE);TIM_SetCounter(TIM5,0x0000);}}。
stm32modbusrtu代码
![stm32modbusrtu代码](https://img.taocdn.com/s3/m/cb0e3264814d2b160b4e767f5acfa1c7aa008233.png)
STM32 Modbus RTU 代码简介Modbus是一种通信协议,常用于工业自动化领域中的设备间通信。
STM32是一系列由意法半导体(STMicroelectronics)开发的32位微控制器。
在本文中,我们将探讨如何使用STM32微控制器编写Modbus RTU代码。
Modbus RTU 协议Modbus RTU是Modbus协议的一种变体,它使用二进制编码来进行数据传输。
RTU代表”Remote Terminal Unit”,是指远程终端单元,也就是Modbus网络中的从设备。
Modbus RTU协议使用串口通信,并且以字节为单位进行数据传输。
每个字节都包含8位数据位和1位奇偶校验位。
STM32 微控制器STM32微控制器是一款高性能、低功耗的32位ARM Cortex-M内核微控制器。
它具有丰富的外设和强大的处理能力,非常适合用于工业自动化等领域。
STM32微控制器支持多个串口接口,并且具有强大的时钟和计时功能,非常适合用于实现Modbus RTU通信。
编写 STM32 Modbus RTU 代码要编写STM32 Modbus RTU代码,我们需要以下步骤:1. 硬件连接首先,我们需要将STM32微控制器与Modbus RTU从设备进行硬件连接。
通常,我们会使用串口接口来进行通信。
确保正确连接了串口的TX和RX引脚。
2. 配置串口在STM32的代码中,我们需要配置串口接口的参数,如波特率、数据位、校验位等。
根据Modbus RTU协议的要求,通常使用9600波特率、8个数据位和无校验位。
以下是一个配置串口的示例代码:// 配置串口void UART_Config(void){// 初始化结构体USART_InitTypeDef USART_InitStruct;// 使能串口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// 配置波特率、数据位和停止位USART_ART_BaudRate = 9600;USART_ART_WordLength = USART_WordLength_8b;USART_ART_StopBits = USART_StopBits_1;// 配置校验位为无校验USART_ART_Parity = USART_Parity_No;// 配置硬件流控制为无流控制USART_ART_HardwareFlowControl = USART_HardwareFlowControl_Non e;// 使能接收和发送功能USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 初始化串口USART_Init(USART1, &USART_InitStruct);// 使能串口USART_Cmd(USART1, ENABLE);}3. 实现 Modbus RTU 功能接下来,我们需要实现Modbus RTU的功能代码。
modbus协议在stm32f103处理器上的实现
![modbus协议在stm32f103处理器上的实现](https://img.taocdn.com/s3/m/54122f23b14e852459fb57b2.png)
Hot-Point Perspective热点透视DCW157数字通信世界2020.011 M ODBUS 协议MODBUS 协议是Modicon 公司(现在的施耐德电气)于1979年发明的一种串行通信协议,最初是为解决可编程逻辑控制器(PLC )之间通信而制定的,现在在常用的控制器上都可以实现。
MODBUS 协议采用主从问答方式进行工作,允许一个主机与一个或者多个从机通讯,通过此协议,控制器相互之间、控制器经由网络(如以太网)和其他设备之间可以通信。
不同厂商生产的控制设备通过MODBUS 协议可以连成工业网络,进行集中监控。
MODBUS 协议有两种传输方式:ASCII 和RTU 。
对于ASCII 模式,一个字节的数据,需要把高低4位分别转换为ASCII 码传输;而RTU 模式,是按16进制字符传输的。
通过比较可以看出,相对于ASCII 模式,RTU 模式表达同样的信息需要的位数较少,在同样的传输速率下能获取更多的信息,可以提高通讯的效率。
本文采用RTU 传输模式,RTU 模式的消息帧结构如表1所示。
表1 MODBUS 帧结构从站号功能码数据区CRC16校验和1字节1字节1-252字节2字节2 硬件设计本设计采用了意法半导体的STM32系列微控制器,该控制器内核采用超低功率的ARMCortex-M3核心,具有高性能、低成本、低功耗的特点,同时集成了丰富出众的外设系统,具有集成度高和开发便捷的优势。
系统硬件结构图如图1所示。
图1 系统硬件结构图系统硬件包括stm32f103微控制器、485通信电路、时钟电路、复位电路和电源电路等。
stm32f103微控制器完成串口数据收发、数据帧的组包与解包、数据处理等,485通信电路部分采用了MAX483芯片,完成USART 串口到485总线的转换,通过高速光耦隔离芯片TLP2362和stm32f103微控制器的USART 串口连接。
3 软件设计3.1 主程序主程序首先完成外设的初始化,初始化完成后就等待串口中断,MODBUS 数据接收和发送都在串口中断中调用相应的函数完成。
基于STM32的FreeModbus从站协议移植
![基于STM32的FreeModbus从站协议移植](https://img.taocdn.com/s3/m/7d72d7792af90242a895e5d4.png)
基于STM32的FreeModbus从站协议移植作者:胡双喜来源:《科学与财富》2018年第31期摘要:FreeModbus是一种Modbus协议的实现方式,能够方便的移植到嵌入式系统中。
本文阐述了FreeModbus的移植方式,并将其与STM32F446RE控制器相结合。
经验证表明,其能够完成基于Modbus RTU传输方式的通讯任务,具有稳定可靠的特点,可以应用于工业场合。
关键词:Modbus;STM32;实时通信一、引言随着工业IT技术的飞速发展以及工业控制系统复杂程度的提高,工业通讯网络的应用日益受到重视,通讯协议的标准化对工业控制系统的稳定性产生了极大的影响。
Modbus是一种广泛应用的工业控制网络,其具有稳定性高、易于部署和维护等优点,适合中小规模的数据传输。
FreeModbus是一种针对嵌入式系统的Modbus协议栈,支持RTU、ASCII以及TCP传输模式,并遵守BSD许可,允许用户将其应用于商业环境。
STM32是目前广泛应用的32位嵌入式微处理器之一,具有体积小、功耗低、性能高等特点,非常适合于系统的实时控制。
其中STM32F4系列是意法半导体推出的以Cortex-M4为内核的高性能控制器,能够进行复杂的计算与控制。
本文以STM32F446RE为平台,研究了FreeModbus协议的移植方法,使STM32F446RE 能够作为从站实现Modbus的通信,并支持Modbus RTU及ASCII传输模式,为未来工业控制的网络化和信息化奠定了基础。
二、FreeModbus简介Modbus是一种广泛应用于工业控制中的串行通讯协议,其实现了一个单主站的主从网络结构。
Modbus支持的数据类型包括浮点数、32为整型等多种数据类型。
目前,西门子S7 200系列等多个系列的PLC、威纶通等不同厂家、型号的触摸屏以及组态王等软件都支持Modbus 协议。
FreeModbus是专门针对嵌入式系统设计的开源协议栈,其实现了Modbus 1.1a版的应用层协议,支持RTU与ASCII两种传输模式,在FreeModbus 0.7版后,又添加了Modbus TCP传输模式的支持。
stm32modbusrtu代码
![stm32modbusrtu代码](https://img.taocdn.com/s3/m/d493d54491c69ec3d5bbfd0a79563c1ec5dad73e.png)
stm32modbusrtu代码STM32 MODBUS RTU是一种通信协议,用于串行通信。
STM32是意法半导体公司(STMicroelectronics)推出的一系列32位单片机。
本文将为您提供STM32 MODBUS RTU相关的参考内容。
1. 开发环境搭建:搭建开发环境是进行STM32 MODBUS RTU开发的第一步。
您可以使用Keil或IAR等集成开发环境进行开发。
在这些开发环境中,您可以配置开发板参数、编写代码、编译和调试程序。
同时,您还需要安装STM32CubeMX软件来配置通信接口和外设。
2. MODBUS RTU协议介绍:了解MODBUS RTU协议是进行STM32 MODBUS RTU开发的关键。
该协议定义了从机应答格式、帧结构、数据帧编码等规则。
您可以通过查阅MODBUS RTU协议文档来深入了解协议的各个方面。
此外,还有很多MODBUS RTU通信库可供参考,您可以了解这些库的使用和示例代码,如libmodbus、MODBUS-Master-Slave-for-Arduino等。
3. 寄存器配置和访问:在STM32 MODBUS RTU开发中,需要了解寄存器的配置和访问。
MODBUS RTU协议使用寄存器来传输数据。
您需要了解如何配置和访问离散寄存器(Coil)、输入寄存器(Input Register)、保持寄存器(Holding Register)和文件记录寄存器(File Record Register)等。
同时,还需要熟悉MODBUS寄存器地址的映射关系。
4. UART通信配置:STM32单片机通常使用UART进行串行通信。
您需要了解如何配置UART通信参数,如串口波特率、数据位、停止位、奇偶校验等。
在STM32CubeMX软件中,您可以方便地配置UART通信参数,并生成对应的初始化代码。
5. MODBUS RTU从机实现:在STM32 MODBUS RTU开发过程中,需要实现MODBUS RTU从机功能。
FreemodbusRTU在stm32上的移植分析
![FreemodbusRTU在stm32上的移植分析](https://img.taocdn.com/s3/m/33d4db4a326c1eb91a37f111f18583d049640ffe.png)
FreemodbusRTU在stm32上的移植分析导入前的原始以太网测试工程将prot以及modbu文件夹拷贝到工程文件夹下,导入工程,将demo中的main等几个函数拷贝到原先main.c 中,注释掉原先的mian函数,就成了这个样子:先理清所有依赖关系,肯定出现一大堆找不到头文件宏定义什么的错误,这个在keil中将文件夹的路径添加到includepath中即可,非常方便。
rebuild一下,发现有两个错误:原来Keil4不支持inline这个关键字,直接将其删掉,编译出现了:..\\Output\\STM32-DEMO.a某f:Error:L6218E:Undefinedymbol__aeabi_aert(referredfrommbacii.o).出现的这个问题,各种百度以及谷歌,找了半天也没找到解决方法。
这里不得不说百度虽然本土化做得很好,可是以英文作为关键词时,往往搜出一大堆不相干的东西,基本上搜不到国外的网页;谷歌本土化做的不好,服务器响应比较慢。
想起360新出了搜索引擎,赶紧去试试,还真的有惊喜,在一篇帖子中写道“MicroLib并不支援aert(),所以才会出现错误讯息”,原来原工程使用了微库,在target中钩掉USEMicroLIB编译就可以通过了。
昨天看优库老友记采访周鸿祎说360做搜索引擎,作为360的忠实用户应该支持一下。
任何一个公司想做的更好,必须注意用户体验。
下面开始正式的移植以及分析和测试工作:无论是modbuASCII还是RTU模式,都以串口通讯做为载体,需要添加串口的使能BOOL某MBPortSerialInit,收发中断的使能voidvMBPortSerialEnable(BOOL某R某Enable,BOOL某T某Enable),发送以及接收BOOL某MBPortSerialPutByte(CHARucByte),BOOL某MBPortSerialGetByte(CHAR某pucByte),这几个函数没什么好说的,有两个中断函数我比较好奇,就是taticvoidprvvUARTT某ReadyISR(void)以及taticvoidprvvUARTR某ISR(void),就是一个发送中断一个接收中断,为什么是这样的名字呢,tm32串口发生中断怎么去调用它们呢,如果换成其他单片机,为什么是这样的一个名字呢?原来在freemodbu中并没有提供中断函数的具体名称,还需要根据自己使用的处理器自己添加中断处理函数voidUSART1_IRQHandler(void),在其中调用上述两个发送和接收的函数。
(完整word版)STM32F107串口通信RS232modbus(去注释方便打印)
![(完整word版)STM32F107串口通信RS232modbus(去注释方便打印)](https://img.taocdn.com/s3/m/b7bb7dd14b35eefdc9d3335a.png)
Main#include "stm32f10x_lib.h"typedef enum { FAILED = 0, PASSED = !FAILED} TestStatus;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;//#define countof(a) (sizeof(a) / sizeof(*(a)))u32 CCR1_Val=1000;USART_InitTypeDef USART_InitStructure;//u8 NbrOfDataToTransfer1 ;//u8 NbrOfDataToRead1;volatile TestStatus TransferStatus1 = FAILED;ErrorStatus HSEStartUpStatus;void RCC_Configuration(void);void GPIO_Configuration(void);void NVIC_Configuration(void);void Uart_config(void);void TIM2_config(void);extern void Com0_Communication(void);TestStatus Buffercmp(u8* pBuffer1, u8* pBuffer2, u16 BufferLength);int main(void){#ifdef DEBUGdebug();#endif/* System Clocks Configuration */RCC_Configuration();/* NVIC configuration */NVIC_Configuration();/* Configure the GPIO ports */GPIO_Configuration();Uart_config();TIM2_config();while (1){Com0_Communication();void RCC_Configuration(void){/* RCC system reset(for debug purpose) */RCC_DeInit();/* Enable HSE */RCC_HSEConfig(RCC_HSE_ON);/* Wait till HSE is ready */HSEStartUpStatus = RCC_WaitForHSEStartUp();if(HSEStartUpStatus == SUCCESS){/* Enable Prefetch Buffer */FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);/* Flash 2 wait state */FLASH_SetLatency(FLASH_Latency_2);/* HCLK = SYSCLK */RCC_HCLKConfig(RCC_SYSCLK_Div1);/* PCLK2 = HCLK */RCC_PCLK2Config(RCC_HCLK_Div1);/* PCLK1 = HCLK/2 */RCC_PCLK1Config(RCC_HCLK_Div2);/* PLLCLK = 8MHz * 9 = 72 MHz */RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/* Enable PLL */RCC_PLLCmd(ENABLE);/* Wait till PLL is ready */while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}/* Select PLL as system clock source */RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);/* Wait till PLL is used as system clock source */while(RCC_GetSYSCLKSource() != 0x08){/* TIM2 clock enable */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);/* Enable USART1, GPIOA, GPIOA and AFIO clocks */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);}void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;/* Configure USART1 Rx (PA.10) as input floating */GPIO_InitStructure。
基于STM32的modbus-rtu实现
![基于STM32的modbus-rtu实现](https://img.taocdn.com/s3/m/3d3fb59bdc88d0d233d4b14e852458fb770b38b5.png)
基于STM32的modbus-rtu实现本⽂引⾃/*****************************************************modbus-rtu 通讯规约通讯⽅式:rs-485 半双功校验⽅式:crc16停⽌位:2位编写:孙可编程思路:1.串⼝中断允许⾃动接收总线上的信息,当接收的字节后超过3.5个字节时间没有新的字节认为本次接收完成,接收完成标志置1;如果接收完成标志已经置1⼜有数据进来则丢弃新来的数据。
2.串⼝接收数据的处理, 当接收完成标志置1进⼊接收数据处理, (1)⾸先判断接收的第⼀位数据与本机地址是否相同,如果不相同清空接收缓存不发送任何信息; (2)接收的第⼀位数据与本机地址相同,则对接收缓存中的数据进⾏crc16校验,如果接收的校验位与本校验结果不相同清空接收缓存不发送任何信息;(3)如果crc16校验正确则根据数据串中的命令码进⾏相应的处理。
******************************************************/#include "modbus.h"u8 Com0_id = 0x05;//本机串⼝0的通讯地址u8 Uart0_rev_buff[100];//com0串⼝接收缓冲区u8 Uart0_send_buff[100];//com0串⼝发送缓冲区vu8 Uart0_rev_count;vs8 Uart0_send_counter = 0;vu8 Uart0_rev_comflag;vu8 Crc_counter = 0;//com0校验计数器vu8 *Uart0_send_pointer = Uart0_send_buff;//com0串⼝发送指针vu16 Mkgz_bz = 0;//模块故障标志1:输⼊异常,2:过压,3:⽋压,4:过温vu16 Out_current = 50;//输出电流vu16 Out_voltage = 240;//输出电压vu16 Mkzt_bz = 0;//模块状态标志vu16 OutX_current = 1000;//输出限流vu16 Jc_voltage = 2530;//均充电压vu16 Fc_voltage = 2400;//浮充电压vu16 user_day = 1825;//使⽤天数void Delay(vu32 nCount);unsigned short getCRC16(volatile unsigned char *ptr,unsigned char len) ;void mov_data(u8 a[100],u8 b[100],u8 c);void Modbus_Function_3(void);void Modbus_Function_6(void);/***************************************函数名称:crc16校验函数功能:crc16校验函数输⼊:字节指针*ptr,数据长度len函数返回:双字节crc函数编写:孙可编写⽇期:2008年6⽉9⽇函数版本:v0.2****************************************/unsigned short getCRC16(volatile unsigned char *ptr,unsigned char len){unsigned char i;unsigned short crc = 0xFFFF;if(len==0){len = 1;}while(len--){crc ^= *ptr;for(i=0; i<8; i++){if(crc&1){crc >>= 1;crc ^= 0xA001;}else{crc >>= 1;}}ptr++;}return(crc);}/***************************************块数据复制数据函数功能:把数组a的c个数据复制到数组b中输⼊:指针a,指针b,数据个数c返回:⽆编写:孙可编写⽇期:2008年3⽉28⽇版本:v0.1****************************************/void mov_data(u8 a[100],u8 b[100],u8 c){u8 i;for(i=c; i>0; i--){a = b;}}///////////////////////////////////////////////////////////////////////void Modbus_Function_3(void){u16 tempdress = 0;u8 i = 3;u16 crcresult;tempdress = (Uart0_rev_buff[2] << 8) + Uart0_rev_buff[3];if((tempdress >= 0x0120) & (tempdress + Uart0_rev_buff[5] < 0x0132)) {Uart0_send_buff[0] = Com0_id;Uart0_send_buff[1] = 0x03;Uart0_send_buff[2] = 2 * Uart0_rev_buff[5];Uart0_send_counter = 2 * Uart0_rev_buff[5] + 3;switch(tempdress){case 0x0120:{Uart0_send_buff = Mkgz_bz & 0xff;i++;Uart0_send_buff = (Mkgz_bz >> 8) & 0xff;i++;}//后⾯不放break的⽬的是继续往下执⾏case 0x0122:{Uart0_send_buff = Out_voltage & 0xff;i++;Uart0_send_buff = (Out_voltage >> 8) & 0xff;i++;}case 0x0124:{Uart0_send_buff = Out_current & 0xff;i++;Uart0_send_buff = (Out_current >> 8) & 0xff;i++;}case 0x0126:{Uart0_send_buff = Mkzt_bz & 0xff;i++;Uart0_send_buff = (Mkzt_bz >> 8) & 0xff;i++;}case 0x0128://这个地址是备⽤的⾥⾯的数据没有意义{Uart0_send_buff = 0x00;i++;Uart0_send_buff = 0x00;i++;}case 0x012A:{Uart0_send_buff = OutX_current & 0xff;i++;Uart0_send_buff = (OutX_current >> 8) & 0xff;i++;}case 0x012C:{Uart0_send_buff = Jc_voltage & 0xff;i++;Uart0_send_buff = (Jc_voltage >> 8) & 0xff;i++;}case 0x012E:{Uart0_send_buff = Fc_voltage & 0xff;i++;Uart0_send_buff = (Fc_voltage >> 8) & 0xff;i++;}case 0x0130:{Uart0_send_buff = 0x00;i++;Uart0_send_buff = 0x00;i++;}}//UCSRB |= (1<<TXCIE)|(1<<TXEN);//发送、发送中断允许crcresult = getCRC16(Uart0_send_buff,Uart0_send_counter);Uart0_send_buff[Uart0_send_counter] = crcresult & 0xff;Uart0_send_buff[Uart0_send_counter+1] = (crcresult >> 8) & 0xff;Uart0_send_counter = Uart0_send_counter+2;Uart0_send_pointer = Uart0_send_buff;USART_SendData(USART1, *Uart0_send_pointer++);USART_ITConfig(USART1, USART_IT_TXE, ENABLE); }}/////////////////////////////////////////////////////////////void Modbus_Function_6(void){u16 tempdress = 0;u8 tx_flat = 0;u16 crcresult;tempdress = (Uart0_rev_buff[2]<<8) + Uart0_rev_buff[3];switch(tempdress){case 0x0126:Mkzt_bz = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5];if(user_day > 0){tx_flat = 1;}}break;case 0x012A:{OutX_current = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5];if(user_day > 0){tx_flat = 1;}}break;case 0x012C:{Jc_voltage = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5];if(user_day > 0){tx_flat = 1;}}break;case 0x012E:{Fc_voltage = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5];if(user_day > 0){tx_flat = 1;}}break;case 0x01EE:{user_day = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5];tx_flat = 1;//eeprom_write_word (&user_day_eep,user_day);}break;default: //命令码⽆效不应答{tx_flat = 0;}}if(tx_flat == 1){Uart0_send_buff[0] = Com0_id;Uart0_send_buff[1] = 0x06;Uart0_send_buff[2] = Uart0_rev_buff[2];Uart0_send_buff[3] = Uart0_rev_buff[3];Uart0_send_buff[4] = Uart0_rev_buff[4];Uart0_send_buff[5] = Uart0_rev_buff[5];Uart0_send_counter = 6;//UCSRB |= (1<<TXCIE)|(1<<TXEN);//发送、发送中断允许crcresult = getCRC16(Uart0_send_buff,Uart0_send_counter);Uart0_send_buff[Uart0_send_counter] = crcresult & 0xff;Uart0_send_buff[Uart0_send_counter+1] = (crcresult >> 8) & 0xff;Uart0_send_counter = Uart0_send_counter+2;Uart0_send_pointer = Uart0_send_buff;USART_SendData(USART1, *Uart0_send_pointer++);USART_ITConfig(USART1, USART_IT_TXE, ENABLE); }}/////////////////////////////////////////////////////////////void Com0_Communication(void){s8 i =0;if(Uart0_rev_comflag == 1)//接收完成标志=1处理,否则退出{if(Uart0_rev_buff[0] == Com0_id)//地址错误不应答unsigned short crcresult;unsigned char temp[2];crcresult = getCRC16(Uart0_rev_buff,Crc_counter-2);temp[1] = crcresult & 0xff;temp[0] = (crcresult >> 8) & 0xff;if((Uart0_rev_buff[Crc_counter-1] == temp[0])&&(Uart0_rev_buff[Crc_counter-2] == temp[1]))//crc校验错误不应答 {//SETBIT(PORTC,PC6);Delay(1);switch(Uart0_rev_buff[1]){case 0x03:{if(user_day > 0){Modbus_Function_3();}}break;case 0x06:{Modbus_Function_6();}break;}}}Uart0_rev_comflag = 0;for(i = 100;i > -1;i--){Uart0_rev_buff = 0;}}}/******************************************************************************** Function Name : Delay* Description : Inserts a delay time.* Input : nCount: specifies the delay time length.* Output : None* Return : None*******************************************************************************/void Delay(vu32 nCount){for(; nCount != 0; nCount--);}标签:。
stm32modbusrtu代码
![stm32modbusrtu代码](https://img.taocdn.com/s3/m/f6dc6f3c26284b73f242336c1eb91a37f0113267.png)
stm32modbusrtu代码1. 背景介绍Modbus是一种在工业自动化领域广泛使用的通信协议,而RTU (Remote Terminal Unit)则是Modbus协议的一种常见实现方式。
而STM32则是一系列基于ARM Cortex-M内核的微控制器,在工业领域中也得到了广泛的应用。
本文将深入探讨STM32的Modbus RTU代码实现。
2. STM32与Modbus RTU的集成在开始编写STM32的Modbus RTU代码之前,首先需要了解Modbus RTU协议的通信方式和数据格式。
Modbus RTU采用串口通信,通信速率一般为9600bps或更高。
在STM32上使用串口接口进行通信是比较常见的做法,因此我们可以利用STM32的串口模块实现与Modbus RTU的集成。
3. STM32 Modbus RTU代码实现之串口初始化在开始编写Modbus RTU代码之前,首先需要初始化STM32的串口模块。
在使用串口进行Modbus RTU通信时,需要注意设置合适的波特率、数据位、停止位和校验位等参数。
这些参数需要根据具体情况进行配置,以确保与Modbus RTU设备之间的正常通信。
4. STM32 Modbus RTU代码实现之数据解析在收到Modbus RTU设备发送的数据后,我们需要进行数据解析。
Modbus RTU的数据格式包括功能码、数据起始区域信息、数据长度以及CRC校验等部分。
通过解析这些数据,我们可以理解Modbus RTU设备请求的具体内容,并根据需要进行相应的处理。
5. STM32 Modbus RTU代码实现之数据响应在解析Modbus RTU设备的请求数据后,STM32需要根据请求进行相应的响应。
根据Modbus RTU协议的规定,响应数据包括从站区域信息、功能码、数据长度以及对应的数据内容。
通过构建合适的响应数据包,并使用串口发送给Modbus RTU设备,我们可以实现与Modbus RTU设备的双向通信。
用stm32库函数编写的modbus源代码
![用stm32库函数编写的modbus源代码](https://img.taocdn.com/s3/m/80463ed602d276a200292ec9.png)
用stm32库函数编写的modbus源代码说在前面的话:1.请勿盲目抄袭。
这个协议使用了一个定时器,所以在别处请不要再使用,如果定时器不够用,可以做虚拟定时器。
也就是采用一个物理的定时器产生时基。
在这个定时器的中断函数中可以给相应的多个定时器自加1.每个虚拟定时器可以用两个变量分别控制打开关闭,和计时。
这个已经试验通过了可行的。
其实就跟我们使用物理的定时器一样,只不过物理的定时器是用晶振产生时基。
2.这段代码已经调试通过了,也硬件试验过,没有问题,如果你出现问题了,看看你在主函数的的各种基本配置有没有完成。
如果要使用06和10号功能,你还需要在主函数中建立一个100个元素的数组,每个元素是16位。
3.写这个文档的时候,这个协议已经是半年前完成的了。
所以有些东西记得不是很清楚了,如果说错了,请以实际为准。
只是不想让这份代码死在电脑中了,所以才想起来要拿出来分享,支持开源精神。
4.如果实在实在是没有弄出来,请联系我,可以共同交流,我的邮箱:#include"stm32f10x.h"/* 此Modbus协议暂时只支持RTU模式,只支持作为Modbus从设备。
暂时支持的功能码(16进制)如下表所示:01.读线圈状态(读多个输出位的状态,有效地位为0-31)02.读输入位状态(读多个输入位的状态,有效地位为0-31)03.读保持寄存器(读多个保持寄存器的数值,有效地位为0-99)04.读输入寄存器(读多个输入寄存器的数值,有效地址为0-1)05.强制单个线圈(强制单个输出位的状态,有效地位为0-31)06.预制单个寄存器(设定一个寄存器的数值,有效地址为0-99)0F.强制多个线圈(强制多个输出位的状态,有效地址为0-31)10.预制多个寄存器(设定多个寄存器的数值,有效地址为0-99)暂时支持的错误代码为:01 不合法功能代码从机接收的是一种不能执行功能代码。
发出查询命令后,该代码指示无程序功能。
STM32 modbus程序
![STM32 modbus程序](https://img.taocdn.com/s3/m/b0cff562a98271fe910ef9d5.png)
i++; } case 0x012E: { Uart0_send_buff[i] = Fc_voltage & 0xff;
i++; Uart0_send_buff[i] = (Fc_voltage >> 8) & 0xff;
vu16 Mkgz_bz = 0;//模块故障标志1:输入异常,2:过压,3:欠压,4:过温 vu16 Out_current = 50;//输出电流 vu16 Out_voltage = 240;//输出电压 vu16 Mkzt_bz = 0;//模块状态标志 vu16 OutX_current = 1000;//输出限流 vu16 Jc_voltage = 2530;//均充电压 vu16 Fc_voltage = 2400;//浮充电压 vu16 user_day = 1825;//使用天数
len = 1; } while(len--)
Page 1
modbus.c
{ crc ^= *ptr; for(i=0; i<8; i++) { if(crc&1) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } ptr++;
} return(crc); }
modbus.c
/***************************************************** modbus-rtu 通讯规约
通讯方式:rs-485 半双功 校验方式:crc16 停止位:2位
STM32F的232口简易MODBUS-RTU通讯程序
![STM32F的232口简易MODBUS-RTU通讯程序](https://img.taocdn.com/s3/m/f1205923192e45361066f50c.png)
USART_SendData(USART1, *Uart0_send_pointer++); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } } ///////////////////////////////////////////////////////////// void Modbus_Function_6(void) { u16 tempdress = 0; u8 tx_flat = 0; u16 crcresult; tempdress = (Uart0_rev_buff[2]<<8) + Uart0_rev_buff[3]; switch(tempdress) { case 0x0126: { Mkzt_bz = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5]; if(user_day > 0) { tx_flat = 1; } }break; case 0x012A: { OutX_current = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5]; if(user_day > 0) { tx_flat = 1; } }break; case 0x012C: { Jc_voltage = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5]; if(user_day > 0) { tx_flat = 1; } }break; case 0x012E: { Fc_voltage = (Uart0_rev_buff[4]<<8) + Uart0_rev_buff[5]; if(user_day > 0) { tx_flat = 1; } }break;
modbus uart stm32f4代码例程
![modbus uart stm32f4代码例程](https://img.taocdn.com/s3/m/3d5629c770fe910ef12d2af90242a8956becaad5.png)
Modbus UART是一种串行通信协议,常用于工业控制领域。
在STM32F4系列微控制器上实现Modbus UART通信需要编写相应的代码例程。
下面将介绍在STM32F4微控制器上实现Modbus UART 通信的代码例程。
【正文】1. 硬件准备在开始编写Modbus UART代码例程之前,首先需要准备好相应的硬件设备,包括STM32F4系列微控制器、RS485转UART模块以及其他外围设备。
2. 配置UART首先需要对STM32F4微控制器上的UART进行配置,包括波特率、数据位、停止位和校验位等参数的设置。
具体的配置方法可以参考STM32F4系列微控制器的冠方手册或者相关的参考资料。
3. 实现Modbus协议在配置好UART之后,需要编写代码实现Modbus协议。
Modbus 协议是一种用于工业领域的通信协议,包括功能码、数据帧格式等内容。
在STM32F4微控制器上实现Modbus协议需要编写相关的代码来实现功能码处理、数据帧解析等功能。
4. 连接RS485模块将RS485转UART模块连接到STM32F4微控制器的UART接口,同时连接其他外围设备。
在连接时需要注意引脚的连接方式以及电气特性的匹配。
5. 编写测试程序编写一个简单的测试程序来验证Modbus UART通信是否正常工作。
测试程序可以包括向外围设备发送数据并等待其响应,然后对响应数据进行解析和处理。
6. 调试和优化在验证测试程序正常工作之后,需要进行调试和优化。
在调试过程中可能会出现通信不稳定、数据解析错误等问题,需要通过调试工具和技术对问题进行定位和解决。
7. 发布和应用完成Modbus UART通信代码例程的编写和调试之后,可以将其发布到相应的评台上供其他开发者使用。
同时可以将其应用于实际的工业控制系统中,实现工业设备之间的数据交换和通信。
总结本文介绍了在STM32F4微控制器上实现Modbus UART通信的代码例程,包括硬件准备、UART配置、Modbus协议实现、连接RS485模块、编写测试程序、调试和优化以及发布和应用等内容。
cubeide modbus示例
![cubeide modbus示例](https://img.taocdn.com/s3/m/e379ba886037ee06eff9aef8941ea76e58fa4a95.png)
cubeide modbus示例英文回答:Modbus Example for CubeIDE.Modbus is a widely used industrial communication protocol that allows devices to exchange data over serial or Ethernet networks. CubeIDE provides a powerful development environment for creating Modbus applications on STM32 microcontrollers.Creating a Modbus Project.1. Open CubeIDE and create a new project.2. Select the STM32 microcontroller you are using.3. Go to the "Middleware" tab and enable the "Modbus" component.4. Configure the Modbus settings (e.g., slave address, baud rate, etc.).Adding Modbus Functionality.Once the Modbus component is enabled, you can add Modbus functionality to your application by addingfunctions to the main loop. For example:c.while (1) {。
// Read data from Modbus slave device.uint16_t data =modbus_read_input_register(slave_address, register_address);// Process data and update device state.// Write data to Modbus slave device.modbus_write_single_register(slave_address,register_address, data);}。
modbus报文解析实例
![modbus报文解析实例](https://img.taocdn.com/s3/m/8107fb28f08583d049649b6648d7c1c708a10b38.png)
Modbus 报文解析实例:基于 STM32+485 的实现
一、Modbus 协议概述
Modbus 是一种常用的工业控制协议,主要用于自动化控制、数据采集等领域。
Modbus 协议采用主从结构,由主站控制通信,子站只能响应主站的查询请求。
Modbus 协议采用报文通信,报文包括功能码、数据地址、数据长度、校验码等字段。
Modbus 协议的传输介质可以是串口、以太网、485 总线等。
二、STM32+485 实现 Modbus 协议
STM32 是一种常用的微控制器,具有高性能、低功耗、多功能、易扩展等优点。
本文以 STM32+485 为例,详细解析了 Modbus 协议的实现过程。
1.硬件设计
硬件设计主要包括 STM32 单片机、485 总线、收发器、电源等组成部分。
其中,STM32 单片机通过 485 总线与收发器相连,收发器再将信号转换成数字信号,并通过总线传输到其他设备。
2.软件设计
软件设计主要包括串口通信、Modbus 协议解析、485 总线控制等组成部分。
其中,串口通信用于实现单片机与收发器之间的数据传输;Modbus 协议解析用于解析接收到的报文,并进行数据解析和处理;485 总线控制用于控制收发器的传输状态,确保通信的顺利进行。
三、总结
在物联网和互联网的时代,不懂 Modbus 如何玩转物联网?本文
介绍了 Modbus 报文的基本结构和实现方式,并以 STM32+485 为例,详细解析了 Modbus 协议的实现过程。
通过本文,读者可以深入了解Modbus 协议的实现方式,为物联网的开发打下坚实的基础。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用stm32库函数编写的modbus源代码说在前面的话:1.请勿盲目抄袭。
这个协议使用了一个定时器,所以在别处请不要再使用,如果定时器不够用,可以做虚拟定时器。
也就是采用一个物理的定时器产生时基。
在这个定时器的中断函数中可以给相应的多个定时器自加1.每个虚拟定时器可以用两个变量分别控制打开关闭,和计时。
这个已经试验通过了可行的。
其实就跟我们使用物理的定时器一样,只不过物理的定时器是用晶振产生时基。
2.这段代码已经调试通过了,也硬件试验过,没有问题,如果你出现问题了,看看你在主函数的的各种基本配置有没有完成。
如果要使用06和10号功能,你还需要在主函数中建立一个100个元素的数组,每个元素是16位。
3.写这个文档的时候,这个协议已经是半年前完成的了。
所以有些东西记得不是很清楚了,如果说错了,请以实际为准。
只是不想让这份代码死在电脑中了,所以才想起来要拿出来分享,支持开源精神。
4.如果实在实在是没有弄出来,请联系我,可以共同交流,我的邮箱:***********************#include"stm32f10x.h"/* 此Modbus协议暂时只支持RTU模式,只支持作为Modbus从设备。
暂时支持的功能码(16进制)如下表所示:01.读线圈状态(读多个输出位的状态,有效地位为0-31)02.读输入位状态(读多个输入位的状态,有效地位为0-31)03.读保持寄存器(读多个保持寄存器的数值,有效地位为0-99)04.读输入寄存器(读多个输入寄存器的数值,有效地址为0-1)05.强制单个线圈(强制单个输出位的状态,有效地位为0-31)06.预制单个寄存器(设定一个寄存器的数值,有效地址为0-99)0F.强制多个线圈(强制多个输出位的状态,有效地址为0-31)10.预制多个寄存器(设定多个寄存器的数值,有效地址为0-99)暂时支持的错误代码为:01 不合法功能代码从机接收的是一种不能执行功能代码。
发出查询命令后,该代码指示无程序功能。
(不支持的功能代码)02 不合法数据地址接收的数据地址,是从机不允许的地址。
(起始地址不在有效范围内)03 不合法数据查询数据区的值是从机不允许的值。
(在起始地址的基础上,这个数量是不合法的)供用户调用的函数有:1.void ModInit(u8 Id);//用于Modbus初始化,在函数调用前,必须初始化函数,用于Main函数中2.void ModRcv(void);//用于modbus信息接收,放在串口接收中断3.void ModSend(void);//用于modbus信息接收,放在串口发送中断例如:void USART1_IRQHandler(void) //USART1中断{if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){void ModRcv(void);………………}if(USART_GetITStatus(USART1,USART_IT_TC)!=RESET){void ModSend(void);//用于modbus信息接收………………}}*///modbus用通讯参数u8 Tim_Out;//大于3.5个字符时间,保守取3ms (波特率9600的时候大约2点几毫秒)u8 Rcv_Complete;//一帧是否已经接受完成u8 Send_Complete;//一帧是否已经发送完成u8 Com_busy;//通讯繁忙,表示上一帧还未处理结束u8 Rcv_Buffer[210];//用来存放接收到的完整的一帧数据(第一个字节用来存放接收到的有效字节数,也就是数组中的有效字节数)u8 Send_Buffer[210];//用来存放待发送的完整的一帧数据(第一个字节用来存放待发送的有效字节数,也就是数组中的有效字节数)u8 Rcv_Data;//用来存放接收的一个字节u8 Send_Data;//用来存放要发送的一字节u8 Mod_Id;//用来标志作为从站的站号u8 Rcv_Num;//用来表示接收的一帧的有效字节数(从功能码到CRC校验)u8 Send_Num;//用来表示待发送的一帧的字节数u8 *PointToRcvBuf;//用来指向接收的数据缓存u8 *PointToSendBuf;//用来指向带发送的数据缓存u8 Comu_Busy;//用来表示能否接收下一帧数据u8 HaveMes;extern u16 HoldReg[100];//CRC校验查表用参数/* CRC 高位字节值表*/static u8 auchCRCHi[] = {0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40} ;/* CRC低位字节值表*/static u8 auchCRCLo[] = {0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06, 0x07,0xC7,0x05,0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD, 0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09, 0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A, 0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,0x14,0xD4, 0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3, 0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3, 0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4, 0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A, 0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29, 0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40} ;//声明modbus的函数void ModInit(u8 Id);//用于Modbus初始化,参数Id为站号(1-255)void ModRcv(void);//用于modbus信息接收void ModSend(void);//用于modbus信息接收void MessageHandle(u8 *pointer_in,u8 *pointer_out);//处理收到的信息帧void ReadOutputBit(u8 *pointer_1,u8 *pointer_2);//读线圈void ReadInputBit(u8 *pointer_1,u8 *pointer_2);//读输入位void ReadHoldingReg(u8 *pointer_1,u8 *pointer_2);//读保持寄存器void ReadInputReg(u8 *pointer_1,u8 *pointer_2);//读输入寄存器void ForceSingleCoil(u8 *pointer_1,u8 *pointer_2);//强制单个线圈void PresetSingleReg(u8 *pointer_1,u8 *pointer_2);//预制单个寄存器void ForceMulCoil(u8 *pointer_1,u8 *pointer_2);//强制多个线圈。