沥沥小鱼 2024-02-19 22:04 采纳率: 45.5%
浏览 12
已结题

(标签-51单片机|关键词-main)温度报警器

题目:温度监测系统
利用51单片机,通过红外遥控器,DS18B20温度传感器(单片机自带),LCD1602显示屏,做一个温度监测系统
(1)通过红外遥控,能够设置温度阚值和电机转速
(2)能够在LCD1602显示屏上显示实时温度和电机转速
(3)温度超出值时蜂鸣器报警,电机转动 ,电机转速使用PWM波实现
(4)温度低于闯值时解除报警,电机停止
现在遇到的问题是:
1.达到温度上线阈值之后LCD显示屏冻结
2.直流电机不转
3.按下红外遥控按钮不能改变转速和阈值大小
这是main函数

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
#include "Buzzer.h"
#include "AT24C02.h"
#include "motor.h"//不可变速模块
#include "DS18B20.h"
#include "Timer0.h"
#include "OneWire.h"
#include "I2C.h"
#include "Int0.h"
#include "Motor one.h"//可变速模块
 Motor_Init();
 void Motor_SetSpeed(unsigned char Speed);
float T,TShow;
char TLow,THigh;
unsigned char KeyNum;
unsigned char Address;
unsigned char Command;
unsigned char Speed;
void main()
{
    IR_Init();
      LCD_Init();
      OneWire_Init();
    DS18B20_ConvertT(); 
      Motor_Init();
      Delay(1000);            //等待转换完成
    THigh=AT24C02_ReadByte(0);    //读取温度阈值数据
    TLow=AT24C02_ReadByte(1);
      if(THigh>125 || TLow<-55 || THigh<=TLow)
       {
            THigh=25;            //如果阈值非法,则设为默认值
            TLow=15;
       }
    while(1)
    {
                 DS18B20_ConvertT();    //转换温度
                     Delay(1);
           T=DS18B20_ReadT();    //读取温度
           if(T<0)                //如果温度小于0
           {
              LCD_ShowChar(1,3,'-');    //显示负号
              TShow=-T;        //将温度变为正数
           }
           else                //如果温度大于等于0
           {
              TShow=T;
           }
                     LCD_ShowString(1,1,"T:");
           LCD_ShowNum(1,3,TShow,3);        //显示温度整数部分
           LCD_ShowChar(1,6,'.');        //显示小数点
           LCD_ShowNum(1,7,(unsigned long)(TShow*100)%100,2);//显示温度小数部分
              if(IR_GetDataFlag() || IR_GetRepeatFlag())    //如果收到数据帧或者收到连发帧
        {
            Address=IR_GetAddress();        //获取遥控器地址码
            Command=IR_GetCommand();        //获取遥控器命令码
            /*温度读取及显示*/
           
            if(Command==IR_VOL_MINUS)        //如果遥控器VOL-按键按下
            {
                    THigh++;                
            }
            if(Command==IR_VOL_ADD)            //如果遥控器VOL+按键按下
            {
                    THigh--;        
            }
            if(Command==IR_POWER)
            {
                TLow++;
            }
            if(Command==IR_MODE)
            {
                  TLow--;
            }
                        //因为题目要求红外遥控还要控制电机速度
                        if(Command==IR_0){Motor_SetSpeed(0);Speed=0;}        //根据遥控器命令码设置速度
                  if(Command==IR_1){Motor_SetSpeed(50);Speed=1;}
                  if(Command==IR_2){Motor_SetSpeed(75);Speed=2;}
                  if(Command==IR_3){Motor_SetSpeed(100);Speed=3;}
              
                }
             LCD_ShowString(2,1,"TH:");
         LCD_ShowString(2,9,"TL:");
         LCD_ShowSignedNum(2,4,THigh,3);
         LCD_ShowSignedNum(2,12,TLow,3);
                 LCD_ShowSignedNum(1,11,Speed,1);   //LCD显示速度
            AT24C02_WriteByte(0,THigh);     //写入到At24C02中保存
            Delay(5);
            AT24C02_WriteByte(1,TLow);
            Delay(5);
        if(T>THigh)            //如果高出阈值
        {
                      motor();   //直流电机运转(不同与Motor one,这个不可变速)
            while(1)
                        {
                            Buzzer_Time(10000);
                            DS18B20_ConvertT();    //转换温度
                        Delay(1);
              T=DS18B20_ReadT(); 
                        }//蜂鸣器报警
                }
        
     }
        }


这是红外遥控函数有关函数


#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_Time;
unsigned char IR_State;

unsigned char IR_Data[4];
unsigned char IR_pData;

unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;

/**
  * @brief  红外遥控初始化
  * @param  无
  * @retval 无
  */
void IR_Init(void)
{
    Timer0_Init();
    Int0_Init();
}

/**
  * @brief  红外遥控获取收到数据帧标志位
  * @param  无
  * @retval 是否收到数据帧,1为收到,0为未收到
  */
unsigned char IR_GetDataFlag(void)
{
    if(IR_DataFlag)
    {
        IR_DataFlag=0;
        return 1;
    }
    return 0;
}

/**
  * @brief  红外遥控获取收到连发帧标志位
  * @param  无
  * @retval 是否收到连发帧,1为收到,0为未收到
  */
unsigned char IR_GetRepeatFlag(void)
{
    if(IR_RepeatFlag)
    {
        IR_RepeatFlag=0;
        return 1;
    }
    return 0;
}

/**
  * @brief  红外遥控获取收到的地址数据
  * @param  无
  * @retval 收到的地址数据
  */
unsigned char IR_GetAddress(void)
{
    return IR_Address;
}

/**
  * @brief  红外遥控获取收到的命令数据
  * @param  无
  * @retval 收到的命令数据
  */
unsigned char IR_GetCommand(void)
{
    return IR_Command;
}

//外部中断0中断函数,下降沿触发执行
void Int0_Routine(void) interrupt 0
{
    if(IR_State==0)                //状态0,空闲状态
    {
        Timer0_SetCounter(0);    //定时计数器清0
        Timer0_Run(1);            //定时器启动
        IR_State=1;                //置状态为1
    }
    else if(IR_State==1)        //状态1,等待Start信号或Repeat信号
    {
        IR_Time=Timer0_GetCounter();    //获取上一次中断到此次中断的时间
        Timer0_SetCounter(0);    //定时计数器清0
        //如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)
        if(IR_Time>13500-500 && IR_Time<13500+500)
        {
            IR_State=2;            //置状态为2
        }
        //如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)
        else if(IR_Time>11250-500 && IR_Time<11250+500)
        {
            IR_RepeatFlag=1;    //置收到连发帧标志位为1
            Timer0_Run(0);        //定时器停止
            IR_State=0;            //置状态为0
        }
        else                    //接收出错
        {
            IR_State=1;            //置状态为1
        }
    }
    else if(IR_State==2)        //状态2,接收数据
    {
        IR_Time=Timer0_GetCounter();    //获取上一次中断到此次中断的时间
        Timer0_SetCounter(0);    //定时计数器清0
        //如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)
        if(IR_Time>1120-500 && IR_Time<1120+500)
        {
            IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));    //数据对应位清0
            IR_pData++;            //数据位置指针自增
        }
        //如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)
        else if(IR_Time>2250-500 && IR_Time<2250+500)
        {
            IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));    //数据对应位置1
            IR_pData++;            //数据位置指针自增
        }
        else                    //接收出错
        {
            IR_pData=0;            //数据位置指针清0
            IR_State=1;            //置状态为1
        }
        if(IR_pData>=32)        //如果接收到了32位数据
        {
            IR_pData=0;            //数据位置指针清0
            if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))    //数据验证
            {
                IR_Address=IR_Data[0];    //转存数据
                IR_Command=IR_Data[2];
                IR_DataFlag=1;    //置收到连发帧标志位为1
            }
            Timer0_Run(0);        //定时器停止
            IR_State=0;            //置状态为0
        }
    }
}

#ifndef __IR_H__
#define __IR_H__

#define IR_POWER        0x45
#define IR_MODE            0x46
#define IR_MUTE            0x47
#define IR_START_STOP    0x44
#define IR_PREVIOUS        0x40
#define IR_NEXT            0x43
#define IR_EQ            0x07
#define IR_VOL_MINUS    0x15
#define IR_VOL_ADD        0x09
#define IR_0            0x16
#define IR_RPT            0x19
#define IR_USD            0x0D
#define IR_1            0x0C
#define IR_2            0x18
#define IR_3            0x5E
#define IR_4            0x08
#define IR_5            0x1C
#define IR_6            0x5A
#define IR_7            0x42
#define IR_8            0x52
#define IR_9            0x4A

void IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);

#endif


这是电动机函数

#include"reg52.h"
#include<Delay.h>
sbit zhengzhuan = P2^2;
sbit fangzhuan = P2^1;
sbit shineng = P2^0;
 
#define uint unsigned int   // 把 unsigned int 简写成uint
 void motor()
     {            // 直流电机函数
    shineng = 1;         // 使能 = 1
    zhengzhuan = 1;      // 正转 = 1
    Delay(75);           // 延时75毫秒
    zhengzhuan = 0;      // 正转 = 0
    Delay(25);           // 延时25毫秒
   }


  • 写回答

2条回答 默认 最新

  • GISer Liu 2024-02-20 00:06
    关注

    该回答引用自GPT-3.5,由博主GIS_Liu编写:

    针对您描述的问题,我会逐个分析并给出解决方案:

    1. LCD显示屏冻结问题: LCD显示屏冻结可能是由于代码中的延时操作影响了主循环的执行。建议将延时操作改为定时器中断方式实现,以确保LCD显示不会被阻塞。

    2. 直流电机不转问题: 检查电机驱动部分的连接是否正确,包括引脚连接和电源供给。另外,确认电机驱动模块的功能是否正常,可以通过简单的测试程序来验证。

    3. 红外遥控按钮无效问题: 首先确保红外遥控模块和单片机之间的连接正确。然后检查红外遥控模块是否正常工作,可以通过红外接收模块的指示灯或者使用示波器来观察红外信号是否正常接收。另外,检查红外遥控按键编码是否正确匹配。

    解决方案的具体步骤如下:

    1. LCD显示屏冻结问题解决方案:

      • 将延时操作改为定时器中断方式实现,确保LCD显示不会被阻塞。
      • 可以使用定时器中断每隔一段时间更新LCD显示,而不是在主循环中使用延时函数。
    2. 直流电机不转问题解决方案:

      • 检查电机驱动部分的连接,确保与单片机的连接正确。
      • 确认电机驱动模块的供电是否正常,可以通过测量电压来验证。
      • 如果电机驱动模块需要外部元件支持(如电容、电阻等),确保这些元件连接正确。
    3. 红外遥控按钮无效问题解决方案:

      • 检查红外遥控模块与单片机之间的连接是否正确。
      • 确认红外遥控模块是否正常工作,可以通过连接示波器或者LED指示灯来观察红外信号接收情况。
      • 检查红外遥控按键编码是否正确,确保与程序中的编码匹配。

    根据您提供的代码,需要对程序进行逐步调试和排查,确定问题所在并进行相应的修正。希望以上解决方案对您有帮助,如有任何疑问,请随时提出。

    如果该回答解决了您的问题,请采纳!如果没有,请参考以下方案进行修订

    用户答题指南

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 5月31日
  • 已采纳回答 5月23日
  • 创建了问题 2月19日