找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9371|回复: 46
打印 上一主题 下一主题
收起左侧

求一个按键闭合后,继电器延时1分钟吸合,再延时5分钟断开的单片机程序

  [复制链接]
跳转到指定楼层
楼主
ID:272609 发表于 2018-10-13 10:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
学习单片机有一阵子了,老实说断断续续有几年了,资料也看了一大堆,感觉始终在门口徘徊,现在要写一个程序,早上花了两个小时还没有写成,程序要求是这样,K1按键按下后,继电器延时1分钟后再吸合,吸合后延时5分钟再断开,等待下一次K1的按键按下。
使用89C52,不用数码管,也不用24C01等EEPROM,论坛里搜索了很多,要么不能用,要么太复杂,看不懂也用不了那么多功能。
求论坛的大神写个源程序,让入门的菜鸟也能活学活用定时器和中断。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:388197 发表于 2018-10-13 14:33 | 只看该作者
随便写的,下载到板子上试了试没问题,1分钟 5分钟时间太长,我改成5秒 25秒,你只要改下数字就行.
#include <reg52.h>
sbit relay = P1^0;              //继电器,0线圈吸合,1线圈断开
sbit key = P1^1;                //按键,0为按下,1为松开
unsigned char key_timer_cnt;    //检测按键计时变量
unsigned int relay_timer_cnt;    //继电器吸合断开计时变量
unsigned char relay_timer_cnt_min;    //继电器延迟断开计数器分钟,因为5分钟,1ms为单位将超过65535
unsigned char relay_state;       //记录继电器状态 0=未触发 1=待吸合 2=待断开
       
void Init_T0(void)                  //定时器中断初始化,设置为1ms
{
    TMOD = 0x01;
    TH0 = 0xfc;
    TL0 = 0x18;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}
void main(void)
{
        Init_T0();
        relay = 1;                         //断开继电器
        relay_state = 0;               //继电器处于未触发状态
        while(1)
        {
             //想实现其他功能,再这里添加代码
        }
}
void T0_ISR() interrupt 1              //1毫秒
{
        TH0 = 0xfc;
        TL0 = 0x18;
//***************************待触发状态,需要做的只是判断按键有没有按下*******************
        if(relay_state == 0)                //当继电器处于待触发状态
        {
                if(key == 0)                      //按键按下,并且继电器处于未触发状态
                {
                        key_timer_cnt++;                                  //按键计时器自加,用于消抖
                        if(key_timer_cnt>=5)                              //按键超过5毫秒
                        {
                                key_timer_cnt = 0;                          
                                relay_state = 1;                               //将继电器设成待吸合状态
                        }
                }else
                {
                        key_timer_cnt = 0;
                }
        }
        //********************待吸合状态,等计数器加满就行*****************************
        if(relay_state == 1)
        {
                relay_timer_cnt++;
                if(relay_timer_cnt>=5000)                      //将5000改为60000 即为1分钟                  
                {
                        relay = 0;                                   //继电器吸合
                        relay_state = 2;                             //吸合后将状态转成待断开
                        relay_timer_cnt = 0;
                }
        }
        //******************待断开状态,跟待吸合一样加满就行*******************************
        if(relay_state == 2)
        {
                relay_timer_cnt++;
                if(relay_timer_cnt>=5000)                     //将5000改为60000即为1分钟
                {
                        relay_timer_cnt = 0;
                        relay_timer_cnt_min++;                      //每60秒加1
                        if(relay_timer_cnt_min>=5)                  //当分钟数等于5
                        {
                                relay = 1;                                //断开继电器
                                relay_timer_cnt_min = 0;
                                relay_timer_cnt = 0;
                                relay_state = 0;                          //断开后将继电器状态转换成未触发
                        }
                }
        }
}

评分

参与人数 4黑币 +80 收起 理由
yong761228 + 10
admin + 50 回帖助人的奖励!
飞线 + 8 回帖助人的奖励!
YJGG + 12 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:155507 发表于 2018-10-13 16:18 | 只看该作者
我给你来个程序试试


  1. #include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器

  2. typedef unsigned int u16;          //对数据类型进行声明定义
  3. typedef unsigned char u8;

  4. sbit k1=P3^1;         //定义P31口是k1
  5. sbit led=P2^0;         //定义P20口是led
  6. sbit Relay=P2^1; //定义P21口是继电器 //继电器,1线圈吸合,0线圈断开

  7. u16 Sec=0; //秒钟
  8. u16 StartSec, StopSec;  //
  9. u8 KeyHit=0, StartRelay=0; //标志位
  10. u16 Relay_on_Interval = 60;    //继电器延时1分钟后再吸合
  11. u16 Relay_off_Interval = 300;  //继电器吸合后延时5分钟再断开
  12. /*******************************************************************************
  13. * 函 数 名         : Timer0Init
  14. * 函数功能                   : 定时器0初始化
  15. * 输    入         : 无
  16. * 输    出         : 无
  17. *******************************************************************************/
  18. void Timer0Init()
  19. {
  20.         TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

  21.         TH0=0X3C;        //给定时器赋初值,定时50ms
  22.         TL0=0XB0;       
  23.         ET0=1;//打开定时器0中断允许
  24.         EA=1;//打开总中断
  25.         TR0=1;//打开定时器                       
  26. }

  27. /*******************************************************************************
  28. * 函 数 名         : delay
  29. * 函数功能                   : 延时函数,i=1时,大约延时10us
  30. *******************************************************************************/
  31. void delay(u16 i)
  32. {
  33.         while(i--);       
  34. }

  35. /*******************************************************************************
  36. * 函 数 名         : keypros
  37. * 函数功能                   : 按键处理函数,判断按键K1是否按下
  38. *******************************************************************************/
  39. void keypros()
  40. {
  41.         if(k1==0)                  //检测按键K1是否按下
  42.         {       
  43.                 delay(1000);   //消除抖动 一般大约10ms
  44.                 if(k1==0)         //再次判断按键是否按下
  45.                 {
  46.                         if(KeyHit==0)
  47.                         {
  48.                                 StartSec=Sec;
  49.                         }
  50.                         KeyHit=1; //按键K1按下
  51.                         led=~led;          //led状态取反
  52.                 }
  53.                 while(!k1);         //检测按键是否松开
  54.         }               
  55. }

  56. /*******************************************************************************
  57. * 函 数 名       : main
  58. * 函数功能                 : 主函数
  59. * 输    入       : 无
  60. * 输    出             : 无
  61. *******************************************************************************/
  62. void main()
  63. {       
  64.         Timer0Init();  //定时器0初始化
  65.         Relay = 0;      //断开继电器
  66.         while(1)
  67.         {       
  68.                 keypros();  //按键处理函数
  69.                 if(KeyHit==1)
  70.                 {
  71.                         if((StartRelay ==0) &&(Sec - StartSec >= Relay_on_Interval))
  72.                         {
  73.                                 Relay=1; //继电器延时1分钟后再吸合
  74.                                 StartRelay =1;
  75.                                 StopSec = Sec;
  76.                         }
  77.                         if((StartRelay ==1) &&(Sec - StopSec >= Relay_off_Interval))
  78.                         {
  79.                                 Relay=0; //继电器吸合后延时5分钟再断开
  80.                                 KeyHit=0; //清除标志
  81.                                 StartRelay =0;
  82.                         }
  83.                        
  84.                 }
  85.         }               
  86. }

  87. /*******************************************************************************
  88. * 函 数 名         : void Timer0() interrupt 1
  89. * 函数功能                   : 定时器0中断函数
  90. * 输    入         : 无
  91. * 输    出         : 无
  92. *******************************************************************************/
  93. void Timer0() interrupt 1
  94. {
  95.         static u16 i;
  96.         TH0=0X3C;        //给定时器赋初值,定时50ms
  97.         TL0=0XB0;
  98.         i++;
  99.         if(i==20)
  100.         {
  101.                 i=0;
  102.                 Sec++;
  103.                
  104.                 //led=~led;       
  105.         }       
  106. }
复制代码

评分

参与人数 1黑币 +8 收起 理由
飞线 + 8 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:401564 发表于 2018-10-13 19:31 | 只看该作者
C我不会,汇编的话可以教你一下,我也是从什么都不会开始自学的,也是走了很多的弯路

评分

参与人数 1黑币 +8 收起 理由
飞线 + 8 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:272609 发表于 2018-10-14 15:32 | 只看该作者
Y_G_G 发表于 2018-10-13 19:31
C我不会,汇编的话可以教你一下,我也是从什么都不会开始自学的,也是走了很多的弯路

汇编我不懂,只会点C,谢谢你的分享,让我们一起努力吧
回复

使用道具 举报

6#
ID:137736 发表于 2018-10-14 17:47 | 只看该作者
Y_G_G 发表于 2018-10-13 19:31
C我不会,汇编的话可以教你一下,我也是从什么都不会开始自学的,也是走了很多的弯路

会汇编水平就比较高了,再学C很容易了。

评分

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

查看全部评分

回复

使用道具 举报

7#
ID:123289 发表于 2018-10-14 21:14 | 只看该作者
学了这么久,这么简单的问题还搞不定,建议改行!改行不是坏事,找一个更合适自己的乃是不错的选择。

评分

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

查看全部评分

回复

使用道具 举报

8#
ID:280876 发表于 2018-10-15 17:14 | 只看该作者
老哥,改行吧。都几年了还是这样

评分

参与人数 1黑币 +8 收起 理由
飞线 + 8 很给力!

查看全部评分

回复

使用道具 举报

9#
ID:405193 发表于 2018-10-15 20:00 | 只看该作者
cjm82 发表于 2018-10-13 14:33
随便写的,下载到板子上试了试没问题,1分钟 5分钟时间太长,我改成5秒 25秒,你只要改下数字就行.
#include
...

非常感谢这位师傅,我虽然年级比较大了,可是最近才开始学单片机编程,我利用您的程序,成功改写1分钟吸合5秒断开循环程序。
#include <reg52.h>
sbit relay = P3^6;              //继电器,0线圈吸合,1线圈断开
sbit key = P3^2;                //按键,0为按下,1为松开
unsigned char key_timer_cnt;    //检测按键计时变量
unsigned int relay_timer_cnt;    //继电器吸合断开计时变量
unsigned char relay_timer_cnt_min;    //继电器延迟断开计数器分钟,因为5分钟,1ms为单位将超过65535
unsigned char relay_state;       //记录继电器状态 0=未触发 1=吸合 2=断开
        
void Init_T0(void)                  //定时器中断初始化,设置为1ms
{
    TMOD = 0x01;
    TH0 = 0xfc;
    TL0 = 0x18;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}
void main(void)
{
        Init_T0();
        relay = 1;                         //断开继电器
        relay_state = 0;               //继电器处于未触发状态
        while(1)
        {
             //想实现其他功能,再这里添加代码
        }
}
void T0_ISR() interrupt 1              //1毫秒
{
        TH0 = 0xfc;
        TL0 = 0x18;
//***************************待触发状态,需要做的只是判断按键有没有按下*******************
        if(relay_state == 0)                //当继电器处于待触发状态
        {
                if(key == 0)                      //按键按下,并且继电器处于未触发状态
                {
                                         relay = 0;
                        key_timer_cnt++;                                  //按键计时器自加,用于消抖
                        if(key_timer_cnt>=5)                              //按键超过5毫秒
                        {
                                key_timer_cnt = 0;                          
                                relay_state = 2;                               //将继电器设成待吸合状态
                        }
                }else
                {
                        key_timer_cnt = 0;
                }
        }
        //********************继电器断开的时间,等计数器加满就行*****************************
        if(relay_state == 1)
        {
                relay_timer_cnt++;
                if(relay_timer_cnt>=5000)                      //将5000改为60000 即为1分钟                  
                {
                        relay = 0;                                   //继电器将吸合
                        relay_state = 2;                             //吸合后将状态转成断开
                        relay_timer_cnt = 0;
                }
        }
        //******************继电器吸合的时间,跟待吸合一样加满就行*******************************
        if(relay_state == 2)
        {
                relay_timer_cnt++;
                if(relay_timer_cnt>=60000)                     //将5000改为60000即为1分钟
                {
                                relay = 1;                                //继电器将断开
                                relay_timer_cnt = 0;
                                relay_state = 1;                          //断开后将继电器状态转换成吸合
                        }
                }
        }

评分

参与人数 3黑币 +143 收起 理由
飞线 + 8 很给力!
admin + 100 回帖助人的奖励!
angmall + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

10#
ID:405193 发表于 2018-10-15 20:07 | 只看该作者
楼主努力,我也是最近才开始学单片机编程,我都40多岁了,我都不怕,加油!

评分

参与人数 2黑币 +28 收起 理由
飞线 + 8 很给力!
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

11#
ID:405193 发表于 2018-10-15 21:03 | 只看该作者
angmall 发表于 2018-10-13 16:18
我给你来个程序试试

师傅,您好,您的程序我用STC15W404as 单片机,改了端口sbit relay = P3^6;   sbit key = P3^2;  就是不成功,可能您里面用了特殊寄存器,我这单片机程序可能不对,请指点一下,非常感谢。

评分

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

查看全部评分

回复

使用道具 举报

12#
ID:388197 发表于 2018-10-16 10:15 | 只看该作者
yong761228 发表于 2018-10-15 21:03
师傅,您好,您的程序我用STC15W404as 单片机,改了端口sbit relay = P3^6;   sbit key = P3^2;  就是不 ...

IO口配置有没有设置成浮空?
另外单片机IO口不要直接去接继电器,接个三极管,用三极管去驱动继电器.如果接的是NPN型的,那么IO口为1时是吸合,为0则断开.

评分

参与人数 2黑币 +28 收起 理由
飞线 + 8 很给力!
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

13#
ID:272609 发表于 2018-10-16 14:15 | 只看该作者
本帖最后由 飞线 于 2018-10-16 21:59 编辑
cjm82 发表于 2018-10-13 14:33
随便写的,下载到板子上试了试没问题,1分钟 5分钟时间太长,我改成5秒 25秒,你只要改下数字就行.
#include
...

cjm82你好,你写的程序我都记下了,我不是简单的复制粘贴,而是每一行都认真的读了一遍,大概理解后,然后自己写到Keil里面。
我感觉你写的程序简单易懂,条理清晰,嗯,让我印象比较深刻的是按键的延时消抖,原来不光是只有一种消抖的办法,还有其他的办法进行消抖。
然后就是按键按下去以后的几个状态,你这里面声明了几个变量,以前我看别人写的时候,这一部分我是看不懂的,他们这边写了一个标志位flag,我感觉你声明的几个状态变量,和这个标志位的意思是相同的,在这里我感觉我是看懂的,再次谢谢你
另外,我把这个程序修改、编译,然后下载到郭天祥的开发版中,目前是不能正常运行的,估计后续是需要进一步修改,因为他外围有很多拓展的硬件,谢谢啦,你让我们这些菜鸟又学到了东西

评分

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

查看全部评分

回复

使用道具 举报

14#
ID:272609 发表于 2018-10-16 14:16 | 只看该作者
angmall 发表于 2018-10-13 16:18
我给你来个程序试试

谢谢你的分享,前面一位老师已经分享了程序,我这里面正在研究他这个每一行的意思,后续等研究明白了,我再看看你这个程序
回复

使用道具 举报

15#
ID:272609 发表于 2018-10-16 14:19 | 只看该作者
yzwzfyz 发表于 2018-10-14 21:14
学了这么久,这么简单的问题还搞不定,建议改行!改行不是坏事,找一个更合适自己的乃是不错的选择。

与其批评别人有多菜,不如写几行代码试试,让别人看看你的水平有多高。
不是干这一行的,完全的业余爱好,再牛的人不也是从菜鸟成长起来的吗
回复

使用道具 举报

16#
ID:245473 发表于 2018-10-16 15:55 | 只看该作者
学了这么久,这么简单的问题还搞不定
回复

使用道具 举报

17#
ID:47286 发表于 2018-10-16 17:05 | 只看该作者
飞线 发表于 2018-10-16 14:19
与其批评别人有多菜,不如写几行代码试试,让别人看看你的水平有多高。
不是干这一行的,完全的业余爱好 ...

这人水平不低 虽然我没见过也不认这人 仅聊过天 反正比我强很多

我开始学单片机比你还晚 我也比你岁数大 能理解学习的艰难 但人确实各有所长 学不会不一定是笨 也许就是不适合搞这方面而已 不管原因是什么 在技术领域 我们不如别人就不能因为别说说了什么而较劲

看你前面回复都很客气 专门抽时间给你写了完整的程序 但没编译也没测试 不知道会有什么问题 你试试吧

#include <stc15w.h>                                //包括 stc15w系列头文件(起动1T模式)

#define uchar unsigned char                //字符型宏
#define uint unsigned int                //整型宏

sbit relay = P?^?;              //定义你所用的端口
                                                                //--!!注意驱动方式 是高有效还是低有效 是否需要置成推挽 硬件电路不同程序会不同!!--
                                                                //--!!所以 有可能你的继电器不工作!!--
sbit key = P?^?;                //定义你所用的端口 置成准双向即可 或不设置 复位后默认即准双向模式

bit flag_on1=0;                                        //声明 1分钟延时开始标记
bit flag_on5=0;                                        //声明 5分钟延时开始标记
bit flag_key=0;                                        //声明 按键检测标记

uint numrelay=0;                                //声明 临时变量 继电器延时计数器
uchar numshark=0;                                //声明 临时变量 按键防抖计数器

void Init_T0(void)                                //定时器中断初始化 1T/5ms
{
        AUXR |= 0x80;                                //定时器时钟1T模式        (1000 0000)
        TMOD |= 0x01;                                //设置 定时器模式        (0000 0001)
        TL0 = 0x00;                                        //设置 定时初值                5ms初值
        TH0 = 0x28;                                        //设置 定时初值                5ms初值
        TF0 = 0;                                        //清除 TF0标志
        TR0 = 1;                                        //打开 定时器0计时
        ET0 = 1;                                        //打开 计时器0中断
        EA  = 1;                                        //打开 总中断控制
}

void Server_Time0() interrupt 1        //中断1服务 1T时钟
{
        static uchar numt01;                //5ms到1s

        TL0 = 0x00;                                        //赋值 T0低位初值
        TH0 = 0x28;                                        //赋值 T0高位初值

        numt01++;                                        //自加 临时计数器01
        numshark++;                                        //自加 计数器shark

        if(numt01==200)                                //如果 临时计数器01达到设定值(5ms转1s)
        {
                numt01=0;                                        //清零 临时计数器01
                numrelay++;                                        //自加 计数器relay
        }
}

void Delay(uchar x)                //延时函数 按键防抖用 1x=1ms 在中断服务里加个计数器即可
{
        numshark=0;
        while(numshark<x);
}

void main(void)
{
    Init_T0();                                //初始化 定时器中断
   
        relay = ?;              //继电器端口是置位还是清零取决于你所用的驱动方式 比如P管是低有效就置位 N管是高有效就应该清零

    while(1)
    {
         if(key==?                        //如果 按键按下(不知道你的按键是高触发还是低触发 高触发=1 低触发=0)
                 &&flag_key==0)                //并且 按键标记=0
                 {
                         Delay(4);                        //延时20ms
                        if(key==?)                        //如果 按键依旧按下(即 防抖)
                        {
                                flag_on1=1;                        //置位 1分钟延时开始标记
                                flag_key=1;                        //置位 按键标记(不再进入按键检测 防止反复按键检测)
                                numrelay=0;                        //清零 计数器relay
                        }
                 }

                 if(flag_on1==1                        //如果 1分钟延时标记=1
                 &&numrelay>=60)                //并且 计数器relay达到设定值 60s
                 {
                        flag_on1=0;                                //清零 1分钟延时开始标记 防止再进入
                        flag_on5=1;                                //置位 5分钟延时开始标记
                        relay=?;                                //打开 继电器
                        numrelay=0;                                //清零 计数器relay
                 }

                 if(flag_on5==1                        //如果 5分钟延时标记=1
                 &&numrelay>=300)                //如果 计数器relay达到设定值 300s
                 {
                        relay=~relay;                        //关闭 继电器
                        flag_on5=0;                                //清零 5分钟延时开始标记
                        flag_key=0;                                //清零 按键检测标记(可以再次检测按键)
                 }
    }
}

评分

参与人数 3黑币 +48 收起 理由
yong761228 + 10 很给力!
admin + 30 回帖助人的奖励!
飞线 + 8 很给力!

查看全部评分

回复

使用道具 举报

18#
ID:405193 发表于 2018-10-17 07:23 | 只看该作者
dzbj 发表于 2018-10-16 17:05
这人水平不低 虽然我没见过也不认这人 仅聊过天 反正比我强很多

我开始学单片机比你还晚 我也比你岁数 ...

非常感谢师傅
回复

使用道具 举报

19#
ID:405193 发表于 2018-10-17 07:37 | 只看该作者
cjm82 发表于 2018-10-16 10:15
IO口配置有没有设置成浮空?
另外单片机IO口不要直接去接继电器,接个三极管,用三极管去驱动继电器.如果接 ...

非常谢谢师傅,您的程序没有任何问题,我还会改写功能,硬件电路我懂。我只是对 “angmall ” 师傅的程序没有看懂,实验没有成功。
回复

使用道具 举报

20#
ID:65956 发表于 2018-10-17 08:33 | 只看该作者
这个不是很简单吗,用1个定时器就可以搞定了,或不用定时器也可以搞定
回复

使用道具 举报

21#
ID:405193 发表于 2018-10-17 21:28 | 只看该作者
各位师傅,我这个自锁程序有问题,遥控器ABCD 按每个按钮都出现对应的按键码Key-d(相当于波形,短时间里有许多相同的波形),D3 D2 D1 D0 是四个继电器,按住或者按一下遥控器按钮A,D3一直吸合,松开遥控器按钮A,再次按遥控器按钮A,D3断开;同理其它BCD也一样。我现在这样写程序出现按住遥控器按钮A, D3继电器不停的吸合 断开。看看哪位师傅帮我修改一下程序,谢谢。

if(key_d == 0x08){D3=~D3;} //当按键码是0x08的时候,D3继电器取反,问题出现在短时间里有许多个0x08 出现,就出现了不停的吸合 断开。我用了延时程序,问题是延时程序过了还是出现这问题,因为可以一直按遥控器按钮,超过延时的时间有出现同样的问题。
if(key_d == 0x04){D2=~D2;}
if(key_d == 0x02){D1=~D1;}
if(key_d == 0x01){D0=~D0;}       

评分

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

查看全部评分

回复

使用道具 举报

22#
ID:280876 发表于 2018-10-18 09:18 | 只看该作者
yong761228 发表于 2018-10-17 21:28
各位师傅,我这个自锁程序有问题,遥控器ABCD 按每个按钮都出现对应的按键码Key-d(相当于波形,短时间里有 ...

你按键扫描是怎么样的,发上来看看
回复

使用道具 举报

23#
ID:405193 发表于 2018-10-18 18:57 | 只看该作者
wushiye54 发表于 2018-10-18 09:18
你按键扫描是怎么样的,发上来看看

师傅,您好,已经有人帮我改好了,谢谢。
回复

使用道具 举报

24#
ID:272609 发表于 2018-10-19 17:43 | 只看该作者
angmall 发表于 2018-10-13 16:18
我给你来个程序试试

老大,看了你的代码,感觉你是计算机专业的科班出身,程序写的很精练,所要实现的功能也能达到,但是对我们这些初学者来说,还是有一些难度,就比如这一句“if((StartRelay ==0) &&(Sec - StartSec >= Relay_on_Interval))”,我是看了两分钟才明白,要不是没看C语言的书籍,我估计我还看不懂的。
最后感谢你的回复和代码,我再仔细看看,还是能学到东西的。
回复

使用道具 举报

25#
ID:272609 发表于 2018-10-19 17:44 | 只看该作者
Y_G_G 发表于 2018-10-13 19:31
C我不会,汇编的话可以教你一下,我也是从什么都不会开始自学的,也是走了很多的弯路

你都会汇编了,那C语言对你来说就是小儿课了
回复

使用道具 举报

26#
ID:272609 发表于 2018-10-19 17:45 | 只看该作者
本帖最后由 飞线 于 2018-10-19 20:38 编辑
wushiye54 发表于 2018-10-15 17:14
老哥,改行吧。都几年了还是这样

弟,哥纯属业余爱好,一边工作一边学习单片机。
回复

使用道具 举报

27#
ID:272609 发表于 2018-10-19 17:54 | 只看该作者
yong761228 发表于 2018-10-15 20:07
楼主努力,我也是最近才开始学单片机编程,我都40多岁了,我都不怕,加油!

加油,我感觉我都快入门了
回复

使用道具 举报

28#
ID:272609 发表于 2018-10-19 17:57 | 只看该作者
hong19851024 发表于 2018-10-16 15:55
学了这么久,这么简单的问题还搞不定

哈哈,让你见笑了
回复

使用道具 举报

29#
ID:272609 发表于 2018-10-19 18:12 | 只看该作者
dzbj 发表于 2018-10-16 17:05
这人水平不低 虽然我没见过也不认这人 仅聊过天 反正比我强很多

我开始学单片机比你还晚 我也比你岁数 ...

谢谢你的代码,写了这么多行,一定占用了你不少的时间,再次谢谢你。我是初学者,学习的是51的单片机,买的是郭天祥的开发板,从头到尾看了你的程序,感觉是可行的。
因为我不是STC15系统的开发板,再加上我想加入一些扩展功能,所以没有下载进去。
if(flag_on1==1  &&numrelay>=60)//如果 1分钟延时标记=1,这个是也在学了C语言的书后,看到了,另外对标志位flag的用法,也有了一些概念。
                  
回复

使用道具 举报

30#
ID:47286 发表于 2018-10-20 11:33 | 只看该作者
飞线 发表于 2018-10-19 18:12
谢谢你的代码,写了这么多行,一定占用了你不少的时间,再次谢谢你。我是初学者,学习的是51的单片机,买 ...

不用客气

各人有自己的情况 所以别人写的东西细节上肯定满足不了 我提供的也只是个思路 能帮到你就好
回复

使用道具 举报

31#
ID:405193 发表于 2018-10-21 23:37 | 只看该作者
各位师傅,帮我看看下面的程序怎么写,我刚学,水平有限,非常感谢。
   //  电机正反转互锁的,就是通电一秒电机正转relay1吸合,到了行程终点或限位开关K2停止,
                   //再通电一秒电机反转relay2吸合,到了另一边限位开关K3停止
#include <reg52.h>
sbit relay1 = P1^3;              //继电器,0线圈吸合,1线圈断开
sbit relay2 = P1^4;  
sbit key1 = P3^7;                //按键,0为按下,1为松开
sbit k2 = P3^1;                                           //relay1 停止;K2=0时,relay1 是断开的,K2=1时,relay1才能吸合
sbit k3 = P3^0;                                           // relay2 停止;K3=0时,relay2 是断开的,K3=1时,relay2才能吸合
unsigned char key_timer_cnt;    //检测按键计时变量
unsigned char relay_state;       //记录继电器状态 0=未触发 1=待吸合 2=待断开

        

void main(void)
{
        P1=0xFF;
                P3=0xFF;
        Init_T0();
        relay1 = 1;                         //断开继电器
        relay2 = 1;   
                relay_state = 0;               //继电器处于未触发状态
        while(1)
        {
                                   //想实现其他功能,再这里添加代码
        }
}
void T0_ISR() interrupt 1              //1毫秒
{
        TH0 = 0xfc;
        TL0 = 0x18;
//***************************待触发状态,需要做的只是判断按键有没有按下*******************
        if(relay_state == 0)                //当继电器处于待触发状态
        {
                if(key1 == 0)                      //按键按下,并且继电器处于未触发状态
                {
                                         key_timer_cnt++;                                  //按键计时器自加,用于消抖
                        if(key_timer_cnt>=5)                              //按键超过5毫秒
                        {
                            key_timer_cnt = 0;                          
                                 
                        }else
                {
                        key_timer_cnt = 0;
                }
                        }
            }
        //****请教是否下面程序怎么写,谢谢!*********************************************
               //三种状态:
                //第一种:  K2=1并且K3=1        (相当于电机不在两边,在中间任何位置)
                //    触发Key1=0    relay1=0,relay2=1,到达限位后停止  K2=0, relay1=1,
            //第二种: K2=0并且K3=1        (相当于电机在一边限位上)
                //          触发Key1=0         relay1=1,relay2=0,到达限位后停止  K3=0, relay2=1,
                // 第三种: K2=1并且K3=0        (相当于电机在另外一边限位上)
                //          触发Key1=0         relay1=0,relay2=1,到达限位后停止  K2=0, relay1=1,

}      
回复

使用道具 举报

32#
ID:405193 发表于 2018-10-22 08:16 | 只看该作者
                   //  电机正反转互锁的,就是通电一秒电机正转relay1吸合,到了行程终点或限位开关K2停止,
                   //再通电一秒电机反转relay2吸合,到了另一边限位开关K3停止
#include <reg52.h>
sbit relay1 = P1^3;              //继电器,0线圈吸合,1线圈断开
sbit relay2 = P1^4;  
sbit key1 = P3^7;                //按键,0为按下,1为松开
sbit k2 = P3^1;                                           //relay1 停止;K2=0时,relay1 是断开的,K2=1时,relay1才能吸合
sbit k3 = P3^0;                                           // relay2 停止;K3=0时,relay2 是断开的,K3=1时,relay2才能吸合
unsigned char key_timer_cnt;    //检测按键计时变量
unsigned char relay_state;       //记录继电器状态 0=未触发 1=触发
void Init_T0(void)                  //定时器中断初始化,设置为1ms
{
    TMOD = 0x01;
    TH0 = 0xfc;
    TL0 = 0x18;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void main(void)
{
        P1=0xFF;
                P3=0xFF;
        Init_T0();
        relay1 = 1;                         //断开继电器
        relay2 = 1;   
                relay_state = 0;               //继电器处于未触发状态
        while(1)
        {
                                   //想实现其他功能,再这里添加代码
        }
}
void T0_ISR() interrupt 1              //1毫秒
{
        TH0 = 0xfc;
        TL0 = 0x18;
//***************************待触发状态,需要做的只是判断按键有没有按下*******************
        if(relay_state == 0)                //当继电器处于待触发状态
        {
                if(key1 == 0)                      //按键按下,并且继电器处于未触发状态
                {
                                                  relay1 = 1;                         //断开继电器
                          relay2 = 1;   
                                                  key_timer_cnt++;                    //按键计时器自加,用于消抖
                        if(key_timer_cnt>=10)                    //按键超过10毫秒
                        {
                            key_timer_cnt = 0;                          
                            relay_state = 1;      
                        }
                                               
                                }                else
                {
                        key_timer_cnt = 0;
                }
                         
            }
        //******各位师傅,帮我看看下面程序错在什么地方,三种情况选择:
                //状态1:         K2= 1并且K3=1 ,relay1 = 0;  直到K2=0,relay1 = 1; 并且返回 relay_state = 0;
                //状态2:          K2= 0并且K3=1 ,relay2 = 0;  直到K3=0,relay2 = 1; 并且返回 relay_state = 0;
                //状态3:          K2= 1并且K3=0 ,relay1 = 0;  直到K2=0,relay1 = 1; 并且返回 relay_state = 0;
                //*******************************************
      
                   if(         relay_state == 1)
                   {
                  
                       if((k2==1)&& (k3==1))
                                    {  relay1 = 0;  
                           if  (k2==0)
                                  {relay1 = 1; relay_state = 0; }
                                 }
                   else if((k2==0)&& (k3==1))
                                 {  relay2 = 0;   
                           if  (k3==0)
                                    {relay2 = 1; relay_state = 0; }
                          }
                   else if((k2==1)&& (k3==0))
                                 {  relay1 = 0;
                            if  (k2==0)
                                {relay1 = 1; relay_state = 0; }
                         }                                                 
                }
          
         
}      
回复

使用道具 举报

33#
ID:47286 发表于 2018-10-22 10:11 | 只看该作者
yong761228 发表于 2018-10-22 08:16
//  电机正反转互锁的,就是通电一秒电机正转relay1吸合,到了行程终点或限位开关K2停止,
                   //再 ...

你直接描述要干嘛吧 看别人程序想明白别人思路再给人家改 对我来说太难了 我懒 不如你说明白要干嘛直接重新写

你后边这逻辑貌似有问题 所有状态都返回相同结果 但不管什么时候都会满足其中一组条件 那就是说任何时候返回的都是相同结果
回复

使用道具 举报

34#
ID:216962 发表于 2018-10-22 11:21 | 只看该作者
飞线 发表于 2018-10-19 17:45
弟,哥纯属业余爱好,一边工作一边学习单片机。

说真的,我也是业余学习的。好多谢你们的分享,论坛有你们会更精彩!
回复

使用道具 举报

35#
ID:405193 发表于 2018-10-22 11:35 | 只看该作者
dzbj 发表于 2018-10-22 10:11
你直接描述要干嘛吧 看别人程序想明白别人思路再给人家改 对我来说太难了 我懒 不如你说明白要干嘛直接重 ...

师傅,您好,要实现的是这样的状态

//状态1:         K2= 1并且K3=1 ,relay1 = 0;  直到K2=0,relay1 = 1; 并且返回 relay_state = 0;
                //状态2:          K2= 0并且K3=1 ,relay2 = 0;  直到K3=0,relay2 = 1; 并且返回 relay_state = 0;
                //状态3:          K2= 1并且K3=0 ,relay1 = 0;  直到K2=0,relay1 = 1; 并且返回 relay_state = 0;
                //*******************************************
      
            
回复

使用道具 举报

36#
ID:405193 发表于 2018-10-22 11:41 | 只看该作者
dzbj 发表于 2018-10-22 10:11
你直接描述要干嘛吧 看别人程序想明白别人思路再给人家改 对我来说太难了 我懒 不如你说明白要干嘛直接重 ...

谢谢师傅: 电机正反转互锁的,就是通电一秒(key=0)电机正转(relay1=0)吸合,到了行程终点或限位开关(K2=0)停止,再通电一秒(key=0)电机反转(relay2=0)吸合,到了另一边限位开关(K3=0)停止
K2 K3 有三种状态:
//状态1:          K2= 1并且K3=1 ,relay1 = 0;  直到K2=0,relay1 = 1;
//状态2:          K2= 0并且K3=1 ,relay2 = 0;  直到K3=0,relay2 = 1;               
//状态3:          K2= 1并且K3=0 ,relay1 = 0;  直到K2=0,relay1 = 1;
回复

使用道具 举报

37#
ID:357520 发表于 2018-10-22 22:20 | 只看该作者
Y_G_G 发表于 2018-10-13 19:31
C我不会,汇编的话可以教你一下,我也是从什么都不会开始自学的,也是走了很多的弯路

可以写一下,最近也想学习一下汇编
回复

使用道具 举报

38#
ID:47286 发表于 2018-10-23 01:29 | 只看该作者
yong761228 发表于 2018-10-22 11:41
谢谢师傅: 电机正反转互锁的,就是通电一秒(key=0)电机正转(relay1=0)吸合,到了行程终点或限位开关(K2=0 ...

//谢谢师傅: 电机正反转互锁的,就是通电一秒(key=0)电机正转(relay1=0)吸合,
//到了行程终点或限位开关(K2=0)停止,再通电一秒(key=0)电机反转(relay2=0)吸合,到了另一边限位开关(K3=0)停止
//K2 K3 有三种状态:

uchar status=0;                //声明 状态变量
uchar bakup=0;                //声明 备份变量

bit flag_key=0;                //声明 按键标记
bit flag_run=0;                //声明 继电器运行标记

void key_status()        //止点扫描
{
//状态1:K2= 1并且K3=1 ,relay1 = 0;直到K2=0,relay1 = 1;
        if(key2==1                //如果 止点2=1
        &&key3==1)                //并且 止点3=1
        {
                status=1;                //赋值 状态=1
        }
//状态2:K2= 0并且K3=1 ,relay2 = 0;直到K3=0,relay2 = 1;
        if(k2==0                //如果 止点2=0
        &&k3==1)                //如果 止点3=1
        {
                status=2;                //赋值 状态=2
        }
//状态3:K2= 1并且K3=0 ,relay1 = 0;直到K2=0,relay1 = 1;
        if(k2==1                //如果 止点2=1
        &&k3==0)                //如果 止点3=0
        {
                status=3;                //赋值 状态=3
        }
}

void key_down()                //按键检测
{
        if(key==0                        //如果 按键按下
        &&flag_key==0)                //并且 按键标记=0
        {
                Delay(200);                        //延时1s
                if(key==0)                        //如果 按键依旧按下
                {
                        flag_key=1;                        //置位 按键标记
                        backup=status;                //赋值 备份变量=状态变量
                        flag_run=1;                        //置位 继电器运行标记
                }
        }
}

void  jk_run()                //继电器工作
{
        if(backup==status                //如果 备份变量=状态变量
        &&flag_run==1)                        //并且 继电器运行标记=1
        {
                switch (status)                //选择 状态
                {
                        case 1:                //状态1:正转
                                relay1=0;                //继电器1吸合
                                relay2=1;                //继电器2释放
                        break;
       
                        case 2:                //状态2:反转
                                relay1=1;                //继电器1释放
                                relay2=0;                //继电器2吸合
                        break;
       
                        case 3:                //状态3:正转
                                relay1=0;                //继电器1吸合
                                relay2=1;                //继电器2释放
                        break;
                }
        }
        else                                        //否则 即 备份变量!=状态变量(状态改变)
        {
                Delay(4);                                //延时20ms防抖
                if(backup!=status)                //如果 状态依旧改变中
                {
                        backup=0;                                //清零 备份变量
                        relay1=1;                                //继电器1释放
                        relay2=1;                                //继电器2释放
                        flag_key=0;                                //清零 按键标记
                        flag_run=0;                                //清零 继电器运行标记
                }
        }
}

void main()
{
        //初始化T0计时器(应该写成每5ms一个中断)

        while(1)
        {
                key_status();        //止点扫描
                key_down();                //按键检测
                jk_run();                //继电器工作
        }
}

评分

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

查看全部评分

回复

使用道具 举报

39#
ID:405193 发表于 2018-10-23 08:51 | 只看该作者
dzbj 发表于 2018-10-23 01:29
//谢谢师傅: 电机正反转互锁的,就是通电一秒(key=0)电机正转(relay1=0)吸合,
//到了行程终点或限位开 ...

非常感谢师傅。
回复

使用道具 举报

40#
ID:405193 发表于 2018-10-23 20:23 | 只看该作者
dzbj 发表于 2018-10-23 01:29
//谢谢师傅: 电机正反转互锁的,就是通电一秒(key=0)电机正转(relay1=0)吸合,
//到了行程终点或限位开 ...

师傅您好,我测试了一下,K2=0或者K3=0的时候触发key,继电器应该一直工作,到达对面开关,现在问题是继电器吸合离开K2或者K3就断开,没有一直运行到对面开关才断开,非常感谢您。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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