444 lines
16 KiB
C
444 lines
16 KiB
C
#ifndef _ECBM_MODBUS_H_
|
||
#define _ECBM_MODBUS_H_
|
||
/*-------------------------------------------------------------------------------------
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2023 奈特
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||
this software and associated documentation files (the "Software"), to deal in
|
||
the Software without restriction, including without limitation the rights to
|
||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||
subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
免责说明:
|
||
本软件库以MIT开源协议免费向大众提供。作者只保证原始版本是由作者在维护修BUG,
|
||
其他通过网络传播的版本也许被二次修改过,由此出现的BUG与作者无关。而当您使用原始
|
||
版本出现BUG时,请联系作者解决。
|
||
**************************
|
||
* 联系方式:进群778916610 *
|
||
* 若1群满人:进群927297508*
|
||
**************************
|
||
------------------------------------------------------------------------------------*/
|
||
//-----------------以下是图形设置界面,可在Configuration Wizard界面设置-----------------
|
||
//<<< Use Configuration Wizard in Context Menu >>>
|
||
//<q>使能IO控制读写功能?
|
||
//<i>使能后需要自己定义实现接口函数,函数内部放控制IO的语句,IO电平由形参传入
|
||
//<i>当modbus需要控制IO的时候会调用这个接口函数
|
||
//<i>void ecbm_modbus_rtu_set_io(emu8 dat)
|
||
//<i>{
|
||
//<i> gpio_out_fast(GPIO_P5, GPIO_PIN_5, dat);
|
||
//<i> //gpio_out(RS485_ENA,dat);
|
||
//<i>}
|
||
#define ECBM_MODBUS_IO_EN 0
|
||
//<h>MODBUS_RTU
|
||
#define ECBM_MODBUS_VERSION "V1.0.4"
|
||
//<i>这是modbus协议的RTU模式。
|
||
//<o>本机地址/ID
|
||
//<1-247>
|
||
//<i>8位的地址,可使用的范围是1~247,0作为广播地址。
|
||
#define ECBM_MODBUS_RTU_ID_ADRESS 1
|
||
//<o>超时时间
|
||
//<i>单位为定时器中断次数。比如500就是定时器中断500次,若每次中断的间隔是1ms,那么就是500mS超时。
|
||
#define ECBM_MODBUS_RTU_TIME_MAX 5
|
||
//<h>线圈读写功能设置
|
||
//<e>线圈缓存
|
||
//<i>勾选后会定义一个数组作为缓存,线圈指令操作都会指向这个数组,适合新项目的开始。可以使用读写函数获取数组内部的值。
|
||
//<i>不勾选的话,可以通过移植两个读写函数将读写线圈功能映射到任意的地方。适合为老项目增加modbus功能。
|
||
#define ECBM_MODBUS_RTU_BIT_BUF_EN 0
|
||
//<o>线圈起始地址
|
||
//<i>有时候为了适配别人的协议,地址不一定是从0开始的,在这里可以设置一个偏移。
|
||
#define ECBM_MODBUS_RTU_BIT_START_ADDR 0
|
||
//<o>线圈缓存总数
|
||
//<i>单位是字节(8位),请根据需求填写。比如设备要有10个线圈,因为至少需要两个字节才能存完10个,那么就应该填2。
|
||
#define ECBM_MODBUS_RTU_BIT_BUF_SIZE 3
|
||
//</e>
|
||
//<h>线圈指令使能
|
||
//<i>如果和线圈有关的指令都没有被使能,那么线圈读写相关的函数和缓存都将被优化掉。
|
||
//<q>[01]读线圈
|
||
#define ECBM_MODBUS_RTU_CMD01_EN 1
|
||
//<q>[05]写单个线圈
|
||
#define ECBM_MODBUS_RTU_CMD05_EN 1
|
||
//</h>
|
||
//</h>
|
||
//<h>寄存器读写功能设置
|
||
//<e>寄存器缓存
|
||
#define ECBM_MODBUS_RTU_REG_BUF_EN 0
|
||
//<o>寄存器起始地址
|
||
//<i>有时候为了适配别人的协议,地址不一定是从0开始的,在这里可以设置一个偏移。
|
||
#define ECBM_MODBUS_RTU_REG_START_ADDR 0
|
||
//<o>寄存器缓存总数
|
||
//<i>单位是字(16位),请根据需求填写。
|
||
#define ECBM_MODBUS_RTU_REG_BUF_SIZE 40
|
||
//</e>
|
||
//<h>寄存器指令使能
|
||
//<i>如果和寄存器有关的指令都没有被使能,那么线圈读写相关的函数和缓存都将被优化掉。
|
||
//<q>[03]读寄存器
|
||
#define ECBM_MODBUS_RTU_CMD03_EN 1
|
||
//<q>[06]写单个寄存器
|
||
#define ECBM_MODBUS_RTU_CMD06_EN 1
|
||
//<e>[10]写多个寄存器
|
||
#define ECBM_MODBUS_RTU_CMD10_EN 1
|
||
//<o>寄存器写入缓存总数
|
||
//<i>单位是字节(8位),由于CRC的存在,在多字节写入的时候,不能立刻把数据存入,需要用一个缓存存起来,待CRC验证完毕之后才能一起写入。
|
||
#define ECBM_MODBUS_RTU_BUF_SIZE 10
|
||
//</e>
|
||
//</h>
|
||
//</h>
|
||
//<h>IO系统指令使能
|
||
//<i>如果和IO系统有关的指令都没有被使能,那么IO相关的函数和缓存都将被优化掉。
|
||
//<q>[02]读离散量输入
|
||
#define ECBM_MODBUS_RTU_CMD02_EN 1
|
||
//<q>[04]读输入寄存器
|
||
#define ECBM_MODBUS_RTU_CMD04_EN 1
|
||
//</h>
|
||
#define ECBM_MODBUS_RTU_CMD_BIT_EN (ECBM_MODBUS_RTU_CMD01_EN+ECBM_MODBUS_RTU_CMD05_EN)
|
||
#define ECBM_MODBUS_RTU_CMD_REG_EN (ECBM_MODBUS_RTU_CMD03_EN+ECBM_MODBUS_RTU_CMD06_EN+ECBM_MODBUS_RTU_CMD10_EN)
|
||
#define ECBM_MODBUS_RTU_CMD_IO_EN (ECBM_MODBUS_RTU_CMD02_EN+ECBM_MODBUS_RTU_CMD04_EN)
|
||
#define ECBM_MODBUS_RTU_CMD_ALL_EN (ECBM_MODBUS_RTU_CMD_BIT_EN+ECBM_MODBUS_RTU_CMD_REG_EN+ECBM_MODBUS_RTU_CMD_IO_EN)
|
||
//<<< end of configuration section >>>
|
||
//-----------------以上是图形设置界面,可在Configuration Wizard界面设置-----------------
|
||
/*-----------------------------------数据类型宏定义--------------------------------*/
|
||
#define fast_type idata //快速内存区。
|
||
#define large_type xdata //大容量内存区。
|
||
typedef unsigned char emu8; //8位无符号型变量。
|
||
typedef unsigned short emu16; //16位无符号型变量。
|
||
typedef unsigned long emu32; //32位无符号型变量。
|
||
/*------------------------------------状态机宏定义---------------------------------*/
|
||
#define ECBM_MODBUS_RTU_READY 0 //就绪态,此时可以接受一帧modbus数据。
|
||
#define ECBM_MODBUS_RTU_WAIT 1 //等待态,当发生错误之后,在此等待当前数据帧结束。
|
||
#define ECBM_MODBUS_RTU_ID_ERR 2 //ID错误,当接收到的ID不是本机也不是广播地址时会到这里。
|
||
#define ECBM_MODBUS_RTU_FUN_NUM 3 //读取功能码,在此读取功能码。
|
||
#define ECBM_MODBUS_RTU_FUN_NUM_ERR 4 //功能码错误,功能码原则上小于128,超过就会到这里。
|
||
#define ECBM_MODBUS_RTU_FUN_NUM_VOID 5 //功能码不存在,主要原因是本机不支持该功能码。
|
||
#define ECBM_MODBUS_RTU_ADDRH 6 //读取地址高8位。
|
||
#define ECBM_MODBUS_RTU_ADDRL 7 //读取地址低8位。
|
||
#define ECBM_MODBUS_RTU_DATA_COUNTH 8 //读取数据或者个数的高8位。
|
||
#define ECBM_MODBUS_RTU_DATA_COUNTL 9 //读取数据或者个数的低8位。
|
||
#define ECBM_MODBUS_RTU_COUNT_ERR 10 //读取个数错误。
|
||
#define ECBM_MODBUS_RTU_CRCH 11 //读取CRC的高8位。
|
||
#define ECBM_MODBUS_RTU_CRCL 12 //读取CRC的低8位。
|
||
#define ECBM_MODBUS_RTU_CRC_ERR 13 //CRC错误,当接收到的数据的CRC和传输的CRC不一致时会报错。
|
||
#define ECBM_MODBUS_RTU_DO 14 //处理态,在该状态下处理数据。
|
||
#define ECBM_MODBUS_RTU_DATAH 15 //读取地址高8位。
|
||
#define ECBM_MODBUS_RTU_DATAL 16 //读取地址低8位。
|
||
#define ECBM_MODBUS_RTU_BYTE_COUNT 17 //读取字节数量。
|
||
#define ECBM_MODBUS_RTU_BYTE_ERR 18 //读取字节数量对应不上。
|
||
/*-------------------------------------返回值定义----------------------------------*/
|
||
#define ECBM_MODBUS_RTU_OK 0 //正常。
|
||
#define ECBM_MODBUS_RTU_BIT_ADDR_ERR 1 //比特位地址错误。
|
||
#define ECBM_MODBUS_RTU_REG_ADDR_ERR 2 //寄存器地址错误。
|
||
#define ECBM_MODBUS_RTU_IO_ADDR_ERR 3 //IO地址错误。
|
||
/*-------------------------------220709增加使能脚控制功能----------------------------*/
|
||
#define ECBM_MODBUS_READ 0 //读使能
|
||
#define ECBM_MODBUS_WRITE 1 //写使能
|
||
/*--------------------------------------变量定义-----------------------------------*/
|
||
extern emu16 fast_type ecbm_modbus_rtu_crc; //初始化CRC变量各位为1。
|
||
extern emu8 fast_type ecbm_modbus_rtu_status; //状态机使用的变量。
|
||
extern emu8 fast_type ecbm_modbus_rtu_id; //本机的设备ID。
|
||
extern emu8 fast_type ecbm_modbus_rtu_fun_code; //功能码。
|
||
extern emu8 fast_type ecbm_modbus_rtu_fun_err_num; //异常码。
|
||
extern emu16 fast_type ecbm_modbus_rtu_address; //数据地址。
|
||
extern emu16 fast_type ecbm_modbus_rtu_data_count; //数据/个数。
|
||
extern emu16 fast_type ecbm_modbus_rtu_crc_buf; //CRC缓存。
|
||
extern emu16 fast_type ecbm_modbus_rtu_timeout; //超时计算。
|
||
extern emu16 fast_type ecbm_modbus_rtu_uart_crc; //CRC计算缓存。
|
||
extern emu8 fast_type ecbm_modbus_rtu_cmd_count; //指令缓存计数。
|
||
extern emu8 fast_type ecbm_modbus_rtu_broadcast_en; //广播模式。
|
||
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
extern emu8 large_type ecbm_modbus_rtu_bit_buf[ECBM_MODBUS_RTU_BIT_BUF_SIZE];//比特线圈存放变量。
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
extern emu16 large_type ecbm_modbus_rtu_reg_buf[ECBM_MODBUS_RTU_REG_BUF_SIZE];//寄存器存放变量。
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD10_EN
|
||
extern emu16 large_type ecbm_modbus_rtu_cmd_buf[ECBM_MODBUS_RTU_BUF_SIZE];//指令缓存。
|
||
#endif
|
||
/*--------------------------------------函数定义-----------------------------------*/
|
||
/**
|
||
* @brief 设置485芯片的读写IO脚,220709
|
||
*
|
||
* @param dat 电平状态
|
||
*/
|
||
extern void ecbm_modbus_rtu_set_io(emu8 dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_set_data
|
||
描 述:发送数据函数。需要用户移植。
|
||
输 入:
|
||
dat 要发送的数据
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_set_data(emu8 dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_get_data
|
||
描 述:数据接收函数。需要用户移植。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:接收到的数据。
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern emu8 ecbm_modbus_rtu_get_data(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ECBM_MODBUS_RTU_TIMEOUT_RUN
|
||
描 述:走时宏定义,为了加快运行速度,所以做成了宏定义。需要用户移植。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-10
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
#define ECBM_MODBUS_RTU_TIMEOUT_RUN() \
|
||
do{\
|
||
if(ecbm_modbus_rtu_timeout>0)/*不为0的时候才增加。*/\
|
||
ecbm_modbus_rtu_timeout++;/*时间往上加。*/\
|
||
if(ecbm_modbus_rtu_timeout>ECBM_MODBUS_RTU_TIME_MAX){/*超时的时候,*/\
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_READY;/*回到就绪态。*/\
|
||
ecbm_modbus_rtu_timeout=0;/*同时关闭时间累积。*/\
|
||
}\
|
||
}while(0)
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_crc16
|
||
描 述:CRC16计算函数。
|
||
输 入:
|
||
buf 需要计算CRC的数据
|
||
输 出:
|
||
ecbm_modbus_rtu_crc 计算的结果
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-10
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_crc16(emu8 buf);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_check_fun_num
|
||
描 述:检测功能码函数。
|
||
输 入:
|
||
fun_num 功能码
|
||
输 出:无
|
||
返回值:功能码存在返回本身,不存在返回0x80+功能码。
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern emu8 ecbm_modbus_rtu_check_fun_num(emu8 fun_num);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_cmd_read_io_bit
|
||
描 述:读输入离散量函数。
|
||
输 入:
|
||
addr 离散量地址
|
||
输 出:
|
||
dat 比特值
|
||
返回值:读取结果
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-15
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern emu8 ecbm_modbus_cmd_read_io_bit(emu16 addr,emu8 * dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_cmd_read_io_reg
|
||
描 述:读输入寄存器函数。
|
||
输 入:
|
||
addr 寄存器地址
|
||
输 出:
|
||
dat 寄存器值
|
||
返回值:读取结果
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-15
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern emu8 ecbm_modbus_cmd_read_io_reg(emu16 addr,emu16 * dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_cmd_write_bit
|
||
描 述:写比特数据函数。
|
||
输 入:
|
||
addr 比特位地址
|
||
dat 比特值
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-16:取消返回值,优化运行速度。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_cmd_write_bit(emu16 addr,emu8 dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_cmd_read_bit
|
||
描 述:读比特数据函数。
|
||
输 入:
|
||
addr 比特位地址
|
||
输 出:
|
||
dat 比特值
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-16:取消返回值,优化运行速度。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_cmd_read_bit(emu16 addr,emu8 * dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_cmd_write_reg
|
||
描 述:写寄存器数据函数。
|
||
输 入:
|
||
addr 寄存器地址
|
||
dat 寄存器值
|
||
输 出:无
|
||
返回值:读取结果
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-16:取消返回值,优化运行速度。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_cmd_write_reg(emu16 addr,emu16 dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_cmd_read_reg
|
||
描 述:读寄存器函数。
|
||
输 入:
|
||
addr 寄存器地址
|
||
输 出:
|
||
dat 寄存器值
|
||
返回值:读取结果
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-16:取消返回值,优化运行速度。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_cmd_read_reg(emu16 addr,emu16 * dat);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_cmd_0x01
|
||
描 述:1号功能码处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-09:新增CRC校验。
|
||
2021-03-15:修改了异常码02的触发条件。
|
||
2021-03-16:新增异常码04的触发条件。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_cmd_0x01(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_cmd_0x02
|
||
描 述:2号功能码处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-15
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_cmd_0x02(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_cmd_0x03
|
||
描 述:3号功能码处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-09:新增CRC校验。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_cmd_0x03(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_cmd_0x05
|
||
描 述:5号功能码处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-09:新增CRC校验。
|
||
2021-03-16:新增异常码04的触发条件,优化了部分执行代码。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_cmd_0x05(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_cmd_0x06
|
||
描 述:6号功能码处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-09:新增CRC校验。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_cmd_0x06(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_cmd_0x10
|
||
描 述:16号功能码处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-12
|
||
修改记录:
|
||
-------------------------------------------------------*/
|
||
void ecbm_modbus_rtu_cmd_0x10(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_receive
|
||
描 述:modbus接收处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-09:新增CRC校验。
|
||
2021-03-12:新增0x10指令相关处理,新增0xff广播地址。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_receive(void);
|
||
/*-------------------------------------------------------
|
||
函数名:ecbm_modbus_rtu_run
|
||
描 述:modbus主循环处理函数。
|
||
输 入:无
|
||
输 出:无
|
||
返回值:无
|
||
创建者:奈特
|
||
调用例程:无
|
||
创建日期:2021-03-05
|
||
修改记录:
|
||
2021-03-09:新增CRC校验相关代码。
|
||
2021-03-12:新增0x10指令相关处理。
|
||
-------------------------------------------------------*/
|
||
extern void ecbm_modbus_rtu_run(void);
|
||
#endif
|