温室监控下位机部分

用的是51普中开发板

功能主要就是接收串口发送过来的信息,

然后根据接收到的信息执行不同的操作,

上位机部分链接:http://t.csdn.cn/evEle

先附上源码链接:(3条消息) 【免费】c#上位机(温室监控系统源码)资源-CSDN文库

通信协议采用modbusRTU

为了能方便的处理数据,在代码中把用到的管脚全都映射到数组上

本文主要介绍了一个用于温室监控系统的代码。该代码使用了多个库文件,包括"Delay.h"、"UART.h"、"DS18B20.h"、"Tool.h"和"Buzzer.h"等等。在代码中定义了一些函数和变量,用于处理Modbus通信、读写线圈和寄存器等操作。

代码解析

以下是代码中定义的一些重要函数和变量的解析:

  1. 函数

crc_cal_value:用于计算CRC校验值。

  1. 函数

ModbusCpu:用于处理接收到的Modbus报文。

  1. 函数

CoilMapper:将Coils数组中的数据映射到对应的GPIO口。

  1. 函数

writeCoils:用于写入线圈状态。

  1. 函数

readCoilsStatus:读取指定范围内的线圈状态。

  1. 函数

RegistersMapper:更新寄存器数据,包括读取温度和设置报警功能。

  1. 函数

TemperatureAlarmSetting:根据温度设置触发报警功能。

  1. 函数

resultKeepRegister:返回指定范围内的寄存器数据。

  1. 函数

SetSingleKeepRegister:设置单个寄存器的值。

  1. 函数

UART_Routine:串口中断处理程序,用于接收数据。

  1. 变量

SlaveAddr:Modbus从机的地址。

  1. 变量

Message:用于接收Modbus报文的数组。

  1. 变量

Coils:存储线圈状态的数组。

  1. 变量

Registers:存储寄存器数据的数组。

主函数

主函数中初始化了串口和温度传感器,并设定了报警温度的上限和下限。然后进入了一个死循环,在循环中调用了CoilMapper和RegistersMapper函数,实现了对线圈和寄存器的处理和更新。

#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
#include "DS18B20.h"
#include "Tool.h"
#include "Buzzer.h"
//*************************************************** 函数
unsigned int crc_cal_value(unsigned char* data_value, unsigned char data_length);
void ModbusCpu();
void CoilMapper();
void writeCoils(int CoilsAddr,int onoff);
void readCoilsStatu(int startAddr,int coilsCount);
void RegistersMapper();
void resultKeepRegister(int StartAddr,int RegisterDataPort);
void TemperatureAlarmSetting(int* T);
void SetSigleKeepRegister(int StartAddr,int Value);
//***************************************************
char SlaveAddr=0x01;
unsigned char Message[8]={0x01,0x03,0x00,0x00,0x00,0x01};//用于接收报文
int mesgIndex=0;
unsigned int CRC;

char Coils[32];//线圈
int Registers[4];//寄存器
void main()
{
     DS18B20_ConvertT();        //上电先转换一次温度,防止第一次读数据错误
     Delay(500);
   UART_Init();    //串口初始化
     
    Registers[1]=50;//报警温度上限
    Registers[2]=-40;//报警温度下限
    while(1)
    {
         CoilMapper();
         RegistersMapper();
    }
}

void ModbusCpu()//处理接收到的报文
{
        CRC=crc_cal_value(Message,sizeof(Message)-2);
        if(Message[6]==(unsigned char)CRC &&  Message[7]==(unsigned char)(CRC>>8))//验证CRC 验证接收到的数据是否正确
        {   
              int Count;
                int Addr=(Message[2]<<8);//
                Addr|=Message[3];
              Count=(Message[4]<<8);
                Count|=Message[5];
                switch(Message[1])//判断功能码
                {
                    case 0x05:writeCoils(Addr,Message[4]==0xFF?1:0);
                        break;
                    case 0x01:readCoilsStatu(Addr,Count);
                                break;
                    case 0x03:resultKeepRegister(Addr,Count);
                                break;
                        case 0x06:SetSigleKeepRegister(Addr,Count);//this Count is Value
                                break;
                }
        }
}


 void writeCoils(int CoilsAddr,int onoff)
 {
     if(CoilsAddr>=sizeof(Coils)||CoilsAddr<0)
         return;
     Coils[CoilsAddr]=onoff;
 }
void readCoilsStatu(int startAddr,int coilsCount)
{
     unsigned int crc;
   int datalen=((coilsCount/8)+(coilsCount%8>0?1:0));
     int retuleMsgLenth=3;
     unsigned char retuleMsg[sizeof(Coils)+3];
     char i=0;
     char temp=0x00;//表示一个字节的数据(表示8个线圈)
     char tempIndex=1;
     retuleMsg[0]=SlaveAddr;
     retuleMsg[1]=0x01;
     retuleMsg[2]=(char)datalen;
    
    
     for(i=startAddr;i<(startAddr+coilsCount);i++)
    {
         if(i>=sizeof(Coils))break;
         temp|=(Coils[i]<<tempIndex++);
         if(tempIndex>=9)
         {
             tempIndex=1;
             retuleMsg[retuleMsgLenth++]=temp;
         }
    }
    if(tempIndex!=1 && tempIndex<=8)
    {
         retuleMsg[retuleMsgLenth++]=temp;
    }
     crc =crc_cal_value(retuleMsg,retuleMsgLenth);
     retuleMsg[retuleMsgLenth++]=(unsigned char)crc;
     retuleMsg[retuleMsgLenth++]=(unsigned char)(crc>>8);
     SendMessage(retuleMsg,retuleMsgLenth);
}
void RegistersMapper()
{
     int T=0;
     DS18B20_ConvertT();    //转换温度
     T=DS18B20_ReadT();    //读取温度
   TemperatureAlarmSetting(&T);
     
     Registers[0]=T;
}
void TemperatureAlarmSetting(int* T)
{
     if(*T>Registers[1]||*T<Registers[2])
     {
           Buzzer_Time(100);
     }
}
 void resultKeepRegister(int StartAddr,int RegisterDataPort)
 {
      char i=0;
      unsigned int crc;
      unsigned char retuleMsg[sizeof(Registers)+3];
      char retuleMsgLenth=3;
      retuleMsg[0]=SlaveAddr;
      retuleMsg[1]=0x03;
      retuleMsg[2]=((char)RegisterDataPort)*2;
     
      for(i=StartAddr;i<(StartAddr+RegisterDataPort);i++)
      {
           if(i<0||i>=sizeof(Registers))break;
             retuleMsg[retuleMsgLenth++]=Registers[i]>>8;//高位
             retuleMsg[retuleMsgLenth++]=(Registers[i]<<8)>>8;//低位
      }
      crc =crc_cal_value(retuleMsg,retuleMsgLenth);
      retuleMsg[retuleMsgLenth++]=(unsigned char)crc;
      retuleMsg[retuleMsgLenth++]=(unsigned char)(crc>>8);
      SendMessage(retuleMsg,retuleMsgLenth);
 }
 void SetSigleKeepRegister(int StartAddr,int Value)
 {
      if(StartAddr<0||StartAddr>sizeof(Registers))return;
      Registers[StartAddr]=Value;
 }
void UART_Routine() interrupt 4
{
    if(RI==1)                    //如果接收标志位为1,接收到了数据
    {
          // P2=~SBUF;                //读取数据,取反后输出到LED
        if(mesgIndex>=8)return;
            Message[mesgIndex]=SBUF;//
          mesgIndex++;
            if(mesgIndex>=8)
            {
                mesgIndex=0;
                ModbusCpu();
            }
        RI=0;                    //接收标志位清0
    }
    
}
void CoilMapper()
{
   P0_0=Coils[0];
     P0_1=Coils[1];
     P0_2=Coils[2];
     P0_3=Coils[3];
     P0_4=Coils[4];
     P0_5=Coils[5];
     P0_6=Coils[6];
     P0_7=Coils[7];
    
     P1_0=Coils[8];
     P1_1=Coils[9];
     P1_2=Coils[10];
     P1_3=Coils[11];
     P1_4=Coils[12];
     P1_5=Coils[13];
     P1_6=Coils[14];
     P1_7=Coils[15];
    
     P2_0=Coils[16]==1?0:1;
     P2_1=Coils[17]==1?0:1;
     P2_2=Coils[18]==1?0:1;
     P2_3=Coils[19]==1?0:1;
     P2_4=Coils[20]==1?0:1;
     P2_5=Coils[21]==1?0:1;
     P2_6=Coils[22]==1?0:1;
     P2_7=Coils[23]==1?0:1;
     
}
 
  

总结

该代码实现了一个基本的温室监控系统,使用了Modbus通信协议,并通过GPIO口控制了线圈状态和读取了温度传感器数据。读取的数据进行相应的处理,如报警功能等。在主函数中将不断循环执行这些功能,实现了温室监控系统的基本功能。

以上是对给定代码的简要解析,希望对你有所帮助。如有任何疑问,请随时向我提问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 温室大棚监控的Qt界面是一种基于Qt开发的图形界面,用于实时监控和管理温室大棚的环境参数和作物生长情况。其主要功能包括数据采集、数据显示、报警信息提示、远程控制等。 通过温室大棚监控的Qt界面,用户可以实时查看温室内的温度、湿度、光照强度、二氧化碳浓度等环境参数,以及作物的生长情况。界面会将这些数据以直观的图表或表格形式展示,方便用户了解温室内的实时情况。 当环境参数超出设定范围时,监控界面会及时发出报警信息提示,提醒用户采取相应的措施。比如,当温度过高时,界面会发出警报声音,并在界面上以红色高亮显示。用户可以通过界面进行远程控制,例如调整温室内的温度、湿度等参数,或者开启关闭灯光、喷灌系统等设备。 此外,温室大棚监控的Qt界面还支持数据的记录和统计分析功能。用户可以对历史数据进行查看和分析,比如不同时段的温度变化趋势、湿度与作物生长的关系等。这些功能有助于用户更好地了解温室大棚的运行情况,优化管理策略,提升作物的产量和质量。 总之,温室大棚监控的Qt界面是一个功能强大、操作简便的工具,它能够提供全面的温室环境和作物生长信息,帮助用户实时监控、远程控制和数据分析,从而实现温室大棚的智能化管理。 ### 回答2: 温室大棚监控的Qt界面是一种基于Qt框架开发的图形用户界面,用于监测和管理温室大棚内的环境信息和设备状态。 该界面主要分为几个主要部分:实时数据显示区、历史数据查询区、设备状态控制区和报警信息提示区。 实时数据显示区主要展示温室大棚内的各项环境数据,包括温度、湿度、光照强度等,可以通过实时曲线图或者数字显示方式呈现。用户可以通过该区域的数据了解当前温室内的环境状况。 历史数据查询区可以用来查看温室大棚内过去一段时间内的环境数据。用户可以选择特定的时间范围和参数,在界面上显示出相应的历史数据曲线图或者数据表格。 设备状态控制区用于控制温室大棚内的各项设备,例如灯光、加热器、通风设备等。用户可以通过点击按钮或拖动滑块的方式进行相应设备的开关控制,以实现温室内环境的调节。 报警信息提示区用于显示温室大棚内的异常情况或报警信息。当监测到温度过高、湿度异常或其他重要参数超出设定范围时,界面会通过文字提示、声音警报或弹窗等方式向用户发出警告,并及时记录相关信息供用户查看。 总之,温室大棚监控的Qt界面通过直观的图形界面、实时数据显示、历史数据查询、设备控制和报警提示等功能,帮助用户全面了解和管理温室大棚的环境情况,提高温室作物的生长效益和保证温室的安全运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值