(XT Mini Mod bus) C 언어 내 장 형 Mod bus 프로토 콜 스 택 , 마스터 , 슬 레이 브 예 제 소 스 코드

Paid ¥6.99Paid ¥6.99

该内容已接入现有会员/付费系统,解锁后可查看完整资料或下载附件。

查看解锁方式
(XT Mini Mod bus) C 언어 내 장 형 Mod bus 프로토 콜 스 택 , 마스터 , 슬 레이 브 예 제 소 스 코드

X T iny Mod bus 는 리 소 스가 제한 된 임 베 디 드 시스템을 위해 설계 된 경 량 C 언어 임 베 디 드 Mod bus 프로토 콜 스 택 입니다 . Mod bus R TU 및 Mod bus AS C II 전송 모 드를 지원 하며 마스터 및 슬 레이 브 기능을 제공합니다 .이 문서 에서는 X T iny Mod bus 의 아 키 텍 처 특성 , API 인터페 이스 , 마이 그레이 션 방법 및 전체 마스터 슬 레이 브 샘플 소 스 코드를 자세히 설명 합니다 .

X T iny Mod bus 개 요

X T iny Mod bus 는 최소 리 소 스 소비 로 완전한 Mod bus 프로토 콜 기능을 제공하기 위해 설계 되었습니다 .순 수한 C 언어로 작성 되었으며 운영 체 제에 의존 하지 않으며 51 MC U , AV R , S TM 32, MS P 430 및 기타 임 베 디 드 플랫폼 으로 쉽게 이 식 할 수 있습니다 .

1. 1 핵심 특징

  • 超轻量级
  • 主从站一体
  • 双协议支持
  • 无操作系统依赖
  • 功能码完整
  • 可裁剪配置
  • 中断驱动
  • CRC check

1. 2 자원 사용 량

资源
Flash(代码)
RAM(全局变量)
栈空间
接收缓冲区
发送缓冲区

2. 문서 구조

X T iny Mod bus /
- - x t iny _ mod bus . h          / / 마스터 헤 더 파일 , API 선언 및 구성 매 크 로
- - x t iny _ mod bus . c          / / 핵심 프로토 콜 구현
- - x t iny _ mod bus _ port . h     플랫폼 포 팅 인터페 이스 (사 용 자 구현)
- - x t iny _ mod bus _ conf ig . h   / / 프로 파 일 (기 능 자 르기)
예 제 / ex amples
    - - - slave _ demo . c        / / 슬 레이 브 예 제
    - - master _ demo . c       / / 기본 스테 이션 예 제
    st m 32 _ port . c        S TM 32 마이 그레이 션 예 제

III . 구성 옵션

xt iny _ mod bus _ conf ig . h 에서 매 크 로를 통해 구성 기능을 정의 합니다 .

/ / 마스터 기능 활성화 (주 석 이 제거 되면 슬 레이 브 만 컴 파 일)
# define X MB _ en ab le _ MAS TER        1

/ / 슬 레이 브 기능 활성화
# define X MB _ EN AB LE _ S LA VE         1

프로토 콜 모 드 : 1 = R TU , 0 = AS C II
# define X MB _ R TU _ MO DE             1

/ / 버 퍼 크기
# define X MB _ BU F _ S IZ E             64

/ / 슬 레이 브 주소 (1 - 24 7)
# define X MB _ S LA VE _ AD DR           1

지원 되는 기능 코드 (필 요한 주 석을 제거 하면 코드 볼 륨 을 줄 일 수 있음)
# define X MB _ FC _ READ _ CO IL S        1   // 0 x 01
# define X MB _ FC _ READ _ IN PU TS       1   // 0 x 02
# define X MB _ FC _ READ _ H OL D ING S     1   // 0 x 03
# define X MB _ FC _ READ _ IN P UT _ REG ETS   1   // 0 x 04
X MB _ FC _ W R ITE _ CO IL 정의        1   // 0 x 05
# define X MB _ FC _ W R ITE _ REG IS TER    1   // 0 x 06
# define X MB _ FC _ W R ITE _ CO IL S       1   // 0 x 0 f
# define X MB _ FC _ W R ITE _ REG IS TER S   1   0 x 10

/ / 데이터 영역 크기
# define X mb _ co ils _ num            16 / / 코 일 수
# define X mb _ input _ num           16 / / 단 속 입력 수 량
# define X MB _ H OL D ING S _ N UM         32 / / 레 지 스터 수 를 유지 합니다 .
# define X MB _ IN P UT _ REG S _ N UM       16 / / 입력 레 지 스터 수

프레 임 시간 초 과 시간 (문 자 간 격 , ms)
# define X MB _ FR AME _ TIM EO UT        5

플랫폼 이 식 인터페 이스

X T iny Mod bus 는 콜 백 함 수를 통해 하드 웨어 플랫폼 과 분리 되어 사용자는 다음 인터페 이 스를 구현 할 수 있습니다 .

x t iny _ mod bus _ port . h

직 렬 포 트 초기 화 (바 트 속도 , 데이터 비트 , 중지 비트 , 체크 비트)
vo id x mb _ port _ u art _ init (u int 32 _ t baud rate);

/ / 바 이트 를 보내 다
vo id x mb _ port _ u art _ send _ by te (u int 8 _ t by te);

/ / 수신 인터 럽 트 사용 가능 / 사용 안 함
vo id x mb _ port _ u art _ r x _ enable (u int 8 _ t enable);

/ / 전송 완료 인터 럽 트 활성화 / 비 활 성 화
vo id x mb _ port _ u art _ tx _ enable (u int 8 _ t enable);

/ / 시스템 밀 리 초 카운 트 가져 오 기 (타 임 초 과 감지 용)
u int 32 _ t x mb _ port _ get _ ti ck (vo id);

/ / 임 계 영역 으로 들어가 기 (중 단 끄 기)
vo id x mb _ port _ enter _ critical (vo id);

/ / 임 계 영역 종료 (개 인 인터 럽 트)
vo id x mb _ port _ exit _ critical (vo id);

/ / RS 48 5 송 수 신 제어 (1 = 전송 , 0 = 수신)
vo id x mb _ port _ rs 48 5 _ dir (u int 8 _ t tx);

4. 1 S TM 32 마이 그레이 션 예

< code>// stm32_port.c
#include "stm32f10x.h"
#include "xtiny_modbus.h"

static volatile uint32_t sys_tick = 0;

// SysTick中断,1ms一次
void SysTick_Handler(void) {
    sys_tick++;
}

void xmb_port_uart_init(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStruct;
    USART_InitTypeDef USART_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // TX: PA9  复用推挽输出
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // RX: PA10 浮空输入
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // RS485方向控制: PA8
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    USART_InitStruct.USART_BaudRate = baudrate;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART1, &USART_InitStruct);
    
    // 使能接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
    USART_Cmd(USART1, ENABLE);
}

void xmb_port_uart_send_byte(uint8_t byte) {
    USART_Send데이터(USART1, byte);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void xmb_port_uart_rx_enable(uint8_t enable) {
    if (enable) USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    else USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
}

void xmb_port_uart_tx_enable(uint8_t enable) {
    if (enable) USART_ITConfig(USART1, USART_IT_TC, ENABLE);
    else USART_ITConfig(USART1, USART_IT_TC, DISABLE);
}

uint32_t xmb_port_get_tick(void) {
    return sys_tick;
}

void xmb_port_enter_critical(void) {
    __disable_irq();
}

void xmb_port_exit_critical(void) {
    __enable_irq();
}

void xmb_port_rs485_dir(uint8_t tx) {
    if (tx) GPIO_SetBits(GPIOA, GPIO_Pin_8);
    else GPIO_초기화Bits(GPIOA, GPIO_Pin_8);
}

// 串口中断服务程序
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t byte = USART_Receive데이터(USART1);
        xmb_uart_rx_isr(byte);  // 交给协议栈处理
    }
    if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) {
        USART_지우기ITPendingBit(USART1, USART_IT_TC);
        xmb_uart_tx_isr();     // 通知协议栈发送完成
    }
}

五、从站模式完整示例

// slave_demo.c
#include "xtiny_modbus.h"
#include <stdint.h>

// 应用数据区(用户可直接读写)
uint8_t  coils[XMB_COILS_NUM];           // Coil status
uint8_t  inputs[XMB_INPUTS_NUM];         // 离散输入
uint16_t holdings[XMB_HOLDINGS_NUM];     // 保持寄存器
uint16_t input_regs[XMB_INPUT_REGS_NUM]; // 输入寄存器

int main(void) {
    // 初始化系统时钟、GPIO等
    SystemInit();
    SysTick_Config(SystemCoreClock / 1000);  // 1ms SysTick
    
    // 初始化Modbusslave
    xmb_slave_init(9600, XMB_SLAVE_ADDR);
    
    // 注册数据区回调(或直接使用全局数组)
    xmb_slave_set_coils(coils);
    xmb_slave_set_inputs(inputs);
    xmb_slave_set_holdings(holdings);
    xmb_slave_set_input_regs(input_regs);
    
    // 初始化一些数据
    holdings[0] = 100;  // temperature
    holdings[1] = 50;   // 湿度
    
    while (1) {
        // 主循环中调用协议栈处理
        xmb_slave_poll();
        
        // 用户应用代码
        // 例如:读取传感器更新到input_regs
        // input_regs[0] = read_adc();
        
        // 更新线圈状态到实际输出
        // for (i=0; i<8; i++) set_relay(i, coils[i]);
    }
}

// 写线圈回调(可选,用于执行实际动作)
void xmb_callback_write_coil(uint16_t addr, uint8_t value) {
    // 当主站写线圈时调用
    // 例如:控制继电器
    // set_relay(addr, value);
}

// 写寄存器回调(可选)
void xmb_callback_write_register(uint16_t addr, uint16_t value) {
    // 当主站写保持寄存器时调用
    // 例如:更新设定值
    // if (addr == 0) set_temperature(value);
}

六、主站模式完整示例

// master_demo.c
#include "xtiny_modbus.h"
#include <stdio.h>

int main(void) {
    uint8_t  coils[8];
    uint16_t regs[10];
    int16_t  rc;
    
    SystemInit();
    SysTick_Config(SystemCoreClock / 1000);
    
    // 初始化Modbusmaster
    xmb_master_init(9600);
    
    while (1) {
        // 读取从站1的8个线圈状态
        rc = xmb_master_read_coils(1, 0, 8, coils);
        if (rc == XMB_OK) {
            printf("读取成功:");
            for (int i = 0; i < 8; i++) printf("%d ", coils[i]);
            printf("\n");
        } else {
            printf("Read failed,错误码:%d\n", rc);
        }
        
        // 读取从站1的10个保持寄存器
        rc = xmb_master_read_holdings(1, 0, 10, regs);
        if (rc == XMB_OK) {
            printf("register:");
            for (int i = 0; i < 10; i++) printf("%d ", regs[i]);
            printf("\n");
        }
        
        // write single coil:控制第1路继电器吸合
        rc = xmb_master_write_coil(1, 0, 1);
        if (rc == XMB_OK) printf("写线圈成功\n");
        
        // write single register
        rc = xmb_master_write_register(1, 0, 1234);
        if (rc == XMB_OK) printf("写寄存器成功\n");
        
        // write multiple coils
        uint8_t coil_vals[4] = {1, 0, 1, 0};
        xmb_master_write_coils(1, 0, 4, coil_vals);
        
        // write multiple registers
        uint16_t reg_vals[3] = {100, 200, 300};
        xmb_master_write_registers(1, 0, 3, reg_vals);
        
        // 延时1秒
        delay_ms(1000);
    }
}

// 错误码说明
// XMB_OK           = 0   成功
// XMB_ERR_TIMEOUT  = -1  超时
// XMB_ERR_CRC      = -2  CRC check오답
// XMB_ERR_EXCEPT   = -3  从站异常响应
// XMB_ERR_ADDR     = -4  地址不匹配
// XMB_ERR_BUSY     = -5  总线忙

七、51单片机移植要点

  • 缓冲区大小:51单片机RAM有限,建议将XMB_BUF_SIZE设为32
  • number of registers:线圈和寄存器数量不宜过多,建议各16个
  • 晶振选择:使用11.0592MHz晶振保证9600bps准确
  • 中断优先级:串口中断优先级设为最高,避免丢字节
  • 帧超时:51单片机无SysTick,可用定时器0实现1ms计时
  • 变量存储:大数组定义为x데이터或i데이터,避免占用直接寻址区
  • CRC表:CRC16查表法占用256字节ROM,51单片机可接受

7.1 51单片机定时器实现ms计时

// 51单片机1ms定时器(11.0592MHz)
static uint16_t xmb_tick = 0;

void timer0_init(void) {
    TMOD |= 0x01;   // 定时器0模式1
    TH0 = 0xFC;     // 1ms初值
    TL0 = 0x67;
    ET0 = 1;        // 使能定时器0中断
    TR0 = 1;        // 启动定时器0
    EA = 1;
}

void timer0_isr(void) interrupt 1 {
    TH0 = 0xFC;
    TL0 = 0x67;
    xmb_tick++;
}

uint32_t xmb_port_get_tick(void) {
    return xmb_tick;
}

八、common problems

  • 通讯无响应:检查从站地址、Baud rate、校验位是否一致,A/B线是否接反
  • CRC오답:确认晶振频率准确,串口配置正确,检查是否有干扰
  • 只能收不能发:检查RS485方向控制引脚,ConfirmDE/RE接在一起
  • 数据丢包:增大缓冲区,提高串口中断优先级,减少关中断时间
  • 主站超时:增加超时时间,确认从站响应速度,检查总线负载
  • 多从站冲突:确保每个从站地址唯一,总线两端接120Ω终端电阻
  • 编译报错:确认配置宏定义正确,移植인터페이스全部实现

九、与其他Modbus协议栈对比

td>
协议栈代码体积RAM占用masterslave适用平台
XTinyModbus~5KB~120B支持
FreeModbus
uModbus
libmodbus
mnModbus

X T iny Mod bus 는 매우 적은 자원 소비 와 간 결 한 API 설계 로 51 MC U 와 같은 매우 제한 된 자 원을 가진 임 베 디 드 시스템에 특히 적합 합니다 . X T Mod iny bus 는 매우 작은 하드 웨어 에서 Mod bus 통신 을 구현 해야 하는 프로젝트에 이상 적입니다 .이 문서 에서 제공 되는 코 드는 프로젝트 개발 에 직접 사용할 수 있으며 실제 제품에 통합 하기 전에 테스트 보 드 에서 통신 을 검 증 하는 것이 좋습니다 .

Put this resource to use in a real project?

Go to the Tool Center for message parsing, CRC 검증 and device debugging, or submit your requirements for selection and integration advice.

Engineer Membership

Turn this article into actionable debugging resources

After activation, you can use advanced message parsing, resource pack downloads, code examples, engineering cases and priority technical support, suitable for real project delivery.

Unlimited Advanced Tools
Resource & Code Packs
Complete Engineering Case Library
Priority Technical Support

Leave a Reply

Your email 주소 will not be published. Required fields are marked *.