Modbus 主站 从站 在STM32单片机上的实现,企业在用的程序。

在工业自动化领域,Modbus协议因其简单可靠,被广泛应用于设备间的通信。今天就来聊聊如何在STM32单片机上实现Modbus主站与从站功能,这可是企业实际在用的程序哦。

Modbus协议基础

Modbus协议定义了主站和从站之间如何通信。主站发起请求,从站响应。常见的功能码有0x03(读取保持寄存器)、0x06(写单个寄存器)等。比如主站要读取从站的保持寄存器数据,就会发送包含功能码0x03、从站地址、寄存器起始地址和数量等信息的请求帧。

STM32单片机实现Modbus主站

硬件准备

使用STM32开发板,一般需要用到串口(UART)来与外部设备进行Modbus通信。假设我们使用的是STM32F4系列开发板,将PA9(TX)和PA10(RX)配置为复用推挽输出模式用于串口通信。

软件实现

  1. 初始化串口
void USART_Init(void) {
    USART_InitTypeDef USART_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

    USART_InitStruct.USART_BaudRate = 9600;
    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_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStruct);

    USART_Cmd(USART1, ENABLE);
}

这里先使能GPIOA和USART1的时钟,配置PA9和PA10为复用功能并选择USART1的复用功能,最后设置串口的波特率、数据位、停止位等参数并使能串口。

  1. 发送Modbus请求帧
void Send_Modbus_Request(uint8_t slave_addr, uint8_t func_code, uint16_t reg_addr, uint16_t reg_count) {
    uint8_t request[8];
    uint16_t crc;

    request[0] = slave_addr;
    request[1] = func_code;
    request[2] = (uint8_t)(reg_addr >> 8);
    request[3] = (uint8_t)reg_addr;
    request[4] = (uint8_t)(reg_count >> 8);
    request[5] = (uint8_t)reg_count;

    crc = CalculateCRC16(request, 6);
    request[6] = (uint8_t)(crc & 0xFF);
    request[7] = (uint8_t)(crc >> 8);

    for (int i = 0; i < 8; i++) {
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, request[i]);
    }
}

这个函数构建Modbus请求帧,包括从站地址、功能码、寄存器地址和数量,然后计算CRC校验并添加到帧尾,最后通过串口发送出去。

STM32单片机实现Modbus从站

硬件部分同样是串口配置,和主站类似,不再赘述。

软件实现

  1. 接收处理函数
void Receive_Modbus_Response(void) {
    uint8_t response[256];
    uint8_t len = 0;

    while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)!= RESET) {
        response[len++] = USART_ReceiveData(USART1);
    }

    // 校验CRC
    uint16_t received_crc = (uint16_t)(response[len - 1] << 8 | response[len - 2]);
    uint16_t calculated_crc = CalculateCRC16(response, len - 2);

    if (received_crc == calculated_crc) {
        // 处理请求,根据功能码不同进行不同处理
        if (response[1] == 0x03) {
            // 读取保持寄存器功能码处理
            uint16_t reg_addr = (uint16_t)(response[2] << 8 | response[3]);
            uint16_t reg_count = (uint16_t)(response[4] << 8 | response[5]);
            // 这里根据实际寄存器数据填充响应帧
            // 假设保持寄存器数据在数组holding_regs中
            for (int i = 0; i < reg_count; i++) {
                response[9 + i * 2] = (uint8_t)(holding_regs[reg_addr + i] >> 8);
                response[10 + i * 2] = (uint8_t)holding_regs[reg_addr + i];
            }
            // 设置响应帧长度和CRC等
            response[7] = reg_count * 2;
            uint16_t new_crc = CalculateCRC16(response, 8 + reg_count * 2);
            response[8 + reg_count * 2] = (uint8_t)(new_crc & 0xFF);
            response[9 + reg_count * 2] = (uint8_t)(new_crc >> 8);

            // 发送响应帧
            for (int i = 0; i < 10 + reg_count * 2; i++) {
                while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                USART_SendData(USART1, response[i]);
            }
        }
    }
}

这个函数接收Modbus请求帧,校验CRC后根据功能码进行处理。这里以功能码0x03为例,读取保持寄存器数据并填充响应帧,重新计算CRC后发送响应。

总结

在STM32单片机上实现Modbus主站与从站功能,通过合理配置硬件和编写软件代码,可以满足企业设备通信的需求。实际应用中还需要根据具体场景进行优化,比如处理通信超时、错误重传等情况,让通信更加稳定可靠。希望这篇文章能给你在相关项目开发中带来一些启发。

Modbus 主站 从站 在STM32单片机上的实现,企业在用的程序。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐