CH32V307 ModbusTCP&RTU物联网型智能空调控制器
本帖最后由 forgot 于 2023-2-27 14:20 编辑#申请原创# CH32V307 ModbusTCP&RTU物联网型智能空调控制器创新设计
实现功能:1、该方案是通过以外网络TCP和串行总线两种方式分别以ModbusTCP和ModbusRTU的标准协议对CH32V307主板进行访问实现各类寄存器读写功能,包括线圈寄存器、离散输入寄存器、保持寄存器等;2、通过CH32V307主板进行modbus协议解析,通过串口对红外模块进行控制以实现空调进行学习、开机、关机、制热、制冷、除湿、风速、风量、定时等功能;3、OLED液晶会对系统进行信息展示,如灯光状态、空调状态等,远程管理主机以PC机上的MThings及modbuspoll来替代完成;
架构及外设组成:
环境搭建:
硬件组成:PC机:通过MThings及modbuspoll来模拟空调远程管理主机。CH32V307开发板:实现ModbusTCP_slave及ModbusRTU_slave的系统主要功能。红外自学习模块:实现学习空调红外指令,并可以通过指令地址完成进行相关指令发送。OLED液晶:显示系统工作状态及空调当前状态。LED灯:对应寄存器0x1001灯光控制
软件说明:以CH32V307开发主板为系统核心,基于Peripheral库和NetLib,通过WCHNET库与TIM2实现TCP Client功能,采用free modbus协议栈实现ModbusTCP读写功能;通过USART标准库与TIM3实现串口2通讯,采用中断的方式,以TIM3实现串口全帧检测,采用free modbus协议栈实现ModbusRTU读写功能;通过USART标准库实现串口3对红外学习模块控制指令发送;通过GPIO模拟时序,实现OLED信息显示。串口1作为打印口实现调试打印功能。通过GPIO基本控制,实现LED灯光控制。
主要功能函数说明:main函数://MB_RTU或者MB_TCP<font size="3" face="Arial">//MB_RTU或者MB_TCP
char Curr_Mod = MB_TCP;
/*********************************************************************
MOD:USART2TX-->A.2 RX-->A.3
AIR:USART3TX-->B.10RX-->B.11
OLED: CLK-->A.4SDA-->A.6
LED: A.0
*********************************************************************/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
LED_Configuration();
OLED_Configuration();
OLED_Init();
OLED_Poweron();
USART_AIR_Init(9600); //air空调发射器串口初始化->串口3
USART_Printf_Init(9600); //usart打印初始化->串口1
if (Curr_Mod == MB_RTU) {
eMBInit(MB_RTU, 0x01, 0, 9600, MB_PAR_NONE); //modbus_rtu初始化-> 串口2+定时器3
} else if(Curr_Mod == MB_TCP){
WCETH_Init(); //eth网卡初始化-> 网口+定时器2
eMBTCPInit(0); //modbus_tcp
}
eMBEnable();
while(1){
if (Curr_Mod == MB_TCP) {
WCHNET_MainTask();
}
eMBPoll();
AIR_Process();
OLED_Show();
}
}</font>
modbus协议eMBPoll函数:<font size="3" face="Arial">eMBErrorCode
eMBPoll( void )
{
static UCHAR *ucMBFrame;
static UCHAR ucRcvAddress;
static UCHAR ucFunctionCode;
static USHORT usLength;
static eMBException eException;
int i;
eMBErrorCode eStatus = MB_ENOERR;
eMBEventType eEvent;
/* 协议栈准备完成 */
if( eMBState != STATE_ENABLED ) {
return MB_EILLSTATE;
}
/* 获取事件 RTU采用发送消息事件,TCP采用xMBPortTCPPool轮询信号*/
if( xMBPortEventGet( &eEvent ) == TRUE ) {
/* 判断事件类型 */
switch ( eEvent ) {
case EV_READY:
break;
/* 接收完成事件 */
case EV_FRAME_RECEIVED:
/* modbus接收函数,获取地址、PDU指针、PDU长度 */
eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );//pdu:功能码+数据
if( eStatus == MB_ENOERR ) {
/* 判断地址是否吻合 */
if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) ) {
/* 发送执行事件 */
;
( void )xMBPortEventPost( EV_EXECUTE );
}
}else {
;
( void )xMBPortEventPost( EV_READY );
}
break;
/* 执行事件 */
case EV_EXECUTE:
/* 功能码 */
ucFunctionCode = ucMBFrame;
eException = MB_EX_ILLEGAL_FUNCTION;
/* 遍历所有支持的功能码 */
for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) {
if( xFuncHandlers.ucFunctionCode == 0 ) {
break;
} else if( xFuncHandlers.ucFunctionCode == ucFunctionCode ) {
/*调用相关处理函数*/
eException = xFuncHandlers.pxHandler( ucMBFrame, &usLength );
break;
}
}
/*不是广播*/
if(ucRcvAddress != MB_ADDRESS_BROADCAST) {
/*异常*/
if( eException != MB_EX_NONE ) {
usLength = 0;
ucMBFrame = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
ucMBFrame = eException;
}
if( ( eMBCurrentMode == MB_ASCII ) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ) {
vMBPortTimersDelay( MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS );
}
/*发送响应函数*/
eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
}
break;
case EV_FRAME_SENT:
break;
}
}
return MB_ENOERR;
}</font>
寄存器红外控制:<font size="3" face="Arial">void Air_Ctrl_Fun(uint16_t *cmd)
{
uint16_t reg = 0;//寄存器地址
reg = *cmd;
if(reg) {
switch(reg) {
case 0x1001:
Air_1001_Reg(usRegHoldingBuf);
break;
case 0x1002:
Air_1002_Reg(usRegHoldingBuf);
break;
case 0x1003:
Air_1003_Reg(usRegHoldingBuf);
break;
case 0x1004:
Air_1004_Reg(usRegHoldingBuf);
break;
case 0x1005:
Air_1005_Reg(usRegHoldingBuf);
break;
case 0x1006:
Air_1006_Reg(usRegHoldingBuf);
break;
case 0x1007:
Air_1007_Reg(usRegHoldingBuf);
break;
default:
break;
}
}
*cmd = 0;
}</font>
液晶显示:void OLED_Show(void)
{
FINE_STR(LAST_CMD);
if(need_show){
if (Curr_Mod == MB_RTU){
OLED_CLS();
OLED_ShowStr(0,0,(unsigned char*)"IoT Air CTRLer",2);
OLED_ShowStr(0,2,(unsigned char*)"Modbus-RTU",2);
if(usRegHoldingBuf){
OLED_ShowStr(0,4,(unsigned char*)"LED_STA:ON",2);
}else {
OLED_ShowStr(0,4,(unsigned char*)"LED_STA:OFF",2);
}
OLED_ShowStr(0,6,(unsigned char*)show_buff1,2);
}else if(Curr_Mod == MB_TCP){
OLED_CLS();
OLED_ShowStr(0,0,(unsigned char*)"IoT Air CTRLer",2);
OLED_ShowStr(0,2,(unsigned char*)"Modbus-TCP",2);
if(usRegHoldingBuf){
OLED_ShowStr(0,4,(unsigned char*)"LED_STA:ON",2);
}else {
OLED_ShowStr(0,4,(unsigned char*)"LED_STA:OFF",2);
}
OLED_ShowStr(0,6,(unsigned char*)show_buff1,2);
}
need_show = 0;
}
}
寄存器地址分布说明:0x1001:灯光控制;0x1002:进入学习;0x1003:退出学习;0x1004:各类模式控制;0x1005:各类风速控制;0x1006:各类风向控制;0x1007:各类定时控制;
RTU配置并连接:
TCP配置并连接:
连接成功:
制冷25°:
视频以动图代替:开机:
制冷:
gitee代码托管:
https://gitee.com/fankas-dream/forgot-gitee.git 需要的自己下载。
modbus RTU主要作用是什么? ModbusTCP是一种基于Modbus协议的通信方式,它使用TCP/IP协议作为传输层,可以实现在不同设备之间进行数据通信和控制。 CH32V307单片机作为下位机如何实现modbus通讯 相比于传统的串口Modbus协议,ModbusTCP具有传输速度快、可靠性高、距离远等优点,在现代工业控制系统中被广泛采用。 ModbusRTU通信,怎么设置通道? modbus tcp 比modbus rtu 速度快吗 如何移植UPNP协议到stm32 modbus tcp和modbus rtu的区别是什么? Modbus-rtu,用什么工具调试,如何调试 modbus RTU和modbus TCP能同时使用么 claretttt 发表于 2023-6-14 09:51
modbus RTU和modbus TCP能同时使用么
可以同时用,要看怎么设计好{:smile:}{:smile:}{:smile:} modbus接收的数据怎么处理 Modbus RTU最大通信速率有多少? robertesth 发表于 2023-6-14 10:42
modbus接收的数据怎么处理
按照寄存器读写方式进行数据获取,实现自己读取数据的目的 abotomson 发表于 2023-6-14 10:48
Modbus RTU最大通信速率有多少?
实际使用上,一般以9600BPS8E1为多,这也是MODBUS RTU建议的默认出厂设置值,另外还有默认19200的,但再高也只有允许设置到115200的,再高就没有见过了。实际上115200的速率,通讯距离会大大的缩短,可靠性也会有所下降。 modbus从站地址怎么设? ingramward 发表于 2023-6-14 11:26
modbus从站地址怎么设?
在配置modbus的参数的时候设置,如果是TCP那就是IP地址 CH32V307 怎么支持RS485接口和MODBUS通信协议 pentruman 发表于 2023-6-14 11:53
CH32V307 怎么支持RS485接口和MODBUS通信协议
硬件上通过串口接到RS485驱动芯片,软件部分加上freemodbus协议栈,轻松实现