查看: 2717|回复: 9

扩展库使用说明——modbus主机

[复制链接]

5

主题

6

帖子

121

积分

版主

Rank: 7Rank: 7Rank: 7

积分
121
发表于 2021-11-30 16:52:20 | 显示全部楼层 |阅读模式
本帖最后由 fangyan123 于 2021-11-30 17:03 编辑

在这里Modbus主要指Modbus-RTU协议,下面的说明均以Modbus-RTU协议进行说明。如果对Modbus协议不了解,建议先下载最下方的“Modbus协议.pdf”文档熟悉该协议。
1-协议简介
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。
2-硬件连接
  Modbus协议实际应用一般基于RS485物理层,下图为RS485模块接线图:

27

27

  在测试协议时,可以通过串口与电脑上位机软件通信进行测试,下面的测试程序都是直接通过电脑上位机进行测试。

3-图形块说明
在这里会挑一些重要或者特殊的进行说明。
1.读线圈
      

24

24

      输入参数:1.超时时间:主机发送数据后,堵塞等待从机响应的最长时间。
                      2.buf:读回来的线圈值,为无符号8位整数的数组。
       返回参数:从机响应超时返回0,不正确类型返回-1,成功返回1。

2.读输入寄存器
      

23

23

      输入参数:1.buf:读回来的输入寄存器值,为无符号8位整数类型的数组,也就是会将输入寄存器的16位数据拆分    为2个8位的数据,高位在前低位在后。

3.写多个保持寄存器
      

22

22

      输入参数:1.buf:读回来的输入寄存器值,为无符号8位整数类型的数组,也就是会将输入寄存器的16位数据拆分    为2个8位的数据,高位在前低位在后。

4.读保持寄存器
      

21

21

      输入参数:1.buf:读回来的输入寄存器值,为无符号8位整数类型的数组,也就是会将输入寄存器的16位数据拆分    为2个8位的数据,高位在前低位在后。

5.读写多个保持寄存器
      

20

20

      输入参数:1.buf:该语句会将buf中的数据写入从机,并将从机读取回来的数据又写回buf中,为无符号8位整数类      型的数组,也就是会将输入寄存器的16位数据拆分为2个8位的数据,高位在前低位在后。

6.定时回调函数
      

19

19

      需要使用定时器每隔100us调用一次。

4-范例代码
1.读取线圈
  图形块以及字符代码

18

18


  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     if(mbMaster.ReqReadCoils(1,1,9,buf,500)){
  22.       spi_tft.clear((0x67FF));
  23.       spi_tft.set_cursor(34,0);
  24.       spi_tft.draw_hanzi_12("读线圈测试");
  25.       spi_tft.set_cursor(0,15);
  26.       spi_tft.println((String("buf[0]:") + String(buf[(int)(0)])));
  27.       spi_tft.println((String("buf[1]:") + String(buf[(int)(1)])));
  28.       delay(1000);
  29.     }
  30.   }
  31.   return 1;
  32. }
复制代码
效果展示:

17

17

2.读离散量输入
  图形块以及字符代码

16

16


  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     if(mbMaster.ReqReadDiscreteInputs(1,1,9,buf,500)){
  22.       spi_tft.clear((0x67FF));
  23.       spi_tft.set_cursor(34,0);
  24.       spi_tft.draw_hanzi_12("读线圈测试");
  25.       spi_tft.set_cursor(0,15);
  26.       spi_tft.println((String("buf[0]:") + String(buf[(int)(0)])));
  27.       spi_tft.println((String("buf[1]:") + String(buf[(int)(1)])));
  28.       delay(1000);
  29.     }
  30.   }
  31.   return 1;
  32. }
复制代码
效果展示:

15

15


3.读输入寄存器
  图形块及字符代码

14

14

  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     if(mbMaster.ReqReadInputRegister(1,1,1,buf,500)){
  22.       spi_tft.clear((0x67FF));
  23.       spi_tft.set_cursor(34,0);
  24.       spi_tft.draw_hanzi_12("读输入测试");
  25.       spi_tft.set_cursor(0,15);
  26.       spi_tft.println((String("buf[0]:") + String(buf[(int)(0)])));
  27.       spi_tft.println((String("buf[1]:") + String(buf[(int)(1)])));
  28.       delay(1000);
  29.     }
  30.   }
  31.   return 1;
  32. }
复制代码
效果展示:

13

13

4.读保持寄存器
  图形块及字符代码

12

12

  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     if(mbMaster.ReqReadHoldingRegister(1,1,1,buf,500)){
  22.       spi_tft.clear((0x67FF));
  23.       spi_tft.set_cursor(16,0);
  24.       spi_tft.draw_hanzi_12("读保持寄存器测试");
  25.       spi_tft.set_cursor(0,15);
  26.       spi_tft.println((String("buf[0]:") + String(buf[(int)(0)])));
  27.       spi_tft.println((String("buf[1]:") + String(buf[(int)(1)])));
  28.       delay(1000);
  29.     }
  30.   }
  31.   return 1;
  32. }
复制代码
效果展示:

11

11

5.写单个线圈
  图形块及字符代码

10

10

  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     spi_tft.clear((0x67FF));
  22.     spi_tft.set_cursor(0,10);
  23.     if(mbMaster.ReqWriteCoil(1,1,0,500)){
  24.       spi_tft.draw_hanzi_12("写线圈成功");
  25.     }
  26.     else{
  27.       spi_tft.draw_hanzi_12("写线圈失败");
  28.     }
  29.     delay(1000);
  30.     spi_tft.clear((0x67FF));
  31.     spi_tft.set_cursor(0,22);
  32.     if(mbMaster.ReqWriteCoil(1,1,1,500)){
  33.       spi_tft.draw_hanzi_12("写线圈成功");
  34.     }
  35.     else{
  36.       spi_tft.draw_hanzi_12("写线圈失败");
  37.     }
  38.     delay(1000);
  39.   }
  40.   return 1;
  41. }
复制代码
效果展示:

       无


6.写多个线圈
  图形块及字符代码

9

9

  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     spi_tft.clear((0x67FF));
  22.     spi_tft.set_cursor(0,10);
  23.     buf[(int)(0)] = 0xff;
  24.     if(mbMaster.ReqWriteCoil_S(1,1,6,buf,500)){
  25.       spi_tft.draw_hanzi_12("写线圈成功");
  26.     }
  27.     else{
  28.       spi_tft.draw_hanzi_12("写线圈失败");
  29.     }
  30.     delay(1000);
  31.     spi_tft.clear((0x67FF));
  32.     spi_tft.set_cursor(0,22);
  33.     buf[(int)(0)] = 0;
  34.     if(mbMaster.ReqWriteCoil_S(1,1,6,buf,500)){
  35.       spi_tft.draw_hanzi_12("写线圈成功");
  36.     }
  37.     else{
  38.       spi_tft.draw_hanzi_12("写线圈失败");
  39.     }
  40.     delay(1000);
  41.   }
  42.   return 1;
  43. }
复制代码
效果展示:

8

8


7.写单个保持寄存器
  图形块及字符代码

3

3
  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     spi_tft.clear((0x67FF));
  22.     spi_tft.set_cursor(0,10);
  23.     if(mbMaster.ReqWriteHoldingRegister(1,1,0x1234,500)){
  24.       spi_tft.draw_hanzi_12("写寄存器成功");
  25.     }
  26.     else{
  27.       spi_tft.draw_hanzi_12("写寄存器失败");
  28.     }
  29.     delay(1000);
  30.   }
  31.   return 1;
  32. }
复制代码
效果展示:

6

6



8.写多个保持寄存器
  图形块及字符代码

4

4
  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     buf[(int)(0)] = 0x12;
  22.     buf[(int)(1)] = 0x34;
  23.     buf[(int)(2)] = 0x56;
  24.     buf[(int)(3)] = 0x78;
  25.     spi_tft.clear((0x67FF));
  26.     spi_tft.set_cursor(0,10);
  27.     if(mbMaster.ReqWriteHoldingRegister_S(1,1,2,buf,500)){
  28.       spi_tft.draw_hanzi_12("写寄存器成功");
  29.     }
  30.     else{
  31.       spi_tft.draw_hanzi_12("写寄存器失败");
  32.     }
  33.     delay(1000);
  34.   }
  35.   return 1;
  36. }
复制代码
效果展示:

5

5


7.读写多个保持寄存器
  图形块及字符代码

2

2
  1. #define MBMASTER_USART1 1

  2. #include <CH32V103.h>
  3. #include "myLib/CH32V_ST7735S.h"
  4. #include "mylib/MB_Master.h"
  5. #include "CH32V_TIM.h"

  6. uint8_t buf[5];

  7. SPITFT spi_tft(128,128,PC5,PA2,PA4);
  8. MBMaster mbMaster(USART1,9600,USART_Parity_No);
  9. void TIM_attachInterrupt_2() {
  10.   mbMaster.TimerCallback();
  11. }

  12. int main(void)
  13. {
  14.   CH32_Init();
  15.   spi_tft.init();
  16.   spi_tft.set_direction(2);
  17.   spi_tft.clear((0x67FF));
  18.   mbMaster.Init();
  19.   TIM_attachInterrupt(TIM2, 100, TIM_attachInterrupt_2);
  20.   while(1){
  21.     buf[(int)(0)] = 0x12;
  22.     buf[(int)(1)] = 0x34;
  23.     buf[(int)(2)] = 0x56;
  24.     buf[(int)(3)] = 0x78;
  25.     spi_tft.clear((0x67FF));
  26.     spi_tft.set_cursor(0,10);
  27.     if(mbMaster.ReqReadWriteHoldingRegister_S(1,3,2,1,2,buf,500)){
  28.       spi_tft.draw_hanzi_12("写寄存器成功");
  29.       spi_tft.set_cursor(0,27);
  30.       spi_tft.println((String("buf[0]:") + String(buf[(int)(0)])));
  31.       spi_tft.println((String("buf[1]:") + String(buf[(int)(1)])));
  32.     }
  33.     else{
  34.       spi_tft.draw_hanzi_12("写寄存器失败");
  35.     }
  36.     delay(1000);
  37.   }
  38.   return 1;
  39. }
复制代码
效果展示:

1

1


附件: Modbus协议.pdf (1.04 MB, 下载次数: 76)
回复

使用道具 举报

1

主题

2

帖子

47

积分

注册会员

Rank: 2

积分
47
发表于 2021-12-30 16:22:06 | 显示全部楼层
您好,使用STC8H1K08,测试modbus读保持寄存器功能时,无法正常读取数值。经过检查,发现发送数据modbus的采集命令正常,回复也正常。但是判断接收时为错误。
#define ModBus_Master_UART UART_2

#include <STC8HX.h>
uint32 sys_clk = 24000000;//设置PWM、定时器、串口、EEPROM频率参数
#include "lib/twen_board.h"
#include "mylib/MB_Master.h"
#include "lib/UART.h"

uint8 mylist[4]={0,0,0,0};

void Timer0Init(void)        //100微秒@24.000MHz
{
  AUXR &= 0x7f;                //定时器时钟12T模式
  TMOD &= 0xf0;                //设置定时器模式
  TL0 = 0x38;                        //设定定时初值
  TH0 = 0xff;                        //设定定时初值
}

void T_IRQ0(void) interrupt 1 using 1{
  MBMasterTimerCallback();
}

void setup()
{
  twen_board_init();//天问51初始化
  Timer0Init();
  MBMasterInit(UART_2, UART2_RX_P10, UART2_TX_P11, 9600, TIM_2, MB_M_PAR_NONE);
  uart_init(UART_1, UART1_RX_P30, UART1_TX_P31, 9600, TIM_1);//初始化串口
}

void loop()
{
  mylist[(int)(0)] = 1;
  mylist[(int)(1)] = 2;
  mylist[(int)(2)] = 0;
  mylist[(int)(3)] = 1;
  if(MBMasterReqWriteHoldingRegister_S(1,1,1,mylist,500)){

  }
  if(MBMasterReqReadHoldingRegister(1,2,1,mylist,500)){

  }
  uart_putchar(UART_1, mylist[(int)(0)]);//串口单个字符输出
  uart_putchar(UART_1, mylist[(int)(1)]);//串口单个字符输出
  uart_putchar(UART_1, mylist[(int)(2)]);//串口单个字符输出
  uart_putchar(UART_1, mylist[(int)(3)]);//串口单个字符输出
}

void main(void)
{
  setup();
  while(1){
    loop();
  }
}
回复

使用道具 举报

1

主题

3

帖子

19

积分

注册会员

Rank: 2

积分
19
发表于 2022-1-16 15:39:32 | 显示全部楼层
图形例程方便打包发上来吗??
回复

使用道具 举报

1

主题

3

帖子

83

积分

注册会员

Rank: 2

积分
83
发表于 2022-1-26 14:46:46 | 显示全部楼层
从机的使用方法有空也发一下吧
回复

使用道具 举报

0

主题

6

帖子

70

积分

注册会员

Rank: 2

积分
70
发表于 2022-1-30 18:46:30 | 显示全部楼层
#include "mylib/MB_Master.h"老大这个文件有么
回复

使用道具 举报

41

主题

167

帖子

3038

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3038
发表于 2022-2-4 11:48:40 | 显示全部楼层
天问Block软件,文件--项目中心--最新项目,搜:modbus
回复

使用道具 举报

0

主题

1

帖子

32

积分

注册会员

Rank: 2

积分
32
发表于 2022-4-1 07:06:25 | 显示全部楼层
modbus从机程序有问题呀,有完整的吗?可以付费
回复

使用道具 举报

1

主题

4

帖子

51

积分

注册会员

Rank: 2

积分
51
发表于 2022-4-4 21:32:31 | 显示全部楼层
可以直接用到stc32G芯片上吗
回复

使用道具 举报

1

主题

4

帖子

25

积分

注册会员

Rank: 2

积分
25
发表于 2022-11-12 19:39:35 | 显示全部楼层
大神有微信吗?我这里有个485问题求助
回复

使用道具 举报

1

主题

6

帖子

23

积分

注册会员

Rank: 2

积分
23
发表于 2023-10-10 21:00:49 | 显示全部楼层
大师,如果两个主串口应该怎么排列呢,谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|好好搭搭在线 ( © 好好搭搭在线 浙ICP备19030393号-1 )

GMT+8, 2024-3-29 08:14 , Processed in 0.331222 second(s), 25 queries .

Powered by Discuz!

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表