打印

请大家帮我查找一个问题,先谢谢了

[复制链接]
3513|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我们做的产品很简单,产品采用89S52单片机进行信号采集、处理、控制。

当单片机引脚采集外部启动信号有效时,开始对2个电磁阀进行控制。每个电磁阀上电55S,然后失电5S,第60s时,给另一个电磁阀上电,也是上电55S时,失电。在此60S内,另一个电磁阀一直失电。

逻辑功能就是下面的图,电磁阀是110V供电的。

电磁阀工作逻辑图.jpg (1.03 MB )

电磁阀工作逻辑图.jpg

相关帖子

沙发
ayb_ice| | 2011-7-11 11:34 | 只看该作者
DIY吧

使用特权

评论回复
板凳
xiaohui408x|  楼主 | 2011-7-11 11:43 | 只看该作者
现在的情况是:我设计好硬件及程序后,在实验室大概看了下,没有什么问题,将板子装到产品上去,运行了一段时间后,出现2个电磁阀同时得电的情况。有时候能自动恢复正常,有时候就不能恢复正常了,按照设计功能,是绝不可能出现这种情况的。但现在,这种情况偶尔会出现一下,我实在找不出原因了,请大家帮我一起分析一下吧。等会我把程序贴出来。

  为了查找这个问题的原因,其他的传感器数据采集显示、按键功能都给我删掉了,只留控制及故障检测功能。

使用特权

评论回复
地板
xiaohui408x|  楼主 | 2011-7-11 11:46 | 只看该作者
上面的图是我自己画的,为了说明我的电路功能。我们现在在做产品,但这个问题解决不了,我们的产品就存在安全隐患。我找了很久也不知道问题在哪.当然,我水平比较菜了。

公司里没有高手,因此在这里请教的大家

使用特权

评论回复
5
xiaohui408x|  楼主 | 2011-7-11 11:47 | 只看该作者
这是这边部分功能的相关硬件原理图

电源—单片机.JPG (136.24 KB )

电源—单片机.JPG

控制——检测.JPG (101.5 KB )

控制——检测.JPG

使用特权

评论回复
6
xiaohui408x|  楼主 | 2011-7-11 11:48 | 只看该作者
#include <reg52.h>
#include <intrins.h>
#include   "head.h"
#include "74HC595.c"

#include  "at25128_e2prom.c"
#include "ds1302.c"
#include "uart.c"


   //定义引脚
   sbit   led1=P0^1;           //        温度显示指示灯
   sbit   led2=P0^2;          //        湿度显示指示灯
   sbit   led3=P0^3;          //        故障指示灯
   sbit   c_ctrlm1=P0^6;           //控制信号1
   sbit   c_ctrlm2=P0^7;           //控制信号2   
   sbit   test1=P2^6;                 //检测驱动输出端信号1

  sbit test2=P2^7; //检测驱动输出端信号2
  sbit control=P0^5;  // 压缩机启动信号
  sbit pressure=P3^2;  //压力开关启动信号

void  delayms(uchar ms) //延时子程序
{
        uint i;
        for(ms;ms>0;ms--)
                for(i=114;i>0;i--);
}  
void init_interrupt(void) //外中断0初始化
{
        EA=1;
        EX0=1;
        IT0=1;
}



void display_init()        //开机显示初始化
{
                        EA=0;
                                                Write_HC595( num_num[0],adress[0]);
                                                Write_HC595( num_num[0],adress[1]);
                                                Write_HC595( num_num[0],adress[2]);
                                                Write_HC595( num_num[0],adress[3]);
                                                Write_HC595( num_num[13],adress[3]);
                                                //display_delays=1;
                                                EA=1;
}




   void save_fault(void) //开机存贮信号,以此判断在程序执行过程中有无复位现象,是硬件复位还是软件复位。
   {   
        uchar adress_h,adress_l;
          adress_h=fault_adress/256;
                  adress_l=fault_adress%256;
     
          
        SPI_WriteByte(adress_h,adress_l,hour_test());//存入时间
       
                 fault_adress++;
                 adress_h=fault_adress/256;
                  adress_l=fault_adress%256;
                SPI_WriteByte(adress_h,adress_l,min_test());
       
                fault_adress++;
                adress_h=fault_adress/256;
                  adress_l=fault_adress%256;
                SPI_WriteByte(adress_h,adress_l,min_test());
       
                fault_adress++;
                adress_h=fault_adress/256;
                  adress_l=fault_adress%256;
                   SPI_WriteByte(adress_h,adress_l,reset_num);        //存入复位次数
       
                fault_adress++;
                adress_h=fault_adress/256;
                  adress_l=fault_adress%256;
                if(F0)
          SPI_WriteByte(adress_h,adress_l,1);//利用PSW^5的值判断是软件复位还是硬件复位,用户标志位
            else
              SPI_WriteByte(adress_h,adress_l,0);//利用PSW^5的值判断是软件复位还是硬件复位。
           fault_adress++;
           adress_h=fault_adress/256;
           adress_l=fault_adress%256;

           SPI_WriteByte(0x00,0x02,adress_h);
           SPI_WriteByte(0x00,0x03,adress_l);

          
   }
   void savedata(void)   //存储运行数据,出现异常现象时,存储         ,当控制信号不等于相应的检测信号时,或者,两个控制信号同时为0时,存入数据
   {       
         uchar adress_h,adress_l;                                 //        另外,正常运行时,每周期存入两次数据,存入的时间点为每次电磁阀切换时存入
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                  
                 SPI_WriteByte(adress_h,adress_l,hour_test());         //存储时间
                 
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                SPI_WriteByte(adress_h,adress_l,min_test());         //存储时间
                 
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                SPI_WriteByte(adress_h,adress_l,sec_test());
               
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                SPI_WriteByte(adress_h,adress_l,c_ctrlm1);        //存储控制信号1
       
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                SPI_WriteByte(adress_h,adress_l,test1);            //存储检测信号1
       
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                SPI_WriteByte(adress_h,adress_l,c_ctrlm2);  //存储控制信号2
       
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
                SPI_WriteByte(adress_h,adress_l,test2);          //存储检测信号2
       
                data_adress++;
                adress_h=data_adress/256;
                 adress_l=data_adress%256;
               
            SPI_WriteByte(0x00,0x00,adress_h);
            SPI_WriteByte( 0x00,0x01,adress_l);
       

   }


void Init_sys()
{
    int i;
         //单片机引脚初始化
        led1=1;
        led2=1;

        c_ctrlm1=1;
        c_ctrlm1=1;
        test1=1;
        test2=1;

        pressure=1;


//        dryer_delays=0;
        //芯片初始化  ,外存及时钟芯片
        //Init_SPI_E2prom();
        //Init_DS();
   //变量初始化
        write_flag=0;  //存入故障数据标志
        write_time=0;  //控制每周期存入故障数据的个数
        WDT_flag=0;          //清看门狗标志
        flag_fault=0;   //运行过程中发现同时得电后,此标志有效,并用其控制故障处理时间
        num=0;  //控制干燥器运行周期
    init_interrupt();//外中断0初始化

         i=20;
        while(i) //开机显示”0000“
    {
        i--;
        display_init();
        delayms(10);
        led3=0;          //点亮led3
        }

        fault_adress=SPI_ReadByte(0x00,0x02)*256+SPI_ReadByte(0x00,0x03);  //从存贮        复位信息数据的指针的地址中读取最后一次指针数值
        data_adress=SPI_ReadByte(0x00,0x00)*256+SPI_ReadByte(0x00,0x01);  //同上
        reset_num=SPI_ReadByte(0x00,0x04);
        reset_num++;
        save_fault(); //记录单片机复位信息,帮助判断故障类型(对于正常上电复位及看门狗复位暂不作区分,先以记录时间来区分)
        //WDTRST=0x01e; //启动89S52内部看门狗
//        WDTRST=0x0e1;
        led3=1;          //熄灭led3


}
void main()
{       
   
        Init_sys();
        F0=1;
          
         while(1)
        {
       
         // WDTRST=0x01e; //喂狗指令
        //  WDTRST=0x0e1;
           delayms(1);//将来由其他函数代替       
         
          
             if((c_ctrlm1!=test1)||(c_ctrlm2!=test2)||(test1==0&&test2==0))
             {
                savedata();
               
                    c_ctrlm1=1; //发现运行不正常,及时关闭两个电磁阀
                    c_ctrlm2=1;
             }
  

       
                
          if(! display_delays)  //实时显示运行数据 ,操作人员可根据此信息判断控制器运行是否正常
           {                                             
               EA=0;
               Write_HC595( num_num[c_ctrlm1],adress[0]);
               Write_HC595( num_num[test1],adress[1]);
               Write_HC595( num_num[c_ctrlm2],adress[2]);
               Write_HC595( num_num[test2],adress[3]);
               Write_HC595( num_num[13],adress[3]);
                      display_delays=1;
                   EA=1;
               }
               
         
         
                     

                 


            
         WDT_flag=1;//程序正确执行的标志       
  }        
          
         
}
          
                       
          










void ex0_inter() interrupt 0  using 0
{

//        uchar i;

//        sensor_flag=1;//只启动一次

        c_ctrlm1=0;
        c_ctrlm2=1;
       
        c_ctrl_m1=1;      
        c_ctrl_m2=0;
//        sth1x_sensor0();   // do not call other function in a interruption
//        display();
//        alarm_tem(temp);
       
        TMOD=0x11; //Timier0 16 bit mode 定时器1、0工作在方式1
        TH0=0x4C;  //(65536-50000)/256;
        TL0=0x00;  //(65536-50000)%256;

        TH1=0xdc;//        延时10ms
        TL1=0x00;//

        EA=1;      //globle interrupt
        ET0=1;     //Timer 0 interrupt   禁止定时器0       
        TR0=1;           //Timer 0 beginning

        ET1=1;     //Timer 0 interrupt       
        TR1=1;           //Timer 0 beginning
}

void t0_iner() interrupt 1 using 1         //先执行外中断        ,此时c_ctrl_m1,c_ctrl_m2不再同时为1了
{

        TH0=0x4C;//        中断定时50ms
        TL0=0x00;//

         if(!test1&&!test2)                  //中断时间到,先检测是否有同时的得电的情况,顺序非常重要!
        {
           c_ctrlm1=1;
           c_ctrlm2=1;
           c_ctrl_m1=1;
           c_ctrl_m2=1;
           flag_fault=20;
           num=0; //回归初始状态
    }
        if(flag_fault)//确保不会有误动作
        {
        flag_fault--;
        num=0;
        c_ctrlm1=1;
        c_ctrlm2=1;
                }  //同时失电,等待故障处理结束


        if(num==1100)   //60s ,闭气时间到,两个同时失电
        {

                c_ctrlm1=1;
                c_ctrlm2=1;
                write_flag=0;
        }

         if(pressure) //压力开关无效,停止工作。
        {
                TR0=0;
                ET0=0;
                TR1=0;
                ET1=0;
                num=0; ////////////////////////////////////////
                c_ctrlm1=1;
                c_ctrlm2=1;
                c_ctrl_m1=1;///////可以做数码管显示的检测标志位
                c_ctrl_m2=1;
               

        }

        if(!flag_fault&&!pressure)        //故障处理结束,压力开关有效
           if(c_ctrl_m1&&c_ctrl_m2)//在压力开关有效的前提下,状态标志异常,并且故障标志到期,则恢复电磁阀交替上电状态
         {
                     c_ctrlm1=0;
                c_ctrlm2=1;
                c_ctrl_m1=1;      
                c_ctrl_m2=0;
                        num=0;        //故障处理后,启动正常 工作状态
         }
        if(num==1200)  //
        {
                num=0;
               
                c_ctrlm1=c_ctrl_m1;
                c_ctrlm2=c_ctrl_m2;
               
                c_ctrl_m1=c_ctrlm2;
                c_ctrl_m2=c_ctrlm1;
                write_flag=0;
        }


        num++;       
         
}
  void t1_iner() interrupt 3 using 2
{

        TH1=0xdc;//        延时10ms
        TL1=0x00;//
        TR1=0;
        ET1=0;

   //  if(WDT_flag==1)
         // {
          //  WDTRST=0x01e;
           //  WDTRST=0x0e1;
          //}
         if( display_delays)
         display_delays--;


         
         TR1=1;
        ET1=1;
}

使用特权

评论回复
7
相信哥咯| | 2011-7-11 12:37 | 只看该作者
51读引脚前先置1,是不是:$。

提供思路给楼主啊,
查是输出引起的还是输入引起。

1.直接控制一个得电,一个失电,看会不会出现同时得电,如果不会就是输入(程序或者硬件)有问题

使用特权

评论回复
8
xiaohui408x|  楼主 | 2011-7-11 12:45 | 只看该作者
谢谢楼上的恢复啊,我想想先

使用特权

评论回复
9
t.jm| | 2011-7-11 13:25 | 只看该作者
把R23、R27阻值改小点,改到1KR。

使用特权

评论回复
10
xiaohui408x|  楼主 | 2011-7-11 14:21 | 只看该作者
谢谢楼上的,我试试。

另外,大家看我的程序有没有什么问题?

使用特权

评论回复
11
xiaohui408x|  楼主 | 2011-7-11 14:22 | 只看该作者
这种偶发现象真实让人头大

使用特权

评论回复
12
shen781219| | 2011-7-11 15:55 | 只看该作者
学习

使用特权

评论回复
13
xiaohui408x|  楼主 | 2011-7-11 19:06 | 只看该作者
为什么没有人理我呢?

使用特权

评论回复
14
idterminator| | 2011-7-11 19:44 | 只看该作者
图小看不清楚;
程序乱;
如果你有画流程图,先对着流程图核查一遍,对于这种逻辑关系简单的处理,可以先检查程序;

这种问题多半是干扰引起的,如果程序再不严谨就很容易出问题了,仔细分析程序先。

下面仅提两点

没有找到c_ctrl_m1,c_ctrl_m2的定义,这不是关键,
从程序来看,你用c_ctrl_m1,c_ctrl_m2这两个标志来确定电磁阀状态,这样很不好,增加了风险,
因为功能要求很明确:不允许两个同时开,所以只用一个标志就可以了,必须的;

另,出现异常后应该先保护设备,安全第一,看你的程序是先savedata(),考虑欠周全。

使用特权

评论回复
15
xiaohui408x|  楼主 | 2011-7-11 20:26 | 只看该作者
非常感楼上,你的建议很好。
我回去改一下。

使用特权

评论回复
16
xiaohui408x|  楼主 | 2011-7-11 20:26 | 只看该作者
头文件里有变量的定义,我没有给出来。

使用特权

评论回复
17
宋业科| | 2011-7-12 10:23 | 只看该作者
换电磁阀,用互锁的。

使用特权

评论回复
18
xiaohui408x|  楼主 | 2011-7-12 10:31 | 只看该作者
楼上的大侠认为我们的电磁阀有问题吗?

使用特权

评论回复
19
原野之狼| | 2011-7-12 10:43 | 只看该作者
首先保证程序逻辑的正确性。
另外,很重要的一点,从硬件上做互锁。

使用特权

评论回复
20
xiaohui408x|  楼主 | 2011-7-12 11:14 | 只看该作者
谢谢,楼上的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

55

帖子

1

粉丝