找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2910|回复: 0
收起左侧

做个18650锂电池供电倒计数计时器(电路图、程序)

[复制链接]
ID:67356 发表于 2019-4-22 22:04 | 显示全部楼层 |阅读模式
/*STC15W204;18650电池供电;频率:12M
T0-1ms作为计数基准 ;T2-20ms作为按键检测
P5.5 蜂鸣器
按下P3.0,设定增加;按下P3.1,设定减小 ;按下P3.2,储存设定数值;P3.3,开始/停止计数
四位数码管,使用中间两个(手头现有)
*/
/*
要求:
开机,读取预存倒计时数值,按压“开始”按钮,每秒数值减1,直到0终止,鸣笛2声提醒,恢复到开机等待状态;
再次按压“开始”,再次反复,,,;
任何时候,可以通过“+”“-”按钮调整初始值,按压“存储键”,数值被储存。
使用18650电池供电,带充电接口;
为节省电能,当等待时间大于5分钟后,自动关闭显示,进入掉电模式;可通过按压“开始”按键,恢复到开机等待状态
*/
QQ截图20190422220245.jpg


#include<STC15.H>
#include<intrins.h>
#define STC_Y1  97560U  // 89C/LEXX、90C/LEXX
#define STC_Y3  14050U  // 10F/Lxx、11F/Lxx 、12C/LExx、15F104E/L104E(A版)、15F204E/L204EA(A版)
#define STC_Y5  13043U  // 15F/L/Wxx(Y3内核个别型号除外)、15F104W
#define uchar unsigned char //宏定义字符型变量
#define uint  unsigned int        //宏定义整型变量
#define Fosc 12000000UL
#define Core STC_Y5
/********************************************************************
                            命令定义
*********************************************************************/
#define CMD_IDLE     0         //EEPROM无操作
#define CMD_READ     1         //读取字节
#define CMD_PROGRAM  2         //写入字节
#define CMD_ERASE    3         //擦除字节
/********************************************************************
                       编程周期由晶振决定
*********************************************************************/
//#define ENABLE_IAP 0X80         //编程周期由晶振决定(如果<30MHZ选用此项)
//#define ENABLE_IAP 0X81         //编程周期由晶振决定(如果<24MHZ选用此项)
//#define ENABLE_IAP 0X82         //编程周期由晶振决定(如果<20MHZ选用此项)
  #define ENABLE_IAP 0X83         //编程周期由晶振决定(如果<12MHZ选用此项)
//#define ENABLE_IAP 0X84         //编程周期由晶振决定(如果<6MHZ选用此项)
//#define ENABLE_IAP 0X85         //编程周期由晶振决定(如果<3MHZ选用此项)
//#define ENABLE_IAP 0X86         //编程周期由晶振决定(如果<2MHZ选用此项)
//#define ENABLE_IAP 0X87         //编程周期由晶振决定(如果<1MHZ选用此项)

#define IAP_ADDRESS 0X0000         //内部EEPROM地址

unsigned char code duanma[12]={0x3F,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x8c};//

sbit    led_2=P3^6;
sbit    led_3=P3^7;



sbit a6=P5^4;//g
sbit a5=P1^0;//f
sbit a4=P1^3;//e
sbit a3=P1^4;//d
sbit a2=P1^5;//c
sbit a1=P1^2;//b
sbit a0=P1^1;//a


sbit    buzzer=P5^5;
unsigned char pwm,pwmcun;
unsigned long counter;
unsigned char Trg;                          //点按
unsigned char Cont;                         //长按
unsigned char cnt_plus;                     //长按延时
unsigned char cnt_plus_time;                //长按速度
unsigned char start=0;                      //开始按键
/**
*  功能:延时t毫秒
*  入参:1~65535
*/
void delay_ms(unsigned int t)
{
    unsigned int i;
    do{
        i = Fosc / Core;
        while(--i);
    }while(--t);
}
/********************************************************************
                           掉电模式(无操作5分钟后关机省电)
*********************************************************************/
void kongxian()
{
PCON = 0x02; //MCU进入掉电模式
_nop_();
_nop_();
}
/********************************************************************
                            操作函数
*********************************************************************/
void IapIdle()
{
IAP_CONTR=0;
IAP_CMD=0;
IAP_TRIG=0;
IAP_ADDRH=0X80;
IAP_ADDRL=0;
}

/********************************************************************
                            读取一个字节函数
*********************************************************************/
uchar IapReadByte(uint addr)
{
uchar dat;  
IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_READ;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG=0X5A;
IAP_TRIG=0XA5;
_nop_();
_nop_();
_nop_();
dat=IAP_DATA;
IapIdle();
return dat;
}

/********************************************************************
                            写入一个字节函数
*********************************************************************/
void IapProgramByte(uint addr,uchar dat)
{

IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_PROGRAM;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_DATA=dat;
IAP_TRIG=0X5A;
IAP_TRIG=0XA5;
_nop_();
_nop_();
_nop_();
IapIdle();
}
/********************************************************************
                            擦除一个字节函数
*********************************************************************/
void IapEraseSector(uint addr)
{
IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_ERASE;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG=0X5A;
IAP_TRIG=0XA5;
_nop_();
_nop_();
_nop_();
IapIdle();
}


/**************************************
****************定时器初始化函数****************
**************************************/
void InitTimer(void)
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x18;                //设置定时初值
        TH0 = 0xFC;                //设置定时初值1ms
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
  ET0 = 1;  //T0中断使能

        AUXR &= 0xFB;                //定时器2时钟12T模式
        T2L = 0xE0;                //设置定时初值
        T2H = 0xB1;                //设置定时初值
        AUXR |= 0x10;                //定时器2开始计时
  IE2 |= 0x04; //T2使能
  EA = 1; //开总中断
       
  IT1 = 0; //0,上升沿和下降沿都能中断。
  EX1 =1; //使能INT1中断

}

/********************************数码管延时关断函数******************************************/
void guanduan (void)//用于关断数码管的位选
{
delay_ms(1);//延时
led_2=1;//关断百位
led_3=1;//关断十位
delay_ms(2);//延时
}
/********************************10us延时函数************************************************/
void delay_10us (unsigned int a)//24MHz时钟时的10微秒延时函数
{
unsigned int b;
while(a--)
{
  for(b=0;b<12;b++);
}
}
/********************************sound数************************************************/
void sound(unsigned int jj,ii ) //jj,时长;ii,频率
{
        unsigned int i;
        for(i=0;i<=jj*5;i++)
        {buzzer=~buzzer;
        if(buzzer)
{delay_10us(ii);}
else {delay_10us(ii-12);}
        }
       
        buzzer=0;
}
/********************************字段函数(显示)********************************************/
void ziduan(unsigned char a)
{
a6=a&0x40;//g
a5=a&0x20;//f
a4=a&0x10;//e
a3=a&0x08;//d
a2=a&0x04;//c
a1=a&0x02;//b
a0=a&0x01;//a
}
/********************************显示函数****************************************************/
void display(signed int a)//显示函数(显示实际数据除以10,支持显示负数,负数显示方式为百位显示负号"-"十位和个位显示数据)
{
  unsigned char shiwei,gewei,d;//定义十位,个位,每次显示帧数


        shiwei=a/10;//计算十位
  gewei=a%10;//计算个位
  for(d=0;d<20;d++)//显示部分,每次显示20个循环(20帧)
  {  
   ziduan(duanma[shiwei]);//显示十位
   led_2=0;//打开十位
   guanduan();//延时关断十位
   ziduan(duanma[gewei]);//显示个位
         led_3=0;//打开个位
   guanduan();//延时关断个位
         }
}

/**************************************
****************按键检测****************
**************************************/
void Key(void)
{
    unsigned char ReadData=P3^0xff;//若为0,表示没有按键
    Trg=ReadData&(ReadData^Cont);
    Cont=ReadData;
    if (Cont==0)
    {
        cnt_plus=0;     //长按标志清0
    }
                if (Trg&0x04)       //按下P3.2,00000100;储存当前数值
                 {
                         sound(50,17);
                         IapEraseSector(0X0000);                    delay_ms(5);
             IapProgramByte(0X0000,pwm);           delay_ms(5);
                         pwmcun=pwm;
                 }

               
                if (Trg&0x01)       //按下P3.0,00000001,设定增加
    {  
                          start=0;
        pwm++;
        if(pwm==99)
        {
            pwm=0;
        }
    }
    if (Trg&0x02)       //按下P3.1,00000010,设定减小
    {  
                                start=0;
        pwm--;
        if(pwm==0)
        {
            pwm=99;
        }
    }
       
                if(Trg&0x08)       //按下P3.3,00001000,计数/停止
                {
                        start=~start;
                        counter=0;
                        sound(50,17);
            pwm=pwmcun;
                }
               
    if (cnt_plus<50)
    {
        cnt_plus++;        //开始长按延时
    }
    if (cnt_plus>=50)     //长按1秒后开始动作
    {
        cnt_plus_time++;        //长按时速度变化
        if (cnt_plus_time>30)
        {
            cnt_plus_time=0;
            if (Cont&0X01)  //长按P1.3,连加5
            {
                if(pwm<=(pwmcun-10))
                {
                    pwm=pwm+5;
                }
                else
                {
                    pwm++;
                }

            }
            if (Cont&0X02)      //长按P1.4,连减5
            {
                if(pwm>=10)
                {
                    pwm=pwm-5;
                }
                else
                {
                    pwm--;
                }

            }
        }
    }
        }       



/**************************************
****************主函数***************
**************************************/
void main ()
{ start=0;
        sound(100,17);
        P5M0=0xff;//P5都是推挽模式
  P5M1=0x00;
        P1M0=0xff;//P1都是推挽模式
  P1M1=0x00;
  InitTimer();
       
        pwmcun=IapReadByte(0X0000);//读取设定起始数值
  delay_ms(5);
  pwm = pwmcun;
         buzzer=0;
         counter = 0 ;
   while(1)
    {

      display(pwm);
         }
}
/**************************************
****************T0中断,1ms用于倒计数****************
**************************************/
void Timer0Interrupt(void) interrupt 1
{
if(start)  //计数状态,T0用于倒计数
{
        counter++;
    if(counter==1000) //每秒(1000ms)倒计时1
    {
        counter = 0 ;
        pwm--;
                             if(pwm==0) //计数完成,滴滴2声,停止
       {
                                start=0;
                                led_2=led_3=1;
                                pwm=pwmcun;
                         sound(80,17);
                         delay_ms(100);
                         sound(80,17);
                                 delay_ms(400);
                                 sound(80,17);
                           delay_ms(100);
                           sound(80,17);
                         }   
    }
}
if(start==0) //倒计数结束后,T0用于延时关机
  {
                counter++;
        if(counter==300000)  //5分钟
        {               
                led_2=led_3=1;
                sound(300,17);
                start=~start;
          kongxian();
        }
}

}
/**************************************
****************T2中断,20ms用于检测按键****************
**************************************/
void t2int() interrupt 12
{
    IE2 &= ~0x04;               //关闭定时器T2
    Key();              //执行键盘扫描
    IE2 |= 0x04;                //启动定时器T2
}
void exint1() interrupt 2 //INT1中断入口
{
        counter=0;
}



评分

参与人数 2黑币 +62 收起 理由
YJGG + 12 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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