本帖最后由 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: USART2 TX-->A.2 RX-->A.3
- AIR: USART3 TX-->B.10 RX-->B.11
- OLED: CLK-->A.4 SDA-->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[MB_PDU_FUNC_OFF];
- eException = MB_EX_ILLEGAL_FUNCTION;
- /* 遍历所有支持的功能码 */
- for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) {
- if( xFuncHandlers[i].ucFunctionCode == 0 ) {
- break;
- } else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) {
- /*调用相关处理函数*/
- eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
- break;
- }
- }
- /*不是广播*/
- if(ucRcvAddress != MB_ADDRESS_BROADCAST) {
- /*异常*/
- if( eException != MB_EX_NONE ) {
- usLength = 0;
- ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
- ucMBFrame[usLength++] = 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[Rey_Ctl_Pos]);
- break;
- case 0x1002:
- Air_1002_Reg(usRegHoldingBuf[INT_LRN_Pos]);
- break;
- case 0x1003:
- Air_1003_Reg(usRegHoldingBuf[OUT_LRN_Pos]);
- break;
- case 0x1004:
- Air_1004_Reg(usRegHoldingBuf[Air_Mod_Pos]);
- break;
- case 0x1005:
- Air_1005_Reg(usRegHoldingBuf[Fan_Spd_Pos]);
- break;
- case 0x1006:
- Air_1006_Reg(usRegHoldingBuf[Fan_Dir_Pos]);
- break;
- case 0x1007:
- Air_1007_Reg(usRegHoldingBuf[Air_Tim_Pos]);
- 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[1]){
- 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[1]){
- 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 需要的自己下载。
|