木槿呀 2024-03-29 19:18 采纳率: 72.2%
浏览 26
已结题

蓝桥杯单片机第十三届第一场,整点继电器吸合,5s后断开出现了问题

我在做蓝桥杯单片机第十三届省赛的时候,在整点时刻,继电器吸合,5s后继电器断开的功能上出现了问题。当00:00:00时刻的时候,继电器会吸合,5s后继电器断开一瞬间,又立马吸合。接下来几十秒过后继电器又瞬间断开吸合几次,然后再00:01:05的时刻才断开,后面又在00:02:00时刻吸合,00:02:05时刻断开,这是为什么啊?
main.c

#include<STC15F2K60S2.H>
#include"hardware.h"
#include"ds1302.h"
#include"onewire.h"
#include"intrins.h"
unsigned char mode=0;//S12界面切换
unsigned int temp=0;
unsigned int temp_cs=23;
bit stat=0;
bit fm=0;
bit bz_zd=0;
bit jdq_flag=0;
float temp2=0.0;
unsigned char Timer[7]={0x50,0x59,0x23,0x29,0x03,0x05,0x24};
unsigned char Write_ds1302_addr[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char Read_ds1302_addr[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//-------------------------------------------------------------
void Workingkey()
{
  if(timer10ms>=10)
  {
    timer10ms=0;
    Scankey();
    if(key_value==12 && key_stat==2)
    {
      switch(mode)
      {
        case 0:
         mode=1;//时间显示
        break;
        case 1:
         mode=2;//参数设置
        break;
        case 2:
         mode=0;//温度显示
        break;
      }
    }
    else if(key_value==13 && key_stat==2)
    {
       stat=~stat;
       ws_buf=0x00;
       ws_output();
       jdq_flag=0;
       bz_5s=0;
       bz_zd=0;
    }
    else if(key_value==16 && key_stat==2 && mode==2)//+
    {
      if(temp_cs==99)
        temp_cs=10;
      else
        temp_cs++;
    }
    else if(key_value==17 && key_stat==2 && mode==2)//-
    {
      if(temp_cs==10)
        temp_cs=99;
      else
        temp_cs--;
    }
   else if(key_value==17 && key_stat>1 && mode==1)
   {
      fm=1; 
   }
   else
      fm=0;
  }
}
//-------------------------------------------------------------
void SMG_display()
{
 if(fm==0)
 {
  if(mode==0)
  {
    SMG_buf[0]=25;
    SMG_buf[1]=1;
    SMG_buf[2]=16;
    SMG_buf[3]=16;
    SMG_buf[4]=16;
    SMG_buf[5]=temp/100;
    SMG_buf[6]=temp%100/10+32;
    SMG_buf[7]=temp%10;
  }
  else if(mode==1)
  {
    SMG_buf[0]=25;
    SMG_buf[1]=2;
    SMG_buf[2]=16;
    SMG_buf[3]=Timer[2]/16;
    SMG_buf[4]=Timer[2]%16;
    SMG_buf[5]=17;
    SMG_buf[6]=Timer[1]/16;
    SMG_buf[7]=Timer[1]%16;
  }
  else if(mode==2)
  {
      SMG_buf[0]=25;
    SMG_buf[1]=3;
    SMG_buf[2]=16;
    SMG_buf[3]=16;
    SMG_buf[4]=16;
    SMG_buf[5]=16;
    SMG_buf[6]=temp_cs/10;
    SMG_buf[7]=temp_cs%10;
  }
 }
 else if(fm==1)
 {
   SMG_buf[0]=25;
    SMG_buf[1]=2;
    SMG_buf[2]=16;
    SMG_buf[3]=Timer[1]/16;
    SMG_buf[4]=Timer[1]%16;
    SMG_buf[5]=17;
    SMG_buf[6]=Timer[0]/16;
    SMG_buf[7]=Timer[0]%16;
 }
}
//-------------------------------------------------------------
void Delay(unsigned int t)
{
  while(t--);
}
//-------------------------------------------------------------
void Delay750ms()        //@12.000MHz
{
    unsigned char i, j, k;

    _nop_();
    _nop_();
    i = 35;
    j = 51;
    k = 182;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

//-------------------------------------------------------------
void Read_temp()
{
  unsigned char LSB,MSB;
  init_ds18b20();
  Write_DS18B20(0xcc);
  Write_DS18B20(0x44);
  Delay(1000);
  init_ds18b20();
  Write_DS18B20(0xcc);
  Write_DS18B20(0xbe);
  LSB=Read_DS18B20();
  MSB=Read_DS18B20();
  temp=MSB;
  temp=(temp<<8)|LSB;
  if((temp&0xf800)==0x0000)
  {
    temp>>=4;
    temp=temp*10;
    temp=temp+(LSB&0x0f)*0.625;
    temp2=(float)temp/10;
  }
  else if((temp&0xf800)==0xf800)
  {
    temp=(~temp+1)&0x07ff;
    temp>>=4;
    temp=temp*10;
    temp=temp+(LSB&0x0f)*0.625;
  }
}
//-------------------------------------------------------------
void Write_ds1302()
{
  char i;
  Write_Ds1302_Byte(0x8e,0x00);
  for(i=0;i<7;i++)
  {
    Write_Ds1302_Byte(Write_ds1302_addr[i],Timer[i]);
  }
  Write_Ds1302_Byte(0x8e,0x80);
}
//-------------------------------------------------------------
void Read_ds1302()
{
  char i;
  for(i=0;i<7;i++)
  {
   Timer[i]=Read_Ds1302_Byte(Read_ds1302_addr[i]);
  }
}
//-------------------------------------------------------------
void ws_display()
{
  if(timer10ms2>=10)
 {
    timer10ms2=0;
    if(stat==0)//温度控制
    {
      if(temp2>temp_cs)
      {
        ws_buf=0x10;
        ws_output();
        jdq_flag=1;
      }
      else if(temp2<=temp_cs)
      {
          ws_buf=0x00;
        ws_output();
        jdq_flag=0;
      }
    }
    else if(stat==1)//时间控制
    {
      if(Timer[0]==0x00 && Timer[1]==0x00 )
      {
         timer5s=0;
         bz_5s=0;
         bz_zd=1;
         ws_buf=0x10;
            ws_output();
         jdq_flag=1;
         led_buf=led_buf&0xfe;
         led_output();
    
      }
            /*if(Timer[0]==0x05 && Timer[1]==0x00)
         {
           ws_buf=0x00;
           ws_output();
           jdq_flag=0;
           led_buf=led_buf|0x01;
           led_output(); 
         }*/
      if(bz_5s==1 && bz_zd==1)
      {
        bz_5s=0;
        bz_zd=0;
        ws_buf=0x00;
        ws_output();
        jdq_flag=0;
        led_buf=led_buf|0x01;
        led_output();
      }
    }
  }
}
//-------------------------------------------------------------
void led_display()
{
  if(timer10ms3>=10)
  {
     timer10ms3=0;
     if(stat==0)
     {
       led_buf=led_buf&0xfd;
       led_output();
     }
     else if(stat==1)
     {
       led_buf=led_buf|0x02;
       led_output();
     }
     if(jdq_flag==1)
     {
       if(bz_50ms==1)
       {
         bz_50ms=0;
         led_buf=led_buf^0x04;
         led_output();
       }
     }
     else if(jdq_flag==0)
     {
       led_buf=led_buf|0x04;
       led_output();
     }
  }
}
//-------------------------------------------------------------
void main()
{
  led_output();
  ws_output();
  Timer1Init();
  Write_ds1302();
  Read_temp();
  Delay750ms();
  Read_temp();
  while(1)
  {
      Workingkey();
    SMG_display();
    Read_ds1302();
    ws_display();
    led_display();
    if(timer300ms>=300)
    {
      timer300ms=0;
      Read_temp();
    }
    
  }
}


hardware.c

#include<STC15F2K60S2.H>
#include"hardware.h"
/*************  本地常量声明    **************/
unsigned char code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

unsigned char code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
unsigned char led_buf=0xff;
unsigned char ws_buf=0x00;
unsigned char SMG_buf[]={16,16,16,16,16,16,16,16};
unsigned int timer10ms=0;
unsigned int timer10ms2=0;
unsigned int timer300ms=0;
unsigned int timer10ms3=0;
unsigned int timer50ms=0;
unsigned int timer5s=0;
unsigned int timer1s=0;
unsigned char key_stat=0;
unsigned char key_value=0;
unsigned char key_values[4][4]=
{
  {4,8,12,16},
  {5,9,13,17},
  {6,10,14,18},
  {7,11,15,19},
};
bit bz_5s=0;
bit bz_50ms=0;
//----------------------------------------------------------------------

void Timer1Init()        //1毫秒@12.000MHz
{

    AUXR |= 0x40;        //定时器时钟1T模式
    TMOD &= 0x0F;        //设置定时器模式
    TL1 = 0x20;        //设置定时初值
    TH1 = 0xD1;        //设置定时初值
    TF1 = 0;        //清除TF1标志
    TR1 = 1;        //定时器1开始计时
    ET1=1;
    EA=1;
}
//---------------------------------------------------------------------
void SelectHC573(unsigned char channel)
{
    switch(channel)
    {
       case 4:
         P2=(P2 & 0x1f)|0x80;
       break;
       case 5:
         P2=(P2 & 0x1f)|0xa0;
       break;
       case 6:
         P2=(P2 & 0x1f)|0xc0;
       break;
       case 7:
         P2=(P2 & 0x1f)|0xe0;
       break;
       case 0:
         P2=(P2 & 0x1f)|0x00;
       break;
    }
}
//---------------------------------------------------------------------
void led_output()
{          
    P0=led_buf;
    SelectHC573(4);
    SelectHC573(0);
}
//---------------------------------------------------------------------
void ws_output()
{
       
    P0=ws_buf;
    SelectHC573(5);
    SelectHC573(0);
}
//---------------------------------------------------------------------
void SMG_output()
{
   static unsigned char SMG_com=0;

       
    P0=0x00;
    SelectHC573(6);
    SelectHC573(0);

    
    P0=T_COM[SMG_com];
    SelectHC573(6);
    SelectHC573(0);

    
    P0=~t_display[SMG_buf[SMG_com]];
    SelectHC573(7);
    SelectHC573(0);

    if(++SMG_com>=8)
    {
      SMG_com=0;
    }
}
//---------------------------------------------------------------------
void ServiceTimer()interrupt 3
{
    SMG_output();
    timer10ms++;
    timer10ms2++;
    timer300ms++;
    timer1s++;
    timer10ms3++;
    timer5s++;
    if(timer5s>=5000)
    {
      timer5s=0;
      bz_5s=1;
    }
    timer50ms++;
    if(timer50ms>=50)
    {
      timer50ms=0;
      bz_50ms=1;
    }
}
//----------------------------------------------------------------------
void Scankey()
{
  unsigned char R,C;
  P3=0x0f;
  P4=0x00;
  if(~P3&0x0f)
  {
     if(key_stat<255)
       key_stat++;
     if(P33==0)
       R=0;
     if(P32==0)
       R=1;
     if(P31==0)
       R=2;
     if(P30==0)
       R=3;

     P3=0xf0;
     P4=0xff;
     if(P44==0)
       C=0;
     if(P42==0)
       C=1;
     if(P35==0)
       C=2;
     if(P34==0)
       C=3;

    key_value=key_values[R][C];
  }
  else 
  {
    key_stat=0;
    key_value=0;
  }
}

  • 写回答

20条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-29 21:50
    关注
    获得0.60元问题酬金

    引自免费微信小程序:皆我百晓生

    首先,让我们分析一下您的问题:在整点时刻(例如00:00:00),继电器会按照预期吸合,并在5秒后断开,但断开后立刻又再次吸合,然后在几十秒内反复断开并吸合几次,最终在5分钟后(如00:01:05)彻底断开,之后在下一个整点(如00:02:00)再次吸合并在5秒后(00:02:05)正常断开。

    从您提供的代码来看,您是通过DS1302实时时钟模块获取当前时间,并根据时间来控制继电器的状态。具体实现是在ws_display()函数里处理继电器的工作状态,尤其是这一段逻辑:

    if(stat==1)//时间控制
    {
      if(Timer[0]==0x00 && Timer[1]==0x00 )
      {
         timer5s=0;
         bz_5s=0;
         bz_zd=1;
         ws_buf=0x10; // 继电器吸合
         ...
      }
      //...
      if(bz_5s==1 && bz_zd==1)
      {
        bz_5s=0;
        bz_zd=0;
        ws_buf=0x00; // 继电器断开
        ...
      }
    }
    

    这段代码表明在整点时刻(即小时和分钟都为0),系统会设置bz_zd标志位,进而使继电器吸合。然后,在timer5s达到5秒后(bz_5s被置1),继电器应当断开。

    然而,您描述的问题在于继电器在5秒后断开后迅速又吸合,这很可能是因为bz_zd或其他相关状态变量没有得到正确清理或者受到了其他部分代码的影响。由于您没有提供完整的中断服务程序和其他与继电器控制相关的全局变量定义和初始化代码,我们暂时无法准确判断出问题所在。

    一种可能的原因是某个地方错误地重置了bz_zdbz_5s标志位。为了定位问题,请检查以下几个方面:

    1. 确保bz_zdbz_5s在每次成功执行打开或关闭继电器操作后都被正确地复位。
    2. 检查是否有其他函数意外地修改了这些状态变量。
    3. 验证timer5s是否每过1毫秒递增,确保其计数准确。
    4. 分析ServiceTimer()中断服务程序以及其他可能会改变继电器状态的代码片段,确认它们不会干扰到原本的时间控制逻辑。

    建议您对涉及继电器状态切换的关键代码进行调试,可以尝试添加日志输出或使用硬件仿真工具观察各个变量的状态变化,以便找出导致继电器异常动作的原因。同时,确保所有可能影响继电器状态的条件分支都被考虑到了,且逻辑上无误。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月6日
  • 赞助了问题酬金15元 3月29日
  • 创建了问题 3月29日

悬赏问题

  • ¥20 c语言写的8051单片机存储器mt29的模块程序
  • ¥60 求直线方程 使平面上n个点在直线同侧并且距离总和最小
  • ¥50 java算法,给定试题的难度数量(简单,普通,困难),和试题类型数量(单选,多选,判断),以及题库中各种类型的题有多少道,求能否随机抽题。
  • ¥50 rk3588板端推理
  • ¥250 opencv怎么去掉 数字0中间的斜杠。
  • ¥15 这种情况的伯德图和奈奎斯特曲线怎么分析?
  • ¥250 paddleocr带斜线的0很容易识别成9
  • ¥15 电子档案元素采集(tiff及PDF扫描图片)
  • ¥15 flink-sql-connector-rabbitmq使用
  • ¥15 zynq7015,PCIE读写延时偏大