STC15单片机可设置倒计时(0~9999)报警器+Proteus仿真

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STC15单片机可设置倒计时(0~9999)报警器+Proteus仿真相关的知识,希望对你有一定的参考价值。

STC15单片机可设置倒计时(0~9999)报警器+Proteus仿真


  • Proteus仿真

程序代码


/*------------------------------------------------------------------*/
/* --- STC MCU International Limited -------------------------------*/
/* --- STC 1T Series MCU RC Demo -----------------------------------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ---------------------*/
/* --- Web: www.GXWMCU.com -----------------------------------------*/
/* --- QQ:  800003751 ----------------------------------------------*/
/* If you want to use the program or the program referenced in the  */
/* article, please specify in which data and procedures from STC    */
/*------------------------------------------------------------------*/


#include	"config.h"
#include	"GPIO.h"
#include	"delay.h"

/*************	功能说明	**************

本程序演示跑马灯。
程序使用P2口来演示,输出低驱动。用户可以修改为别的口。

******************************************/

/*************	本地常量声明	**************/
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
#define s8 signed char
#define s16 signed int
#define s32 signed long
#define KEY_TIME 25                        //按键消抖时间 (毫秒)
#define reset()        IAP_CONTR |= 0x20                //芯片复位
#define feed_dog()  WDT_CONTR |= 0x10   //看门狗喂狗
u8 code nbr[16] = {                //共阴数码管段码16进制
    0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};
u8 show[4];                //4位数码管当前显示的段码 更改数码管显示的段码 只需更改此数组
u8 wink;                //闪烁的数码管段码        0x01: 第一位闪烁 0x02:第二位闪烁 0x04: 第三位闪烁 0x0F:全闪烁 0x00:全不闪烁

sbit P3_0 = P3 ^ 0;                //按键S1 (I/O口定义的按键未经消抖,请勿在中断外直接使用)
sbit P3_1 = P3 ^ 1;                //按键S2
sbit P3_2 = P3 ^ 2;     //有源蜂鸣器 低电平鸣叫
sbit P3_3 = P3 ^ 3;     //继电器或MOS管 低电平吸合(导通)
u16 S1_ms, S2_ms;                //按键0、按键1连续按下的时间 定时器中断计数此变量 最长65535毫秒 松开清零

u16 delayms;  //定时器中断延时 (毫秒)
u16 time;      //定时时间 (秒)
u16 beep_ms;   //蜂鸣器鸣叫时间 (毫秒)

u16 bdata Bit16 = 0;    //定义16位可位寻址变量
sbit delay = Bit16 ^ 0;      //定时器中断延时毫秒开关 中断外置1 延时完中断内清0
sbit test = Bit16 ^ 1;       //此值为1数码管全亮 蜂鸣器响 所有按键无效 否则正常
sbit S1 = Bit16 ^ 2;         //按键0 连续按下N毫秒清0, 松开置1(定时器0中断消抖)
sbit S2 = Bit16 ^ 3;         //按键1 (处理方式与按键0相同)
sbit hz10 = Bit16 ^ 4;      //10Hz信号源 (定时器0中断产生,用于控制数码管闪烁)
sbit bak = Bit16 ^ 5;       //按键长按识别处理用
sbit Beep = Bit16 ^ 6;      //有源蜂鸣器 低电平响
sbit start = Bit16 ^ 7;     //倒计时开关 置1倒计时开始 清0则结束
sbit pause = Bit16 ^ 8;     //1暂停倒计时 0正常
sbit relay = Bit16 ^ 9;     //继电器或MOS管 低电平吸合(导通) 1秒只能吸合或释放1次

/*************	本地变量声明	**************/


/*************	本地函数声明	**************/



/*************  外部函数和变量声明 *****************/
void InitTimer0() {        //初始化定时器0中断
    TMOD = 0x01;
    TH0 = 0xFC;
    TL0 = 0x18;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void beep(u16 ms) {     //蜂鸣器鸣叫 参数:鸣叫毫秒
    beep_ms = ms;
    Beep = 0;
}

u16 set_time() {        //设定定时时间
    u8 n = 0;       //0:编辑千位 1:百位 2:十位 3:个位
    u8 o[4];
    o[0] = 0; o[1] = 0; o[2] = 0; o[3] = 0;
    while (1) {
        feed_dog();
        wink = 8 >> n;
        show[0] = nbr[o[0]];
        show[1] = nbr[o[1]];
        show[2] = nbr[o[2]];
        show[3] = nbr[o[3]];
        if (S2 == 0) {                        //S2按下 短按加1
            beep(50);
            if (o[n]++ >= 9) o[n] = 0;
            show[n] = nbr[o[n]];
            delayms = 500; delay = 1;
            while (delay && S2 == 0);        //长按延时等待
            while (S2_ms >= 500) {                //按键长按,开始连加
                feed_dog();
                delayms = 125; delay = 1;                //0.125秒连加一次
                while (delay && S2 == 0);
                beep(50);
                if (o[n]++ >= 9) o[n] = 0;
                show[n] = nbr[o[n]];
            }
            delay = 0;
            delayms = 0;
        }

        if (S1 == 0) {                //S1按下
            beep(50);
            n++;                //输入下一位
            while (S1 == 0) {
                feed_dog();
                if (S1_ms >= 1000 && !bak) {                //长按退回编辑
                    beep(50);
                    n = 0;
                    wink = 8 >> n;
                    show[0] = nbr[o[0]];
                    show[1] = nbr[o[1]];
                    show[2] = nbr[o[2]];
                    show[3] = nbr[o[3]];
                    bak = 1;
                }
            }

            if (bak) {
                bak = 0;
                continue;
            }

            if (n >= 4) {                //个位输入完成
                wink = 0;
                return o[0] * 1000 + o[1] * 100 + o[2] * 10 + o[3];

            }
        }
    }
//    return 0;
}


/******************** IO配置函数 **************************/
void	GPIO_config(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
	GPIO_InitStructure.Pin  = GPIO_Pin_All;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);	//初始化
}



/******************** 主函数 **************************/
void main(void)
{
	 u8 i = 0;
    Beep = 1;
    WDT_CONTR = 0x27;           //初始化看门狗
    P1M0 = 0x0F; P1M1 = 0x00;   //P1.0~P1.3强推挽
    P2M0 = 0xFF; P2M1 = 0x00;   //P2.0~P2.7强推挽
    //上电1秒数码管全亮 蜂鸣器响
    test = 1;
		GPIO_config();
    InitTimer0();
    delayms = 1000; delay = 1;
    while (delay);
    test = 0;

    show[0] = nbr[0];
    show[1] = nbr[0];
    show[2] = nbr[0];
    show[3] = nbr[0];
	while(1)
	{
relay = 1;
        pause = 0;
        do {        //时间设定
            time = set_time();
        } while (!time);
        time -= 1;
        start = 1;
        relay = 0;
        while (start) {
            feed_dog();
            if (S1 == 0) {      //S1按下蜂鸣器响1下
                beep(50);
                while (S1 == 0) {
                    feed_dog();
                }
            }

            if (S2 == 0) {      //S2按下暂停倒计时
                beep(50);
                pause = !pause;
                relay = pause;
                while (S2 == 0) {
                    feed_dog();
                    if (pause && S2_ms >= 3000) {       //长按3秒复位
                        _nop_(); _nop_(); _nop_(); _nop_();
                        reset();
                        _nop_(); _nop_(); _nop_(); _nop_();
                    }
                }
            }

        }
        //倒计时结束
        show[0] = 0x79;     //E
        show[1] = 0x54;     //n
        show[2] = 0x5E;     //d
        show[3] = 0x00;
        for (i = 0; i < 6; i++) {       //蜂鸣器响6下
            delayms = 500; delay = 1; while (delay);
            beep(500);
            while (!Beep);
            feed_dog();
        }

        while (1) {
            feed_dog();
            if (S1 == 0 || S2 == 0) {
                beep(50);
                while (S1 == 0 || S2 == 0) {
                    feed_dog();
                }
                break;
            }
        }
	}
}

void Timer0Interrupt() interrupt 1{         //12Mhz 1mS定时器中断
    static u8 seg = 0;  //当前正在扫描的数码管段码 4位数码管 范围:0~3
    static u8 ms1 = 0;
    static u16 ms = 0, ms2 = 0;
    TH0 = 0xFC;
    TL0 = 0x18;
    if (delay && !--delayms) {    //延时任意毫秒
        delay = 0;
    }
    //数码管动态扫描处理
    P1 |= 0xF;          //消影
    P2 = test ? 0xFF : (wink & (1 << (3 ^ seg)) && !hz10 ? 0 : show[seg]);      //段码
    P1 &= ~(1 << seg);   //位码
    if (++seg >= 4) seg = 0;

    if (test) {     //测试模式
        S1 = 1; S2 = 1;
        P3_2 = 0;
        return;
    }

    //蜂鸣器处理
    P3_2 = Beep;
    if (!Beep && !--beep_ms) {
        Beep = 1;
    }
    if (++ms1 >= 50) {
        ms1 = 0;
        hz10 = !hz10;
    }

    //按键处理
    if (P3_0 == 0) {
        if (S1_ms != 0xFFFF) S1_ms++;
    }
    else {
        S1_ms = 0;
    }

    if (P3_1 == 0) {
        if (S2_ms != 0xFFFF) S2_ms++;
    }
    else {
        S2_ms = 0;
    }

    S1 = !(S1_ms >= KEY_TIME);
    S2 = !(S2_ms >= KEY_TIME);
    //继电器处理
    if (++ms2 >= 1000) {    //继电器1秒只能进行1次吸合或释放,防止频繁开关导致设备损坏
        ms2 = 0;
        P3_3 = relay;
    }
    //时间倒计时处理
    if (start) {
        if (pause) {
            wink = 0xF;
        }
        else {
            wink = 0;
            if (++ms >= 1000) {
                ms = 0;
                show[0] = nbr[time / 1000 % 10];
                show[1] = nbr[time / 100 % 10];
                show[2] = nbr[time / 10 % 10];
                show[3] = nbr[time % 10];

                if (!time--) {      //倒计时结束
                    start = 0;
                    relay = 1;
                }
            }
        }
    }
}



程序源码和仿真资源

链接:https://pan.baidu.com/s/1DjhHyl_yG3VP1gXn8rU5iQ 
提取码:07fx

以上是关于STC15单片机可设置倒计时(0~9999)报警器+Proteus仿真的主要内容,如果未能解决你的问题,请参考以下文章

基于51单片机交通灯设计时间可设置仿真红绿灯十字路口

燃太TN901红外测温模块LCD1602显示

STC15单片机定时器0工作模式介绍

单片机STC15定时器(1)中断,数码管自动加1的电子钟,为啥不自动加1

基于51单片机交通灯设计时间可设置仿真红绿灯十字路口

基于51单片机交通灯设计时间可设置仿真红绿灯十字路口