基于STM32的Modbus协议精简版程序

简介: 基于STM32的Modbus协议精简版程序

STM32 Modbus RTU从站程序,包含核心功能,易于理解和移植。

一、最简Modbus从站实现(单文件版)

modbus_slave.c

/**
 * @file modbus_slave.c
 * @brief STM32 Modbus RTU从站精简实现
 * @date 2024
 */

#include "stm32f10x.h"
#include <string.h>

/* Modbus配置 */
#define MODBUS_SLAVE_ADDR    0x01    // 从站地址
#define MODBUS_BAUDRATE      9600    // 波特率
#define REG_HOLDING_NUM      10      // 保持寄存器数量

/* 保持寄存器 */
static uint16_t holding_regs[REG_HOLDING_NUM] = {
   0};

/* 接收缓冲区 */
static uint8_t rx_buf[256];
static uint8_t rx_len = 0;
static uint8_t frame_complete = 0;

/* 函数声明 */
static uint16_t crc16(uint8_t *buf, uint16_t len);
static void send_response(uint8_t *buf, uint8_t len);
static void process_modbus_frame(void);

/**
 * @brief 初始化Modbus
 */
void Modbus_Init(void)
{
   
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* 1. 使能时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    /* 2. 配置GPIO */
    // TX: PA2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // RX: PA3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 3. 配置USART */
    USART_InitStructure.USART_BaudRate = MODBUS_BAUDRATE;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);

    /* 4. 使能接收中断 */
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

    /* 5. 配置NVIC */
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* 6. 使能USART */
    USART_Cmd(USART2, ENABLE);

    /* 7. 初始化寄存器 */
    for(int i=0; i<REG_HOLDING_NUM; i++) {
   
        holding_regs[i] = i * 100;
    }
}

/**
 * @brief CRC16计算
 * @param buf 数据缓冲区
 * @param len 数据长度
 * @return CRC16值
 */
static uint16_t crc16(uint8_t *buf, uint16_t len)
{
   
    uint16_t crc = 0xFFFF;
    uint16_t i, j;

    for (i = 0; i < len; i++) {
   
        crc ^= buf[i];
        for (j = 0; j < 8; j++) {
   
            if (crc & 0x0001) {
   
                crc >>= 1;
                crc ^= 0xA001;
            } else {
   
                crc >>= 1;
            }
        }
    }
    return crc;
}

/**
 * @brief 发送响应
 * @param buf 数据缓冲区
 * @param len 数据长度
 */
static void send_response(uint8_t *buf, uint8_t len)
{
   
    uint16_t crc = crc16(buf, len);

    /* 发送数据 */
    for(uint8_t i=0; i<len; i++) {
   
        USART_SendData(USART2, buf[i]);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    }

    /* 发送CRC */
    USART_SendData(USART2, crc & 0xFF);
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    USART_SendData(USART2, (crc >> 8) & 0xFF);
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}

/**
 * @brief 处理Modbus帧
 */
static void process_modbus_frame(void)
{
   
    uint8_t addr = rx_buf[0];
    uint8_t func = rx_buf[1];
    uint16_t reg_addr, reg_num, value;
    uint8_t tx_buf[256];
    uint8_t tx_len = 0;

    /* 检查地址 */
    if(addr != MODBUS_SLAVE_ADDR && addr != 0x00) {
   
        return;  // 不是本机地址
    }

    /* 检查CRC */
    uint16_t recv_crc = (rx_buf[rx_len-1] << 8) | rx_buf[rx_len-2];
    if(crc16(rx_buf, rx_len-2) != recv_crc) {
   
        return;  // CRC错误
    }

    /* 广播地址不响应 */
    if(addr == 0x00) {
   
        return;
    }

    /* 处理功能码 */
    switch(func) {
   
        /* 读保持寄存器 (0x03) */
        case 0x03:
            reg_addr = (rx_buf[2] << 8) | rx_buf[3];
            reg_num  = (rx_buf[4] << 8) | rx_buf[5];

            if(reg_addr >= REG_HOLDING_NUM || 
               (reg_addr + reg_num) > REG_HOLDING_NUM) {
   
                // 返回异常
                tx_buf[0] = addr;
                tx_buf[1] = func | 0x80;
                tx_buf[2] = 0x02;  // 非法地址
                tx_len = 3;
                break;
            }

            tx_buf[0] = addr;
            tx_buf[1] = func;
            tx_buf[2] = reg_num * 2;  // 字节数
            tx_len = 3;

            for(uint16_t i=0; i<reg_num; i++) {
   
                tx_buf[tx_len++] = (holding_regs[reg_addr+i] >> 8) & 0xFF;
                tx_buf[tx_len++] = holding_regs[reg_addr+i] & 0xFF;
            }
            break;

        /* 写单个寄存器 (0x06) */
        case 0x06:
            reg_addr = (rx_buf[2] << 8) | rx_buf[3];
            value = (rx_buf[4] << 8) | rx_buf[5];

            if(reg_addr >= REG_HOLDING_NUM) {
   
                // 返回异常
                tx_buf[0] = addr;
                tx_buf[1] = func | 0x80;
                tx_buf[2] = 0x02;  // 非法地址
                tx_len = 3;
                break;
            }

            holding_regs[reg_addr] = value;

            // 回显请求
            memcpy(tx_buf, rx_buf, rx_len-2);
            tx_len = rx_len-2;
            break;

        /* 写多个寄存器 (0x10) */
        case 0x10:
            reg_addr = (rx_buf[2] << 8) | rx_buf[3];
            reg_num = (rx_buf[4] << 8) | rx_buf[5];
            uint8_t byte_count = rx_buf[6];

            if(reg_addr >= REG_HOLDING_NUM || 
               (reg_addr + reg_num) > REG_HOLDING_NUM ||
               byte_count != reg_num * 2) {
   
                // 返回异常
                tx_buf[0] = addr;
                tx_buf[1] = func | 0x80;
                tx_buf[2] = 0x02;  // 非法地址
                tx_len = 3;
                break;
            }

            // 写入数据
            uint8_t idx = 7;
            for(uint16_t i=0; i<reg_num; i++) {
   
                holding_regs[reg_addr+i] = (rx_buf[idx] << 8) | rx_buf[idx+1];
                idx += 2;
            }

            // 回显请求的前6个字节
            memcpy(tx_buf, rx_buf, 6);
            tx_len = 6;
            break;

        default:
            // 不支持的功能码
            tx_buf[0] = addr;
            tx_buf[1] = func | 0x80;
            tx_buf[2] = 0x01;  // 非法功能
            tx_len = 3;
            break;
    }

    /* 发送响应 */
    if(tx_len > 0) {
   
        send_response(tx_buf, tx_len);
    }
}

/**
 * @brief USART2中断处理函数
 */
void USART2_IRQHandler(void)
{
   
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
   
        uint8_t data = USART_ReceiveData(USART2);

        if(rx_len < sizeof(rx_buf)) {
   
            rx_buf[rx_len++] = data;
        }

        // 简单超时检测(实际应用中应使用定时器)
        static uint32_t last_time = 0;
        uint32_t now = SysTick->VAL;

        if(now - last_time > 1000) {
     // 简单超时判断
            frame_complete = 1;
        }
        last_time = now;

        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    }
}

/**
 * @brief 主循环调用,处理Modbus帧
 */
void Modbus_Poll(void)
{
   
    if(frame_complete && rx_len > 0) {
   
        process_modbus_frame();
        rx_len = 0;
        frame_complete = 0;
    }
}

/**
 * @brief 写保持寄存器
 * @param addr 寄存器地址
 * @param value 值
 */
void Modbus_WriteReg(uint16_t addr, uint16_t value)
{
   
    if(addr < REG_HOLDING_NUM) {
   
        holding_regs[addr] = value;
    }
}

/**
 * @brief 读保持寄存器
 * @param addr 寄存器地址
 * @return 寄存器值
 */
uint16_t Modbus_ReadReg(uint16_t addr)
{
   
    if(addr < REG_HOLDING_NUM) {
   
        return holding_regs[addr];
    }
    return 0;
}

main.c

#include "stm32f10x.h"
#include "modbus_slave.h"
#include <stdio.h>

/* 系统时钟配置 */
void SystemClock_Init(void)
{
   
    RCC_DeInit();
    RCC_HSEConfig(RCC_HSE_ON);
    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    RCC_PLLCmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    while(RCC_GetSYSCLKSource() != 0x08);

    SystemCoreClockUpdate();
}

/* 延时函数 */
void Delay_ms(uint32_t ms)
{
   
    for(uint32_t i=0; i<ms*8000; i++);
}

int main(void)
{
   
    /* 初始化系统 */
    SystemClock_Init();

    /* 初始化Modbus */
    Modbus_Init();

    /* 初始化寄存器示例值 */
    Modbus_WriteReg(0, 1234);   // 寄存器0
    Modbus_WriteReg(1, 5678);   // 寄存器1
    Modbus_WriteReg(2, 100);    // 寄存器2

    while(1)
    {
   
        /* 处理Modbus请求 */
        Modbus_Poll();

        /* 更新寄存器值(示例:模拟传感器数据) */
        static uint32_t counter = 0;
        if(++counter >= 1000) {
   
            counter = 0;
            uint16_t temp = Modbus_ReadReg(2);
            Modbus_WriteReg(2, temp + 1);  // 温度递增
        }

        Delay_ms(1);
    }
}

二、使用CubeMX生成的Modbus程序(HAL库版)

如果你使用STM32CubeMX生成代码,这是更现代的方式:

modbus.c (HAL库版本)

/* modbus.c - HAL库版本 */
#include "modbus.h"
#include <string.h>

#define MODBUS_ADDR     0x01
#define REG_COUNT       20

static uint16_t holding_regs[REG_COUNT] = {
   0};
static uint8_t rx_buffer[256];
static uint8_t rx_index = 0;
static uint32_t last_rx_time = 0;

/* CRC16计算 */
uint16_t Modbus_CRC16(uint8_t *data, uint16_t length)
{
   
    uint16_t crc = 0xFFFF;
    for(uint16_t i=0; i<length; i++) {
   
        crc ^= data[i];
        for(uint8_t j=0; j<8; j++) {
   
            if(crc & 0x0001) {
   
                crc >>= 1;
                crc ^= 0xA001;
            } else {
   
                crc >>= 1;
            }
        }
    }
    return crc;
}

/* 发送响应 */
void Modbus_SendResponse(uint8_t *data, uint16_t length)
{
   
    uint16_t crc = Modbus_CRC16(data, length);
    HAL_UART_Transmit(&huart2, data, length, 100);
    HAL_UART_Transmit(&huart2, (uint8_t*)&crc, 2, 100);
}

/* 处理Modbus请求 */
void Modbus_ProcessFrame(uint8_t *frame, uint16_t length)
{
   
    if(length < 4) return;

    uint8_t addr = frame[0];
    uint8_t func = frame[1];

    if(addr != MODBUS_ADDR && addr != 0x00) return;

    /* 检查CRC */
    uint16_t recv_crc = (frame[length-1] << 8) | frame[length-2];
    if(Modbus_CRC16(frame, length-2) != recv_crc) return;

    uint8_t tx_buffer[256];
    uint16_t tx_length = 0;

    switch(func) {
   
        case 0x03:  // 读保持寄存器
            {
   
                uint16_t start_addr = (frame[2] << 8) | frame[3];
                uint16_t reg_count = (frame[4] << 8) | frame[5];

                tx_buffer[0] = MODBUS_ADDR;
                tx_buffer[1] = 0x03;
                tx_buffer[2] = reg_count * 2;
                tx_length = 3;

                for(uint16_t i=0; i<reg_count; i++) {
   
                    if(start_addr + i < REG_COUNT) {
   
                        tx_buffer[tx_length++] = (holding_regs[start_addr+i] >> 8) & 0xFF;
                        tx_buffer[tx_length++] = holding_regs[start_addr+i] & 0xFF;
                    }
                }

                Modbus_SendResponse(tx_buffer, tx_length);
            }
            break;

        case 0x06:  // 写单个寄存器
            {
   
                uint16_t reg_addr = (frame[2] << 8) | frame[3];
                uint16_t reg_value = (frame[4] << 8) | frame[5];

                if(reg_addr < REG_COUNT) {
   
                    holding_regs[reg_addr] = reg_value;
                }

                // 回显
                memcpy(tx_buffer, frame, length-2);
                tx_length = length-2;
                Modbus_SendResponse(tx_buffer, tx_length);
            }
            break;
    }
}

/* UART接收完成回调 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
   
    if(huart->Instance == USART2) {
   
        uint32_t now = HAL_GetTick();

        if(now - last_rx_time > 5) {
     // 5ms超时
            rx_index = 0;
        }

        if(rx_index < sizeof(rx_buffer)) {
   
            rx_buffer[rx_index++] = huart->pRxBuffPtr[0];
        }

        last_rx_time = now;

        // 重新启动接收
        HAL_UART_Receive_IT(&huart2, huart->pRxBuffPtr, 1);
    }
}

/* Modbus轮询 */
void Modbus_Poll(void)
{
   
    uint32_t now = HAL_GetTick();

    if(rx_index > 0 && (now - last_rx_time) > 10) {
     // 10ms帧间隔
        Modbus_ProcessFrame(rx_buffer, rx_index);
        rx_index = 0;
    }
}

main.c (HAL库版本)

/* main.c - HAL库版本 */
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "modbus.h"

void SystemClock_Config(void);

int main(void)
{
   
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART2_UART_Init();

    /* 启动UART接收中断 */
    uint8_t rx_byte;
    HAL_UART_Receive_IT(&huart2, &rx_byte, 1);

    /* 初始化寄存器 */
    holding_regs[0] = 1000;
    holding_regs[1] = 2000;
    holding_regs[2] = 3000;

    while(1) {
   
        Modbus_Poll();
        HAL_Delay(1);
    }
}

三、Modbus测试工具

1. 使用Modbus Poll测试

连接设置:
- 连接:Serial Port
- 串口:COM3 (根据你的实际端口)
- 波特率:9600
- 数据位:8
- 校验:None
- 停止位:1
- 模式:RTU

测试命令:
1. 读取保持寄存器:
   从站地址:1
   功能码:03
   起始地址:0
   数量:10

2. 写入单个寄存器:
   从站地址:1
   功能码:06
   寄存器地址:0
   值:1234

2. Python测试脚本

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
STM32 Modbus从站测试脚本
"""

import serial
import time
import struct

class ModbusTest:
    def __init__(self, port='COM3', baudrate=9600):
        self.ser = serial.Serial(
            port=port,
            baudrate=baudrate,
            bytesize=8,
            parity='N',
            stopbits=1,
            timeout=1
        )

    def crc16(self, data):
        """计算CRC16"""
        crc = 0xFFFF
        for byte in data:
            crc ^= byte
            for _ in range(8):
                if crc & 0x0001:
                    crc >>= 1
                    crc ^= 0xA001
                else:
                    crc >>= 1
        return crc.to_bytes(2, 'little')

    def read_holding_registers(self, slave_addr, start_addr, count):
        """读取保持寄存器"""
        # 构建请求帧
        frame = bytes([
            slave_addr,      # 从站地址
            0x03,            # 功能码
            start_addr >> 8, # 起始地址高字节
            start_addr & 0xFF, # 起始地址低字节
            count >> 8,      # 寄存器数量高字节
            count & 0xFF     # 寄存器数量低字节
        ])

        # 添加CRC
        frame += self.crc16(frame)

        # 发送请求
        self.ser.write(frame)
        time.sleep(0.1)

        # 读取响应
        response = self.ser.read(5 + count*2)
        return response

    def write_single_register(self, slave_addr, reg_addr, value):
        """写入单个寄存器"""
        frame = bytes([
            slave_addr,
            0x06,
            reg_addr >> 8,
            reg_addr & 0xFF,
            value >> 8,
            value & 0xFF
        ])

        frame += self.crc16(frame)
        self.ser.write(frame)
        time.sleep(0.1)
        return self.ser.read(8)

    def test(self):
        """测试函数"""
        print("开始Modbus测试...")

        # 测试1:读取寄存器
        print("测试1:读取保持寄存器")
        response = self.read_holding_registers(0x01, 0, 3)
        print(f"响应: {response.hex()}")

        # 测试2:写入寄存器
        print("\n测试2:写入寄存器")
        response = self.write_single_register(0x01, 0, 9999)
        print(f"响应: {response.hex()}")

        # 测试3:再次读取
        print("\n测试3:再次读取")
        response = self.read_holding_registers(0x01, 0, 1)
        print(f"响应: {response.hex()}")

        self.ser.close()

if __name__ == "__main__":
    tester = ModbusTest(port='COM3', baudrate=9600)
    tester.test()

参考代码 stm32-modbus协议程序 www.youwenfan.com/contentali/71977.html

四、常见问题解决

1. 通信不稳定

// 在USART初始化中添加:
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

// 确保正确配置GPIO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // RX

2. CRC计算错误

// 验证CRC计算
uint8_t test_data[] = {
   0x01, 0x03, 0x00, 0x00, 0x00, 0x01};
uint16_t crc = crc16(test_data, 6);
// 正确的CRC应该是:0x840A

3. 帧间隔检测

// 使用定时器精确检测3.5个字符时间
// 9600bps时,3.5个字符 ≈ 3.5ms
void TIM3_IRQHandler(void)
{
   
    if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
   
        frame_complete = 1;  // 帧结束
        TIM_Cmd(TIM3, DISABLE);
    }
}

五、扩展功能

1. 添加更多功能码

case 0x01:  // 读线圈
case 0x02:  // 读离散输入
case 0x04:  // 读输入寄存器
case 0x05:  // 写单个线圈
case 0x0F:  // 写多个线圈
case 0x10:  // 写多个寄存器

2. 添加异常处理

#define MODBUS_EXCEPTION_ILLEGAL_FUNCTION  0x01
#define MODBUS_EXCEPTION_ILLEGAL_ADDRESS   0x02
#define MODBUS_EXCEPTION_ILLEGAL_VALUE     0x03
#define MODBUS_EXCEPTION_SLAVE_FAILURE     0x04

3. 添加寄存器映射表

typedef struct {
   
    uint16_t addr;
    uint16_t value;
    uint8_t  access;  // 0:只读, 1:读写
} REGISTER_MAP;

REGISTER_MAP reg_map[] = {
   
    {
   0x0000, 0x1234, 1},  // 可读写
    {
   0x0001, 0x5678, 0},  // 只读
    // ...
};

这个精简版Modbus程序可以直接在你的STM32F103上运行,支持最常用的03和06功能码。

目录
相关文章
|
5天前
|
缓存 测试技术 API
Qwen 3.7 Plus 与 Max 实测:性价比与多模态能力差异解析(2026)
2026 年 6 月 1 日,阿里悄无声息地发布了 Qwen 3.7 Plus,距 Qwen 3.7 Max 上线刚好 11 天。同样的 1M 上下文,同样的 35 小时自治上限。但价格才是头条:Plus 是 0.40/M输入,Max是 2.50/M——便宜约 6 倍——并且还能看图、看视频。Vision Arena 上 Plus 已经排到 #16。所以这周真正值得讨论的问题不是”要不要为视觉能力买单”,而是”Max 凭什么用 6 倍价格换来 2 个百分点的 benchmark 领先”。
|
6天前
|
JavaScript 定位技术 API
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
CodeGraph 是一款爆火的本地代码智能工具,通过 tree-sitter 解析 AST 构建结构化知识图谱(存于 SQLite),为编程 Agent 提前生成“代码地图”。它显著降低 Agent 在中大型项目中的探索成本——实测工具调用减少71%、Token 降57%、速度提升46%,支持19+语言及主流框架路由识别,完全离线、无需 API Key。
707 6
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
|
6天前
|
人工智能 自然语言处理 文字识别
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
Qwen3.7-Max是阿里云百炼面向智能体时代推出的新一代旗舰模型,对标GPT-5.5、Claude Opus 4.7等闭源旗舰。该模型支持百万级token上下文窗口,具备顶级推理能力、多模态搜索与视觉理解增强、流式输出低延迟响应等核心优势,覆盖编程、办公、长周期自主执行等复杂场景。同时支持OpenAI接口兼容,便于系统快速迁移。用户可通过Token Plan团队或节省计划等订阅方式灵活调用,适合企业级高要求场景使用。
8732 37
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
|
6天前
|
人工智能 运维 JavaScript
阿里云Qoder CN(原通义灵码)全解析 产品形态、版本划分与技术适配说明
在AI辅助开发与智能办公工具持续普及的当下,阿里云旗下原通义灵码正式更名为Qoder CN,同时延伸出QoderWork CN、Qoder CN CLI、Qoder CN Mobile等多款配套产品,形成覆盖代码开发、日常办公、终端交互、移动端使用的完整工具矩阵。Qoder CN核心定位为AI智能编码助手,深度适配主流代码编辑器、集成开发环境以及终端场景;QoderWork CN则偏向桌面端综合办公辅助,二者面向不同使用场景,划分了多个版本档位,搭配差异化资源配额、功能权限与计费规则,同时兼容多款主流大模型。
694 5
|
6天前
|
存储 安全 Java
AgentScope Java 2.0:打造分布式、企业级智能体底座
AgentScope 2.0 面向分布式部署、稳定运行、权限安全等企业级需求全面升级,打造支持多租户隔离与长期稳定运行的企业级智能体底座。
|
6天前
|
数据采集 人工智能 前端开发
让 Coding Agent 从黑盒到透明:阿里云 Agent 观测审计数据采集实践
AI Agent 规模化落地带来执行黑盒、行为难追溯、成本难度量三大难题。阿里云基于 OTel 标准,面向 Coding Agent、个人通用助理和框架型 Agent,推出 LoongSuite Pilot、插件及探针等无侵入采集方案,让 Agent 实现可看见、可分析、可审计、可治理。
745 148
|
6天前
|
人工智能 运维 自然语言处理
阿里云百炼Qwen3.7-Max模型详解:综合能力、核心优势与订阅计划参考指南
2026年,大模型技术持续向通用化、高性能、场景化方向迭代,阿里云百炼作为一站式大模型服务平台,持续推出迭代升级的模型产品,Qwen3.7-Max便是当前主力旗舰级大模型之一。该模型依托深度优化的底层架构与大规模训练数据,在文本理解、逻辑推理、多模态交互、代码生成、长文本处理等多个维度实现能力升级,同时搭配灵活的订阅计划体系,能够适配个人开发者、中小企业、大型企业、政企机构等不同类型用户的使用需求。
583 2
|
6天前
|
JSON 缓存 安全
通过 CC Switch 本地路由让 Codex CLI 接入 DeepSeek 等第三方模型
CC Switch 通过本地路由(`127.0.0.1:15721`)实现协议转换:将 Codex 的 Responses API 请求自动映射为 DeepSeek 等厂商的 Chat Completions 接口,兼容流式响应与工具调用,无需修改 Codex 源码,安全隔离 API Key。(239字)
1769 3
通过 CC Switch 本地路由让 Codex CLI 接入 DeepSeek 等第三方模型
|
6天前
|
人工智能 缓存 自然语言处理
阿里Qwen3.7-Max评测:Agent能力显著提升,耗时与调用成本大幅下降
阿里云百炼推出面向智能体的旗舰大模型Qwen3.7-Max,具备长周期自主执行能力,显著提升编程、办公自动化等复杂任务处理水平;支持MCP集成与多框架兼容,并以限时5折+100万Tokens免费试用大幅降低使用门槛,助力企业高效落地AI应用。在阿里云百炼平台快速体验:https://t.aliyun.com/U/fPVHqY
1972 10
|
6天前
|
人工智能 运维 API
2026年阿里云百炼通义千问Qwen3.7-plus深度介绍 功能特性、使用优势及618大促订阅方案指南
大模型技术的普及,让AI能力逐步融入个人办公、内容创作、代码编写、企业运营、教育培训等各类场景。不同定位的模型对应不同使用需求,旗舰级模型性能强劲但使用成本偏高,轻量化模型价格低廉却难以胜任复杂任务,而介于两者之间的中端主力模型,凭借均衡的能力、亲民的定价、广泛的场景适配性,成为绝大多数个人用户、小型团队、中小企业的首选。
799 1