组态王与STM32F103VET6单片机Modbus协议通讯+三菱协议通讯源码组态王软件
搞工控的老铁们应该都体验过组态王和单片机配合干活有多酸爽。今天咱们就拿STM32F103VET6这个经典款来说说怎么玩转双协议通讯。别被Modbus和三菱协议吓到,其实底层套路都差不多,关键得摸准寄存器配置的脉门。
先上硬菜------Modbus RTU通讯的干货代码。重点看串口3的配置,这个片子自带硬件收发控制就是香:
c
// 串口3初始化
USART_InitTypeDef USART_InitStruct;
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_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStruct);
// 重点配置DE控制引脚
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
这段配置里藏着三个易错点:波特率必须与组态王完全一致、GPIO复用模式必须设对、收发切换时序要配合定时器。实测发现用TIM4做超时判断最稳,500us触发一次中断刚好卡住数据帧间隙。

组态王与STM32F103VET6单片机Modbus协议通讯+三菱协议通讯源码组态王软件
再说说三菱协议这个磨人的小妖精。和Modbus最大的区别在于数据格式------它用的是ASCII码明文传输,帧头帧尾带特定字符。咱们得在中断服务程序里做状态机解析:
c
void USART3_IRQHandler(void) {
static uint8_t rx_buffer[20], state=0;
if(USART_GetITStatus(USART3, USART_IT_RXNE)) {
uint8_t ch = USART_ReceiveData(USART3);
switch(state) {
case 0: // 等待起始符
if(ch == ':') state++;
break;
case 1: // 接收数据区
if(ch == '\r') {
process_melsec_cmd(rx_buffer);
state = 0;
} else {
rx_buffer[i++] = ch;
}
break;
}
}
}
这个状态机看似简单,实操时要特别注意两点:ASCII转HEX的处理必须用查表法(别手写转换逻辑,容易翻车),还有组态王那边的设备地址要和单片机的站号对应上。曾经有个兄弟调了两天发现是地址设成了16进制,血泪教训啊!
最后给个双协议共存的配置秘诀:用不同寄存器地址段区分协议类型。比如Modbus用4xxxx保持寄存器,三菱用D寄存器区,这样在数据解析层就能自动分流。源码包里有个protocol_router.c文件就是干这个的,核心逻辑就下面这几行:
c
if(reg_addr >= 0x4000) {
handle_modbus_request(frame);
} else if(reg_addr >= 0xD000) {
handle_melsec_request(frame);
} else {
send_error_code(ILLEGAL_DATA_ADDRESS);
}
实测这种方案比用不同串口省资源,F103的RAM刚好够用。调试时记得先拿Modbus Poll和三菱的GX Works2分别测试,再用组态王联调,能避开八成以上的玄学问题。

源码包里的工程文件已经验证过读写保持寄存器、开关量控制等常用功能。注意烧录前改下工程里的晶振配置(默认是8MHz外部晶振),不然波特率对不上可就扑街了。完整代码在GitHub的stm32-kingview-multi-protocol仓库,需要的老铁自取。