(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_SendData(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_ResetBits(GPIOA, GPIO_Pin_8);
}

// シリアルポート中断服务程序
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t byte = USART_ReceiveData(USART1);
        xmb_uart_rx_isr(byte);  // 交给プロトコルスタック処理
    }
    if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) {
        USART_ClearITPendingBit(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 checkError
// 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计时
  • 变量存储:大配列定义为xdata或idata,避免占用直接寻址区
  • 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线是否接反
  • CRCError:確認晶振频率准确,シリアルポート設定正确,チェックありますか?干渉
  • 只能收不能发:チェック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 verification 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 address will not be published. Required fields are marked *.