371 lines
9.2 KiB
C
371 lines
9.2 KiB
C
/*
|
||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||
*
|
||
* SPDX-License-Identifier: Apache-2.0
|
||
*
|
||
* Change Logs:
|
||
* Date Author Notes
|
||
* 2024-04-23 lijian the first version
|
||
*/
|
||
#include "modbus_rtu.h"
|
||
#include <board.h>
|
||
|
||
Modbus_RTU_t Modbus_RTU;
|
||
|
||
/**
|
||
* 设置modbus从机地址
|
||
* @param modbus_addr
|
||
*/
|
||
void set_Modbus_Addr(rt_uint16_t modbus_addr)
|
||
{
|
||
Modbus_RTU.modbus_addr = modbus_addr;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取Modbus从机地址
|
||
* @return rt_uint16
|
||
*/
|
||
rt_uint16_t get_Modbus_Addr()
|
||
{
|
||
return Modbus_RTU.modbus_addr;
|
||
}
|
||
|
||
/**
|
||
* 设置modbus寄存器地址
|
||
* @param modbus_reg_addr
|
||
*/
|
||
void set_Modbus_Reg_Addr(rt_uint16_t modbus_reg_addr)
|
||
{
|
||
Modbus_RTU.modbus_reg_addr = modbus_reg_addr;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取Modbus读取寄存器起始地址
|
||
* @return rt_uint16
|
||
*/
|
||
rt_uint16_t get_Modbus_Reg_Addr()
|
||
{
|
||
return Modbus_RTU.modbus_reg_addr;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置Modbus读寄存器数量
|
||
* @return rt_uint16
|
||
*/
|
||
void set_Modbus_Reg_Num(rt_uint16_t modbus_reg_num)
|
||
{
|
||
Modbus_RTU.modbus_reg_num = modbus_reg_num;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取Modbus读寄存器数量
|
||
* @return rt_uint16
|
||
*/
|
||
rt_uint16_t get_Modbus_Reg_Num()
|
||
{
|
||
return Modbus_RTU.modbus_reg_num;
|
||
}
|
||
|
||
|
||
|
||
//功能码01(0x01): 读线圈状态(Read Coils)
|
||
//功能码02(0x02): 读离散输入状态(Read Discrete Inputs)
|
||
//功能码03(0x03): 读保持寄存器(Read Holding Registers)
|
||
//功能码04(0x04): 读输入寄存器(Read Input Registers)
|
||
//功能码05(0x05): 写单个线圈(Write Single Coil)
|
||
//功能码06(0x06): 写单个保持寄存器(Write Single Holding Register)
|
||
//功能码15(0x0F): 写多个线圈(Write Multiple Coils)
|
||
//功能码16(0x10): 写多个保持寄存器(Write Multiple Holding Registers)
|
||
|
||
/**
|
||
* modbus初始化
|
||
*/
|
||
void Modbus_init()
|
||
{
|
||
|
||
// Modbus_RTU.modbus_addr = (rt_uint16_t)0x01;
|
||
// Modbus_RTU.modbus_reg_addr = (rt_uint16_t)0x00;
|
||
// Modbus_RTU.modbus_reg_num = (rt_uint16_t)0x02;
|
||
|
||
rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE,
|
||
RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL);
|
||
|
||
if (hinst == RT_NULL)
|
||
{
|
||
rt_kprintf("create rs485 instance fail.\n");
|
||
return;
|
||
}
|
||
|
||
rs485_set_recv_tmo(hinst, 1000);
|
||
if (rs485_connect(hinst) != RT_EOK)
|
||
{
|
||
rs485_destory(hinst);
|
||
rt_kprintf("rs485 connect fail.\n");
|
||
return;
|
||
}
|
||
|
||
rt_uint8_t ctx_send_buf[AGILE_MODBUS_MAX_ADU_LENGTH];
|
||
rt_uint8_t ctx_read_buf[AGILE_MODBUS_MAX_ADU_LENGTH];
|
||
|
||
|
||
agile_modbus_rtu_t ctx_rtu;
|
||
agile_modbus_t *ctx = &ctx_rtu._ctx;
|
||
agile_modbus_rtu_init(&ctx_rtu, ctx_send_buf, sizeof(ctx_send_buf), ctx_read_buf, sizeof(ctx_read_buf));
|
||
agile_modbus_set_slave(ctx, Modbus_RTU.modbus_addr); //地址
|
||
rt_kprintf("Modbus Running.\n");
|
||
|
||
|
||
rt_int8_t send_len;
|
||
rt_int8_t read_len;
|
||
rt_uint8_t i;
|
||
rt_int8_t rc;
|
||
|
||
//
|
||
|
||
|
||
while (1)
|
||
{
|
||
rt_thread_mdelay(1000);
|
||
|
||
|
||
//if(Modbus_RTU.modbus_func == 3){
|
||
send_len = agile_modbus_serialize_read_registers(ctx, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num);
|
||
//
|
||
// } else if(Modbus_RTU.modbus_func == 1){
|
||
// send_len = agile_modbus_serialize_read_bits(ctx, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num);
|
||
//
|
||
// }
|
||
|
||
// rt_kprintf("rs485 send %d datas : ", send_len);
|
||
// for (i = 0; i < send_len; i++) {
|
||
// rt_kprintf("%02X ", ctx->send_buf[i]);
|
||
// }
|
||
|
||
// rt_kprintf("\n");
|
||
|
||
read_len = rs485_send_then_recv(hinst, (void *) ctx->send_buf, send_len, ctx->read_buf, ctx->read_bufsz);
|
||
if (read_len < 0)
|
||
{
|
||
// rt_kprintf("rs485 send datas error.\n");
|
||
break;
|
||
}
|
||
|
||
if (read_len == 0)
|
||
{
|
||
// rt_kprintf("rs485 recv timeout.\n");
|
||
continue;
|
||
}
|
||
|
||
ctx->read_buf[read_len] = 0;
|
||
|
||
// Bsp_Rs485_Tx(ctx->send_buf, send_len); //
|
||
// int read_len = Bsp_Rs485_Rx(ctx->read_buf, ctx->read_bufsz); //
|
||
|
||
if (read_len == 0)
|
||
{
|
||
// rt_kprintf("Receive timeout.\n");
|
||
continue;
|
||
}
|
||
rc = agile_modbus_deserialize_read_registers(ctx, read_len, Modbus_RTU.hold_register);
|
||
if (rc < 0)
|
||
{
|
||
Modbus_RTU.modbus_rec = 0;
|
||
|
||
rt_kprintf("Receive failed.\n");
|
||
if (rc != -1)
|
||
rt_kprintf("Error code:%d\n", -128 - rc);
|
||
continue;
|
||
}
|
||
|
||
Modbus_RTU.modbus_rec = 1;
|
||
|
||
if (Modbus_RTU.log) {
|
||
rt_kprintf("Hold Registers:");
|
||
for (i = 0; i < 10; i++)
|
||
rt_kprintf("Register [%d]: 0x%04X\n", i, Modbus_RTU.hold_register[i]);
|
||
}
|
||
|
||
if (Modbus_RTU.modbus_rec) {
|
||
//get_modbus_rec();
|
||
// MQTT_Send_Modbus(get_modbus_rec());
|
||
}
|
||
rt_kprintf("\r\n\r\n\r\n");
|
||
}
|
||
|
||
}
|
||
|
||
void set_modbus_log(rt_uint8_t log){
|
||
Modbus_RTU.log = log;
|
||
}
|
||
|
||
/**
|
||
* 获取modbus读取数据的转换后返回值
|
||
* @return
|
||
*/
|
||
rt_uint16_t get_modbus_rec(){
|
||
if (Modbus_RTU.modbus_rec) {
|
||
|
||
rt_uint8_t high_d=0;
|
||
rt_uint8_t low_d=0;
|
||
|
||
if (Modbus_RTU.modbus_reg_num == 2) {
|
||
high_d = Modbus_RTU.hold_register[0];
|
||
low_d = Modbus_RTU.hold_register[1];
|
||
rt_uint16_t rec = (high_d << 8) | low_d;
|
||
return rec;
|
||
}
|
||
Modbus_RTU.modbus_rec =0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
//void Bsp_Rs485_Tx(){
|
||
//
|
||
//}
|
||
//
|
||
//void Bsp_Rs485_Rx(){
|
||
//
|
||
//}
|
||
//
|
||
//static void rs485_sample_master(void *args)
|
||
//{
|
||
// const char read_cmd[] = "read datas test\r\n";
|
||
// static rt_uint8_t buf[256];
|
||
// rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE,
|
||
// RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL);
|
||
//
|
||
// if (hinst == RT_NULL)
|
||
// {
|
||
// LOG_E("create rs485 instance fail.");
|
||
// return;
|
||
// }
|
||
//
|
||
// rs485_set_recv_tmo(hinst, 1000);
|
||
// if (rs485_connect(hinst) != RT_EOK)
|
||
// {
|
||
// rs485_destory(hinst);
|
||
// LOG_E("rs485 connect fail.");
|
||
// return;
|
||
// }
|
||
//
|
||
// while (1)
|
||
// {
|
||
// int len = strlen(read_cmd);
|
||
// len = rs485_send_then_recv(hinst, (void *) read_cmd, len, buf, sizeof(buf));
|
||
// if (len < 0)
|
||
// {
|
||
// LOG_E("rs485 send datas error.");
|
||
// break;
|
||
// }
|
||
//
|
||
// if (len == 0)
|
||
// {
|
||
// LOG_D("rs485 recv timeout.");
|
||
// continue;
|
||
// }
|
||
//
|
||
// buf[len] = 0;
|
||
// LOG_D("rs485 recv %d datas : %s", len, buf);
|
||
// }
|
||
//
|
||
//}
|
||
|
||
//
|
||
//#define PORT_NUM MB_MASTER_USING_PORT_NUM
|
||
//#define PORT_BAUDRATE MB_MASTER_USING_PORT_BAUDRATE
|
||
//
|
||
//#define PORT_PARITY MB_PAR_EVEN
|
||
//
|
||
//#define MB_POLL_CYCLE_MS 500
|
||
//
|
||
//#define func_Coil 1
|
||
//#define func_Holding 3
|
||
//
|
||
//#define MODBUS_REG_NUM 30
|
||
|
||
//rt_uint16_t buffer[MODBUS_REG_NUM];
|
||
//
|
||
///*
|
||
// *
|
||
|
||
// *
|
||
// */
|
||
//
|
||
//void Copy_Holding(rt_uint16_t * Holding, rt_uint16_t reg_num){
|
||
// rt_uint16_t * a = get_modbus_03();
|
||
// for (rt_uint8_t var = 0; var < reg_num; var++) {
|
||
// Holding[var] = a[var];
|
||
// }
|
||
//}
|
||
//
|
||
//void Copy_Coil(rt_uint16_t * Coil, rt_uint16_t reg_num){
|
||
// unsigned char * a = get_modbus_01();
|
||
// for (rt_uint8_t var = 0; var < reg_num; var++) {
|
||
// Coil[var] = a[var];
|
||
// }
|
||
//}
|
||
//
|
||
//
|
||
//
|
||
//void Modbus_Read_Holding_Registers(rt_uint16_t addr, rt_uint16_t reg_addr, rt_uint16_t reg_num, rt_uint16_t * Holding){
|
||
//
|
||
// while(1){
|
||
// eMBMasterPoll();
|
||
//
|
||
// /*
|
||
// * ucSndAddr 请求的从机地址,0代表广播。
|
||
// usRegAddr 读寄存器的地址
|
||
// usRegData 读寄存器的数量
|
||
// lTimeOut 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。
|
||
// */
|
||
// eMBMasterReqReadHoldingRegister(addr, reg_addr, reg_num, 1000);
|
||
//
|
||
// rt_thread_mdelay(MB_POLL_CYCLE_MS);
|
||
//
|
||
// if (get_Holding_flag()) {
|
||
// Copy_Holding(Holding, reg_num);
|
||
// Modbus_RTU.modbus_rec =1;
|
||
// get_modbus_rec();
|
||
// }
|
||
//
|
||
// }
|
||
//}
|
||
//
|
||
//void Modbus_Read_Coils(rt_uint16_t addr, rt_uint16_t reg_addr, rt_uint16_t reg_num, rt_uint16_t * Coil){
|
||
//
|
||
// while(1){
|
||
// eMBMasterPoll();
|
||
//
|
||
// /*
|
||
// * ucSndAddr 请求的从机地址,0代表广播。
|
||
// usCoilAddr 读线圈的地址
|
||
// usNCoils 读线圈的数量
|
||
// lTimeOut 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可
|
||
// */
|
||
// eMBMasterReqReadCoils(addr, reg_addr, reg_num, 1000);
|
||
//
|
||
// rt_thread_mdelay(MB_POLL_CYCLE_MS);
|
||
// if (get_Coil_flag()) {
|
||
// Copy_Coil(Coil , reg_num);
|
||
// Modbus_RTU.modbus_rec =1;
|
||
// }
|
||
// }
|
||
//}
|
||
//
|
||
//
|
||
//void Modbus_config(void){
|
||
//
|
||
// eMBMasterInit(MB_RTU, PORT_NUM, PORT_BAUDRATE, PORT_PARITY);
|
||
// eMBMasterEnable();
|
||
//
|
||
//// if(Modbus_RTU.modbus_func == func_Holding){
|
||
// Modbus_Read_Holding_Registers(Modbus_RTU.modbus_addr, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num ,buffer);
|
||
//// } else if(Modbus_RTU.modbus_func == func_Coil){
|
||
//// Modbus_Read_Coils(Modbus_RTU.modbus_addr, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num , buffer);
|
||
//// }
|
||
//
|
||
//}
|
||
//
|
||
|
||
|