找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2468|回复: 4
收起左侧

用单片机开发板做了个定时发送命令程序,有些疑问调不通

[复制链接]
ID:4021 发表于 2018-9-30 14:49 | 显示全部楼层 |阅读模式
本帖最后由 shui206 于 2018-9-30 15:59 编辑

本人是一个电力从业者,主业为强电,最近想做一个小设备,用51单片机加四个按键和6位共阴极数码管
要求功能是,用定时器中断在设定的时间,循环发送一个分闸脉冲命令  延时后再发送合闸命令,一次循环后计数加1;
分闸和合闸脉冲的延时时间可调,并且在按下设置按键后,数码管分别用3位显示分闸设定时间,3位显示合闸设定时间并且循环先停止
时间可以加减,
在常规循环发送分 合闸命令时  显示的是循环次数
程序写了后,循环信号暂停,但是显示的还是循环次数,本人是野路子  程序贴出来大家俅俅,有时间的帮看下
//程序功能包含分合闸脉冲输出,延时时间可调,及每次输出一轮分合闸信号,计数。
//程序设置参数时 分合闸脉冲输出暂停

单片机源程序如下:
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit hout=P1^0;  //合闸信号输出
  5. sbit fout=P1^2;  //分闸信号输出
  6. sbit seth=P1^1;  //分闸延时时间设置时指示
  7. sbit setf=P1^3;   //合闸延时时间设置指示
  8. sbit run=P1^7;    //运行指示灯
  9. sbit s1=P3^2;  //设置键,外部中断位
  10. sbit s2=P3^5;  //减少键
  11. sbit s3=P3^6;   //增加键
  12. sbit s4=P3^7;   //清零键
  13. sbit dula=P2^6;      //段选
  14. sbit wela=P2^7;    //位选
  15. sbit beep=P2^3;  //蜂鸣器

  16. uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};    //数码管显示数字
  17. uchar code tablewei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};  //六位数码管位选信号

  18. uchar count1,count2,s1num,numsetf,numseth,miaof,miaoh;
  19. uint numdis;  //定义循环次数
  20. void delayms(uchar z)  //12M晶振延时毫秒函数
  21. {
  22. uint x,y;
  23. for(x=z;x>0;x--)
  24.      for(y=123;y>0;y--);
  25. }

  26. //void delay(uchar z)  //12M晶振时秒函数
  27. //{
  28. // uint x,y,w;
  29. //for(x=z;x>0;x--)
  30.   //   for(y=123;y>0;y--)
  31. //            for(w=10;y>0;y--);

  32. //}

  33. void di()   //蜂鸣器发声函数
  34. {
  35.   beep=0;
  36.   delayms(100);
  37.   beep=1;
  38. }

  39. void display(uint numdis) //显示次数函数
  40. {
  41.   uchar wan,qian,bai,shi,ge;
  42.   wan=numdis/10000;
  43.   qian=numdis%10000/1000;
  44.   bai=numdis%1000/100;
  45.   shi=numdis%100/10;
  46.   ge=numdis%10;

  47.   dula=1;
  48.   P0=table[wan];
  49.   dula=0;
  50.   P0=0xff;
  51.   wela=1;
  52.   P0=tablewei[1];
  53.   wela=0;
  54.   delayms(5);

  55.   dula=1;
  56.   P0=table[qian];
  57.   dula=0;
  58.   P0=0xff;
  59.   wela=1;
  60.   P0=tablewei[2];
  61.   wela=0;
  62.   delayms(5);

  63.   dula=1;
  64.   P0=table[bai];
  65.   dula=0;
  66.   P0=0xff;
  67.   wela=1;
  68.   P0=tablewei[3];
  69.   wela=0;
  70.   delayms(5);

  71.   dula=1;
  72.   P0=table[shi];
  73.   dula=0;
  74.   P0=0xff;
  75.   wela=1;
  76.   P0=tablewei[4];
  77.   wela=0;
  78.   delayms(5);

  79.   dula=1;
  80.   P0=table[ge];
  81.   dula=0;
  82.   P0=0xff;
  83.   wela=1;
  84.   P0=tablewei[5];
  85.   wela=0;
  86.   delayms(5);
  87. }

  88. void display_setf(uchar numsettf) //显示设置分闸延时时间的函数
  89. {
  90.   uchar bai,shi,ge;
  91.   bai=numsettf%1000/100;
  92.   shi=numsettf%100/10;
  93.   ge=numsettf%10;

  94.   dula=1;
  95.   P0=table[bai];
  96.   dula=0;
  97.   P0=0xff;
  98.   wela=1;
  99.   P0=tablewei[3];
  100.   wela=0;
  101.   delayms(5);

  102.   dula=1;
  103.   P0=table[shi];
  104.   dula=0;
  105.   P0=0xff;
  106.   wela=1;
  107.   P0=tablewei[4];
  108.   wela=0;
  109.   delayms(5);

  110.   dula=1;
  111.   P0=table[ge];
  112.   dula=0;
  113.   P0=0xff;
  114.   wela=1;
  115.   P0=tablewei[5];
  116.   wela=0;
  117.   delayms(5);
  118. }

  119. void display_seth(uchar numsetth) //显示设置合闸延时时间的函数
  120. {
  121.   uchar bai,shi,ge;
  122.   shi=numsetth%100/10;
  123.   bai=numsetth%1000/100;
  124.   ge=numsetth%10;

  125.   dula=1;
  126.   P0=table[bai];
  127.   dula=0;
  128.   P0=0xff;
  129.   wela=1;
  130.   P0=tablewei[0];
  131.   wela=0;
  132.   delayms(5);

  133.   dula=1;
  134.   P0=table[shi];
  135.   dula=0;
  136.   P0=0xff;
  137.   wela=1;
  138.   P0=tablewei[1];
  139.   wela=0;
  140.   delayms(5);

  141.   dula=1;
  142.   P0=table[ge];
  143.   dula=0;
  144.   P0=0xff;
  145.   wela=1;
  146.   P0=tablewei[2];
  147.   wela=0;
  148.   delayms(5);
  149. }



  150. void keyscan()   //按键扫描函数
  151. {
  152.   if(s1==0)     
  153.    {
  154.      delayms(5);
  155.          if(s1==0)     //设置键启动
  156.              {
  157.        s1num++;
  158.            run=1;
  159.            while(!s1);
  160.            di();
  161.            if(s1num==1)  //按一次设置键
  162.                {
  163.                  TR0=0;
  164.                  TR1=0;
  165.                  setf=0;       //分闸延时设置指示
  166.                  seth=1;   
  167.                  }
  168.        if(s1num==2)   //按两次设置键
  169.                 {
  170.                   setf=1;
  171.                   seth=0;
  172.                   }
  173.        if(s1num==3)    //按三次设置键
  174.                 {
  175.                   s1num=0;   //设置按键计数清零
  176.                   display(numdis);   
  177.                   run=0;
  178.                   setf=1;
  179.                   seth=1;
  180.                   TR0=1;
  181.                 }
  182.           }
  183.    }
  184.   if(s1num!=0)
  185.    {
  186.       if(s2==0)
  187.         {
  188.            delayms(5);
  189.            if(s2==0)
  190.              {
  191.                   while(!s2);
  192.                   di();
  193.                   if(s1num==1)
  194.                    {
  195.                      display_setf(numsetf);   //显示实时分闸延时时间
  196.                      numsetf++;               
  197.                      if(numsetf==201)
  198.                               numsetf=0;   //分闸延时最长200秒清零   
  199.                     }
  200.               if(s1num==2)
  201.                     {
  202.                       display_seth(numseth);   //显示实时合闸延时时间
  203.                       numseth++;               
  204.                       if(numseth==201)
  205.                       numseth=0;   //合闸延时最长200秒清零
  206.                       }
  207.              }
  208.          }  
  209.        if(s3==0)
  210.            {
  211.               delayms(5);
  212.                if(s3==0)
  213.                  {
  214.                     while(!s3);
  215.                     di();
  216.                    if(s1num==1)
  217.                       {
  218.                         display_setf(numsetf);    //显示实时分闸延时时间
  219.                         numsetf--;               
  220.                         if(numsetf==0)
  221.                         numsetf=200;   //分闸延时最长200秒清零   
  222.                        }
  223.                    if(s1num==2)
  224.                        {
  225.                         display_seth(numseth);   //显示实时合闸延时时间
  226.                         numseth++;               
  227.                         if(numseth==0)
  228.                         numseth=200;   //合闸延时最长200秒清零
  229.                   }
  230.               }
  231.           }  
  232.        if(s4==0)
  233.             {
  234.              delayms(5);
  235.              if(s4==0)   
  236.              numdis=0;   //循环计数清零
  237.               }
  238.    }

  239. }

  240. void init()//初始化函数
  241. {
  242.     numdis=0;
  243.     numsetf=45;
  244.     numseth=45;
  245.     count1=0;
  246.         count2=0;
  247.         miaof=0;
  248.         miaoh=0;
  249.         fout=1;
  250.         hout=1;
  251.         run=0;
  252.         setf=1;
  253.         seth=1;
  254.         TMOD=0x11;
  255.         TH0=(65536-50000)/256;
  256.         TL0=(65536-50000)%256;
  257.         EA=1;   //打开总中断
  258.         ET0=1;
  259.     ET1=1;
  260.         TR0=1;
  261.     TR1=0;
  262. }



  263. void main()   //主函数
  264. {
  265. init();
  266. while(1)
  267.   {
  268.   keyscan();
  269.   display(numdis);
  270.   }

  271. }




  272. void T0_time() interrupt 1
  273. {
  274.         TH0=(65536-45872)/256;
  275.         TL0=(65536-45872)%256;
  276.         count1++;
  277.     if(count1==2)
  278.                 {
  279.                         count1=0;
  280.                         miaof++;
  281.                         if(miaof==numsetf)  
  282.                    {
  283.                             miaof=0;
  284.                      fout=0;
  285.                          delayms(200);
  286.              fout=1;
  287.                          TR0=0;
  288.              TR1=1;         
  289.                     }
  290.                 }      
  291. }

  292. void T1_time() interrupt 3
  293. {
  294.         TH1=(65536-45872)/256;
  295.         TL1=(65536-45872)%256;
  296.         count2++;
  297.     if(count2==2)
  298.                 {
  299.                         count2=0;
  300.                         miaoh++;
  301.                         if(miaoh==numseth)  
  302.                    {
  303.                             miaoh=0;
  304.                      hout=0;
  305.                          delayms(200);
  306.              hout=1;
  307.                      numdis++;  
  308.                    TR0=1;
  309.                          TR1=0;
  310.                     }
  311.                 }      
  312. }
复制代码


回复

使用道具 举报

ID:387733 发表于 2018-9-30 19:37 | 显示全部楼层
keyscan函数中显示的内容,到主循环立即被循环次数替代了。
建议去掉 keyscan()中的显示语句,定义一个变量 xianshi, 设置合闸时, xianshi=1,设置分闸时,xianshi=2,正常工作时,xianshi=0,然后在主循环中,根据变量 xianshi 的值,分别调用三个不同的显示程序。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:213173 发表于 2018-10-1 15:43 | 显示全部楼层
给你把程序框架调整了并优化了显示程序,用计数法代替软件延时,在TX-1C实验板上验证无误。算是送你的国庆节礼物。

//程序功能包含分合闸脉冲输出,延时时间可调,及每次输出一轮分合闸信号,计数。
//程序设置参数时 分合闸脉冲输出暂停*/
//S1键调整选择,S2键+,长按连+,S3键-,长按连-,S4计数清0

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define key_S 20                //宏定义短按时间(约20ms)消抖
#define key_L 300        //宏定义长按时间(约2/3s)
#define key_M 150        //宏定义长按间隔(约1/3s)
sbit hout=P1^0;  //合闸信号输出
sbit seth=P1^1;  //合闸延时时间设置指示
sbit fout=P1^2;  //分闸信号输出
sbit setf=P1^3;  //分闸延时时间设置指示
sbit run=P1^7;    //运行指示灯
sbit s1=P3^4;  //设置键
sbit s2=P3^5;  //增加键
sbit s3=P3^6;   //减少键
sbit s4=P3^7;   //清零键
sbit dula=P2^6;      //段选
sbit wela=P2^7;    //位选
sbit beep=P2^3;  //蜂鸣器

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x39};//数码管显示数字
uchar code tablewei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};  //六位数码管位选信号
uchar data dis_buf[6];//循环次数显示缓存
uchar data dis_fh[6];//分合时间设置显示缓存
uchar s1num=0,numsetf,numseth,miaof,miaoh;
uint count=0;
uint numdis;  //定义循环次数
bit beep_sign=0;//蜂鸣器使能标志
bit sec_sign=0;//秒标志
bit half_sign=0;//半秒标志
bit fh_sign=0;//分合标志

void init()//初始化函数
{
        numdis=0;                //循环次数
        numsetf=45;                //分闸设定初始时间
        numseth=45;                //合闸设定初始时间
        run=0;                          //运行指示灯亮
        miaof=numsetf;
        miaoh=numseth;
        TMOD= 0x01;                //设置定时器模式
        TH0 = 0xFC;                //设置定时初值 1毫秒@11.0592MHz
        TL0 = 0x66;                //设置定时初值
        TR0 = 1;                        //定时器0开始计时
        EA=1;                                //开总中断
        ET0=1;                        //开T0中断
}

void keyscan()   //按键扫描函数
{
        static bit key1_sign,key4_sign;                        //按键自锁标志
        static uint count_1,count_2,count_3=0,count_4=0;//消抖计数变量
        if(s1==0)     
        {
                count_1++;
                if((count_1>=key_S)&&(key1_sign==0))     //设置键启动
                {
                        key1_sign=1;                        //按键1自锁标志置1
                        s1num++;
                        run=1;                   //运行指示灯熄灭
                        if(s1num==1)  //按一次设置键
                        {
                                setf=0;       //分闸延时设置指示
                                seth=1;   
                        }
                        if(s1num==2)   //按两次设置键
                        {
                                setf=1;
                                seth=0;       //合闸延时设置指示
                        }
                        if(s1num==3)    //按三次设置键
                        {
                                s1num=0;   //设置按键计数清零  
                                run=0;                //运行指示灯亮
                                setf=1;
                                seth=1;
                                miaof=numsetf;
                                miaoh=numseth;
                        }
                        beep_sign=1; //提示音
                }
        }
        else
        {
                key1_sign=0;                                //按键1自锁标志清0
                count_1=0;                                        //消抖计数count1清0
        }
        if(s1num!=0)
        {
                if(s2==0)
                {
                        count_2++;
                        if(count_2>=key_L)                        //长按快调
                        {
                                if(s1num==1)
                                {
                                        if(numsetf<200)
                                                numsetf++;                  
                                }
                                if(s1num==2)
                                {
                                        if(numseth<200)
                                                numseth++;               
                                }
                                count_2=key_M;
                                beep_sign=1; //提示音
                        }
                }  
                else                                                        //按键抬起
                {  
                        if(count_2>key_S && count_2<key_L)//短按
                        {
                                if(s1num==1)
                                {
                                        if(numsetf<200)
                                                numsetf++;                  
                                }
                                if(s1num==2)
                                {
                                        if(numseth<200)
                                                numseth++;               
                                }
                                beep_sign=1; //提示音
                        }
                        count_2=0;                                        //count_2清0
                }

                if(s3==0)
                {
                        count_3++;
                        if(count_3>=key_L)                        //长按
                        {
                                if(s1num==1)
                                {
                                        if(numsetf>0)
                                                numsetf--;                  
                                }
                                if(s1num==2)
                                {
                                        if(numseth>0)
                                                numseth--;
                                }
                                count_3=key_M;
                                beep_sign=1; //提示音
                        }
                }  
                else                                                        //按键抬起
                {  
                        if(count_3>key_S && count_3<key_L)//短按
                        {

                                if(s1num==1)
                                {
                                        if(numsetf>0)
                                                numsetf--;                  
                                }
                                if(s1num==2)
                                {
                                        if(numseth>0)
                                                numseth--;
                                }
                                beep_sign=1; //提示音
                        }
                        count_3=0;                                        //count_3清0
                }
        }
        if(s4==0)
        {
                count_4++;
                if((count_4>=key_S)&&(key4_sign==0))  
                {
                        key4_sign=1;                        //按键1自锁标志置1
                        numdis=0;                           //循环计数清零
                        beep_sign=1; //提示音
                }
        }
        else
        {
                key4_sign=0;                                //按键4自锁标志清0
                count_4=0;                                        //消抖计数count_4清0
        }
}

void Control()//控制程序
{
        if((sec_sign==1)&&(s1num==0))       
        {
                sec_sign=0;
                if(fh_sign==0)
                {
                        fout=0;                        //分闸信号输出
                        hout=1;                        //合闸信号输出
                        setf=0;                        //分闸指示灯亮
                        seth=1;                        //合闸指示灯熄
                        miaof--;
                        if(miaof==0)
                        {
                                fh_sign=1;
                                miaoh=numseth;
                                numdis++;                //循环次数累加
                                if(numdis>=10000)//限制溢出
                                        numdis=0;
                        }
                }
                else
                {
                        fout=1;                        //分闸信号输出
                        hout=0;                        //合闸信号输出
                        setf=1;                        //分闸指示灯熄
                        seth=0;                        //合闸指示灯亮
                        miaoh--;
                        if(miaoh==0)
                        {
                                fh_sign=0;
                                miaof=numsetf;
                        }
                }
        }
}

void decompose()//数据分解保存
{
        dis_buf[0]=16;//显示C
        dis_buf[1]=numdis/10000;
        dis_buf[2]=numdis%10000/1000;
        dis_buf[3]=numdis%1000/100;
        dis_buf[4]=numdis%100/10;
        dis_buf[5]=numdis%10;

        dis_fh[0]=numsetf/100;
        dis_fh[1]=numsetf%100/10;
        dis_fh[2]=numsetf%10;
        dis_fh[3]=numseth/100;
        dis_fh[4]=numseth%100/10;
        dis_fh[5]=numseth%10;
}

void beep_di()   //蜂鸣器发声函数
{
        static uint count_5;
        if(beep_sign==1)
        {
                beep=0;
                count_5++;
                if(count_5>=100)
                {
                        count_5=0;
                        beep_sign=0;
                        beep=1;
                }
        }
}

void display() //显示函数
{
        static uint i=0;
        P0=0x00;                //送段码消隐
        dula=1;
        dula=0;
/********显示累加合闸次数***********/
        if(s1num==0)//
        {
                P0=tablewei[i];//送位码
                wela=1;
                wela=0;
                if((half_sign==1)&&(i==0))
                {
                        P0=table[dis_buf[i]]|0x80;//送段码+闪点
                        dula=1;
                        dula=0;
                }
                else
                {
                        P0=table[dis_buf[i]];//送段码
                        dula=1;
                        dula=0;
                }
        }
/*******显示设置参数**********/
        else
        {
                P0=tablewei[i];//送位码
                wela=1;
                wela=0;
                if((half_sign==1)&&(i<=2)&&(s1num==1))//显示设置分闸闪点
                {
                        P0=table[dis_fh[i]]|0x80;//送段码+闪点
                        dula=1;
                        dula=0;
                }
                else if((half_sign==1)&&(i>=3)&&(s1num==2))//显示设置合闸闪点
                {
                        P0=table[dis_fh[i]]|0x80;//送段码+点
                        dula=1;
                        dula=0;
                }
                else
                        P0=table[dis_fh[i]];//送段码
                        dula=1;
                        dula=0;
        }
        i++;
        if(i>5)
                i=0;
}

void main()   //主函数
{
        init();                //初始化
        while(1)
        {
                keyscan();//按键扫描
                Control();//控制程序
                decompose();//数据分解保存
                beep_di();//蜂鸣器发声函数
        }
}
void T0_time() interrupt 1
{
        static uint i=0;
        TH0 = 0xFC;                //重装初值 1毫秒@11.0592MHz
        TL0 = 0x66;                //重装初值
        i++;
        if(i==500)
        {
                i=0;
                half_sign=~half_sign;//半秒闪点标志取反
        }
        if(s1num==0)
        {
                count++;
                if(count>=1000)//1秒
                {
                        count=0;
                        sec_sign=1;//秒标志置1
                }
        }      
        display();//显示程序刷新
}

评分

参与人数 1黑币 +35 收起 理由
angmall + 35 赞一个!

查看全部评分

回复

使用道具 举报

ID:4021 发表于 2019-4-29 09:22 | 显示全部楼层
谢谢各支持  从强电转学弱电好多概念不清楚  去年用90C52画了个板子干扰太大,死机。
现在又在试试STC12的单片机  加入24C20存储次数《次数为2万次最高》  可惜存储次数一直调不好,重新上电有时候可以读出上次次数,有时候显示随机数字,闲暇时还在努力
回复

使用道具 举报

ID:213173 发表于 2019-4-29 11:10 | 显示全部楼层
shui206 发表于 2019-4-29 09:22
谢谢各支持  从强电转学弱电好多概念不清楚  去年用90C52画了个板子干扰太大,死机。
现在又在试试STC12的 ...

STC12自带EEPROM,加入24C02纯属蛇足。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表