Modbus通讯协议的C语言实现
刚写完一个modbus通讯协议,调试完,整理出来了,软件代码只能为大家提供一个思路,仅供参考。
//communication.h
#include "H01_Global\_Define.h"
#include "H01_Global\base_types.h"#define SIZE_BUF_RECE 100
#define SIZE_BUF_TRAN 100#define TRANS_TIMER_DELAY_1MS 1
#define TRANS_TIMER_DELAY_10MS 10
#define TRANS_TIMER_DELAY_100MS 100
#define TRANS_TIMER_DELAY_1S 1000typedef union
{uint16_t word;struct {uint8_t low;uint8_t high;}byte;struct{uint8_t bit0:1;uint8_t bit1:1;uint8_t bit2:1;uint8_t bit3:1;uint8_t bit4:1;uint8_t bit5:1;uint8_t bit6:1;uint8_t bit7:1;uint8_t bit8:1;uint8_t bit9:1;uint8_t bit10:1;uint8_t bit11:1;uint8_t bit12:1;uint8_t bit13:1;uint8_t bit14:1;uint8_t bit15:1;}BIT;
}WORD_BYTE;typedef struct
{uint32_t MODBUS_Reg_Set_Speed;uint32_t MODBUS_Reg_Set_Enable_VSP;uint32_t MODBUS_Reg_Set_Dir;uint32_t MODBUS_Reg_Force_Stop;
}MODBUS_HOLDING_REGISTORS;typedef struct
{uint32_t MODBUS_Reg_Get_Motor_Type;uint32_t MODBUS_Reg_Get_Software_Version;uint32_t MODBUS_Reg_Get_Running_Status;uint32_t MODBUS_Reg_Get_Running_Speed;uint32_t MODBUS_Reg_Get_Phase_Current;uint32_t MODBUS_Reg_Get_IPM_Temperature;uint32_t MODBUS_Reg_Get_DC_Voltage;uint32_t MODBUS_Reg_Get_Running_Dir;uint32_t MODBUS_Reg_Get_Errors;
}MODBUS_INPUT_REGISTORS;typedef struct
{uint32_t dev_comm;uint32_t delay_tran;uint32_t Function_Code;uint32_t flag_state;uint32_t addr_dev;uint32_t pt_tran;uint32_t pt_rece;uint32_t len_tran;uint32_t len_rece;uint32_t xorsum_rece;uint32_t addsum_rece;uint32_t xorsum_tran;uint32_t addsum_tran;uint32_t flag_trans_start;uint32_t flag_trans_end;uint32_t flag_trans_timer_ON;uint32_t count_trans_timer_1ms;uint32_t count_trans_timer_10ms;uint32_t count_trans_timer_100ms;uint32_t count_trans_timer_1s;WORD_BYTE address_reg;WORD_BYTE num_reg;uint32_t buf_rece[SIZE_BUF_RECE];uint32_t buf_tran[SIZE_BUF_TRAN];MODBUS_HOLDING_REGISTORS Modbus_Holding_Reg ;MODBUS_INPUT_REGISTORS Modbus_Input_Reg;
}MODBUS_COMM;extern void Uart_Trans(void);
extern void Uart_Receive(void);
extern void Init_Modbus(void);
extern void Timer_Task(void);
extern void Proc_Modbus_Data(void);
extern uint32_t Read_Reg_Modbus(MODBUS_COMM *modbus);
void Set_Reg_Modbus(MODBUS_COMM *modbus, WORD_BYTE data);
extern void CRC_Rece_Check(void);
extern uint32_t Flag_Trans_End;
extern uint32_t Timer_Count;
extern uint32_t Timer_1s;
// communication.c
#include "H05_User\AllInOne.h"
/*****************************************************************************/
/* Local pre-processor symbols/macros ('#define') */
/*****************************************************************************/
#define MAX_DEV_COMM 4
#define DELAY_SENT 20
/*****************************************************************************/
/* Global variable definitions (declared in header file with 'extern') */
/*****************************************************************************//*****************************************************************************/
/* Local type definitions ('typedef') */
/*****************************************************************************/
typedef enum
{Reg_Set_Speed = 100, //100Reg_Set_Enable_VSP, //101Reg_Set_Dir, //102Reg_Force_Stop
}Modbus_Holding_Registors;typedef enum
{Reg_Get_Motor_Type = 200, //200Reg_Get_Software_Version, //201Reg_Get_Running_Status, //202Reg_Get_Running_Speed, //203Reg_Get_Phase_Current, //204Reg_Get_IPM_Temperature, //205Reg_Get_DC_Voltage, //206Reg_Get_Running_Dir, //207Reg_Get_Errors //208
}Modbus_Input_Registors;enum
{MODBUS_State_Idle = 0,MODBUS_State_Receive,MODBUS_State_Transmit
};
/*****************************************************************************/
/* Local variable definitions ('static') */
/*****************************************************************************/
uint32_t Timer_Count;
uint32_t Timer_1s;
uint32_t Flag_Trans_End;
extern uint32_t Software_Version;
extern MODBUS_COMM modbus_comm;
extern MODBUS_COMM *modbus;void Init_Modbus()
{uint32_t temp = 0;modbus = &modbus_comm;modbus->addr_dev = 1;modbus->dev_comm = 0;modbus->delay_tran = 0;modbus->Function_Code = 0;modbus->flag_state = MODBUS_State_Idle;modbus->pt_tran = 0;modbus->pt_rece = 0;modbus->len_tran = 0;modbus->len_rece = 0;modbus->xorsum_rece = 0;modbus->xorsum_tran = 0;modbus->addsum_rece = 0;modbus->addsum_tran = 0;modbus->flag_trans_start = 0;modbus->flag_trans_end = 1;modbus->flag_trans_timer_ON = 0;modbus->count_trans_timer_1ms = 0;modbus->count_trans_timer_10ms = 0;modbus->count_trans_timer_100ms = 0;modbus->count_trans_timer_1s = 0;modbus->address_reg.word = 0;modbus->num_reg.word = 0;for(temp = 0; temp<SIZE_BUF_RECE; temp++){modbus->buf_rece[temp] = 0;}for(temp=0; temp<SIZE_BUF_TRAN; temp++){modbus->buf_tran[temp] = 0;}modbus->Modbus_Input_Reg.MODBUS_Reg_Get_DC_Voltage = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Errors = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_IPM_Temperature = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Motor_Type = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Phase_Current = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Running_Dir = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Running_Speed = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Running_Status = 0;modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Software_Version = Software_Version;
}void Uart_Trans()
{uint32_t data_trans;if(modbus->flag_trans_start){if(modbus->pt_tran < modbus->len_tran){if(UART_SpiUartGetTxBufferSize() == 0){data_trans = modbus->buf_tran[modbus->pt_tran];UART_UartPutChar(data_trans);modbus->pt_tran++;modbus->flag_trans_end = 0;}}else{modbus->pt_tran = 0;modbus->pt_rece = 0;modbus->flag_trans_start = 0;modbus->flag_trans_end = 1;modbus->flag_state = MODBUS_State_Idle;}}else{modbus->pt_tran = 0;}
}void Uart_Receive()
{uint32_t data_rece;data_rece = UART_UartGetChar();if(modbus->flag_state){modbus->pt_rece = 0;}else{if((modbus->pt_rece)&&(modbus->addr_dev == modbus->buf_rece[0])){if(modbus->dev_comm > MAX_DEV_COMM){modbus->pt_rece = 0;}modbus->buf_rece[modbus->pt_rece] = data_rece;modbus->pt_rece++;if(modbus->pt_rece < 8){if(modbus->pt_rece == 7){if(modbus->buf_rece[1] >= 0x0F){modbus->len_rece = modbus->buf_rece[6]+9;}else{modbus->len_rece = 8;}}}else if(modbus->pt_rece >= modbus->len_rece){modbus->pt_rece = 0;modbus->flag_state = MODBUS_State_Receive;if(modbus->buf_rece[0]){modbus->delay_tran = DELAY_SENT;}}}else{if((modbus->addr_dev == data_rece) || (data_rece == 0)){modbus->buf_rece[0] = data_rece;modbus->pt_rece = 1;}}}modbus->dev_comm = 0;
}void Timer_Task()
{Timer_Count++;if(Timer_Count >= 5000){Timer_Count = 0;Timer_1s++;}if(modbus->flag_trans_timer_ON){modbus->count_trans_timer_100ms++;if(modbus->count_trans_timer_100ms >= TRANS_TIMER_DELAY_100MS){modbus->count_trans_timer_100ms = 0;modbus->flag_trans_timer_ON = 0;modbus->flag_trans_start = 1;}}
}uint32_t Read_Reg_Modbus(MODBUS_COMM *modbus)
{WORD_BYTE dat;uint32_t addr;addr = modbus->address_reg.word;dat.word = 0;if(modbus->Function_Code == 3){switch(addr){case Reg_Set_Speed:dat.word = modbus->Modbus_Holding_Reg.MODBUS_Reg_Set_Speed;break;case Reg_Set_Enable_VSP:dat.word = modbus->Modbus_Holding_Reg.MODBUS_Reg_Set_Enable_VSP;break;case Reg_Set_Dir:dat.word = modbus->Modbus_Holding_Reg.MODBUS_Reg_Set_Dir;break;case Reg_Force_Stop:dat.word = modbus->Modbus_Holding_Reg.MODBUS_Reg_Force_Stop;break;default:break;}}else if(modbus->Function_Code == 4){switch(addr){case Reg_Get_Motor_Type:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Motor_Type;break;case Reg_Get_Software_Version:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Software_Version;break;case Reg_Get_Running_Status:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Running_Status;break;case Reg_Get_Running_Speed:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Running_Speed;break;case Reg_Get_Phase_Current:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Phase_Current;break;case Reg_Get_IPM_Temperature:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_IPM_Temperature;break;case Reg_Get_DC_Voltage:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_DC_Voltage;break;case Reg_Get_Running_Dir:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Running_Dir;break;case Reg_Get_Errors:dat.word = modbus->Modbus_Input_Reg.MODBUS_Reg_Get_Errors;break;default:break;}}else if((modbus->Function_Code == 6)||(modbus->Function_Code == 16)){}return (dat.word);
}void Set_Reg_Modbus(MODBUS_COMM *modbus, WORD_BYTE data)
{if(modbus->Function_Code == 3){}else if(modbus->Function_Code == 4){}else if((modbus->Function_Code == 6)||(modbus->Function_Code == 16)){switch(modbus->address_reg.word){case Reg_Set_Speed:modbus->Modbus_Holding_Reg.MODBUS_Reg_Set_Speed = data.word;break;case Reg_Set_Enable_VSP:modbus->Modbus_Holding_Reg.MODBUS_Reg_Set_Enable_VSP = data.word;break;case Reg_Set_Dir:modbus->Modbus_Holding_Reg.MODBUS_Reg_Set_Dir = data.word;break;case Reg_Force_Stop:modbus->Modbus_Holding_Reg.MODBUS_Reg_Force_Stop = data.word;break;default:break;}}
}void Proc_Modbus_Data()
{uint32_t index_modbus;uint32_t index;WORD_BYTE data;if(modbus->flag_state == MODBUS_State_Receive){modbus->len_tran = 0;if(crc16_str_rece(modbus->buf_rece, modbus->len_rece-2)){modbus->addr_dev = modbus->buf_rece[0];modbus->Function_Code = modbus->buf_rece[1];modbus->buf_tran[0] = modbus->addr_dev;if((modbus->Function_Code&&(modbus->Function_Code<7)) || (modbus->Function_Code == 15) || (modbus->Function_Code == 16)){modbus->address_reg.byte.high = modbus->buf_rece[2];modbus->address_reg.byte.low = modbus->buf_rece[3];modbus->num_reg.byte.high = modbus->buf_rece[4];modbus->num_reg.byte.low = modbus->buf_rece[5];modbus->address_reg.word++;if((modbus->Function_Code == 3)||(modbus->Function_Code==4)||(modbus->Function_Code==6)||(modbus->Function_Code==16)){if((modbus->Function_Code==3)||(modbus->Function_Code==4)){modbus->buf_tran[1] = modbus->Function_Code;modbus->buf_tran[2] = (modbus->num_reg.byte.low<<1);modbus->len_tran = modbus->buf_tran[2] + 5;index_modbus = 3;for(index=0; index<modbus->num_reg.byte.low; index++, modbus->address_reg.word++){data.word = Read_Reg_Modbus(modbus);modbus->buf_tran[index_modbus++] = data.byte.high;modbus->buf_tran[index_modbus++] = data.byte.low;}}else if(modbus->Function_Code == 6){for(index=1; index<6; index++){modbus->buf_tran[index] = modbus->buf_rece[index];}modbus->len_tran = 8;data.byte.high = modbus->buf_rece[4];data.byte.low = modbus->buf_rece[5];Set_Reg_Modbus(modbus, data);}else{for(index=1; index<6; index++){modbus->buf_tran[index] = modbus->buf_rece[index];}modbus->len_tran = 8;index_modbus = 7;for(index=0; index<modbus->num_reg.byte.low; index++, modbus->address_reg.word++){data.byte.high = modbus->buf_rece[index_modbus++];data.byte.low = modbus->buf_rece[index_modbus++];Set_Reg_Modbus(modbus, data);}}}}if(modbus->len_tran){crc16_str_sent(modbus->buf_tran, (modbus->len_tran - 2));modbus->flag_state = MODBUS_State_Transmit;modbus->flag_trans_timer_ON = 1;modbus->count_trans_timer_100ms = 0;}else{modbus->flag_state = MODBUS_State_Idle;}}else{modbus->flag_state = MODBUS_State_Idle;}}
}
另外针对CRC校验的代码实现,请移步我的另一篇博客:
链接: CRC校验查表法原理及实现(CRC-16).
以上的代码仅仅是一demo例程,面向电机控制系统的modbus通讯协议,所以在定义寄存器的时候会定义电机运行期间的变量,仅供参考,不要来问我为什么移植到某平台上运行不了这样的问题,这仅仅是项目软件的很小的一个部分,仅提供思路而已。
Modbus通讯协议的C语言实现相关推荐
- Modbus通讯协议
https://baike.baidu.com/item/Modbus%E9%80%9A%E8%AE%AF%E5%8D%8F%E8%AE%AE/5972462?fromtitle=ModBus& ...
- 杭州金田电磁转换器MODBUS通讯协议
杭州金田电磁转换器MODBUS通讯协议 通讯协议采用标准MODBUS RTU通讯协议.仪表为从机. RTU消息帧定义 数据通讯由主机发起,主机首先发送RTU消息帧,消息帧发送至少要以3.5个字符时间的 ...
- MODBUS通讯协议及编程【一】
一.Modbus 协议简介 Modbus 协议是应用于电子控制器上的一种通用语言.通过此协议,控制器相互之间.控制器经由网络(例如以太网)和其它设备之间可以通信.它已经成为一通用工业标准.有了它, ...
- Modbus 通讯协议
Modbus 通讯协议 摘要 工业控制已从单机控制走向集中监控.集散控制,如今已进入网络时代,工业控制器连网也为网络管理提供了方便.Modbus就是工业控制器的网络协议中的一种. 关键词 Modbus ...
- STM32移植modbus通讯协议简明教程
目录 一.本文讨论内容 二.工具与源码 三.Modbus概述 四.Modbus-RTU通讯协议 五.完成Modbus输入输出代码 六.完成Modbus逻辑功能 七.测试与验证 一.本文讨论内容 本文简 ...
- 基于modbus协议的工业自动化网络规范_工控学堂:解读Modbus通讯协议「宜收藏」...
作为工控人,Modbus通讯协议想必都不陌生,Modbus通讯协议可以说是工业自动化领域应用最为广泛的通讯协议,因为他的开放性.可扩充性和标准化使他成为通用工业标准. 1979年施耐德电气制定了一个用 ...
- 一文搞懂物联网Modbus通讯协议
简介: 一般来说,常见的物联网通讯协议众多,如蓝牙.Zigbee.WiFi.ModBus.PROFINET.EtherCAT.蜂窝等.而在众多的物联网通讯协议中,Modbus是当前非常流行的一种通讯协 ...
- 协议:Modbus通讯协议详细
1.Modbus通讯协议详细解释 https://blog.csdn.net/rxiang12/article/details/79125813 2.Modbus通信协议详解 https://blog ...
- modbus通讯协议详解
1.Modbus协议简介 Modbus协议是一种广泛应用于当今工业控制领域的通用通信协议.通过此协议,控制器相互之间.或者控制器经由网路(如以太网)可以和其他设备之间进行通信.Modbus协议使用的是 ...
最新文章
- 好程序员Web前端教程分享Vue学习心得
- MyBatis-学习笔记10【10.JNDI扩展知识】
- centos7 tomcat_centos7中利用logrotate工具切割日志,以tomcat日志为例
- 2017 Multi-University Training Contest - Team 2——HDU6045HDU6047HDU6055
- 创建线程都有哪些方式?— Callable篇
- 从放牛娃到北大博士,这篇论文后记刷屏
- Dubbo 面试题汇总(附答案)
- iphone查看删除的短信_苹果删除的短信
- Kali Linux Web 渗透测试秘籍 第九章 客户端攻击和社会工程
- 小米 11 不送充电器;苹果已修复 iCloud 登录激活问题;Ruby 3.0.0 发布|极客头条...
- yum提示Another app is currently holding the yum lock
- 两分钟,帮你搞懂光纤接头
- 【Excel】两组行数不同数据做二维柱状图
- Clonezilla SE---克隆linux------转载
- 计算机基础及msoffice应用内容,计算机一级计算机基础及 ms office 应用考些什么 自考计算机应用基础,要考哪些内容?...
- c语言 表盘指针旋转,请教下,表盘指针图片旋转 ??
- 止咳绝招 献给身边咳嗽的人
- 你从哪里来你是谁你到哪里去_你到底在哪里?
- 高边坡监测主要监测的内容
- GuestOS? HostOS?