找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机有源蜂鸣器一次响声正常,一次响声很小?

[复制链接]
跳转到指定楼层
楼主
ID:171306 发表于 2017-3-16 19:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    我买的51单片机,想写一个程序,让他计时,并在还剩30秒时和结束时提醒(蜂鸣器响,是有源蜂鸣器),
     但是在还剩30秒时,不想,在结束时能响,请问这是为什么啊?




     下面是源程序,都是比较简单的语言,蜂鸣器部分用红色标出。


#include <reg52.h>                    //52系列单片机头文件     
#define uchar unsigned char

//申明变量和位口
sbit     K1=P3^4;     //对应按钮K1
sbit     K2=P3^5;    //对应按钮K2
            
sbit    dula=P2^6;     //段选申明
sbit    wela=P2^7;     //位选申明

sbit    beep=P2^3;        //蜂鸣器申明

unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  //0~9,A~F的16进制

void delayms(unsigned int xms);       //延时函数申明

unsigned char numt0=0,miao=0,fen=0,lunci=0;    //  计数变量

unsigned char CK1=0,CK2=0;   //串口接收变量(全局)




//延时函数
void delayms(unsigned int xms)                                
{
        unsigned int i,j;
        for(i=xms;i>0;i--)                      //i=xms即延时约xms毫秒
                for(j=112;j>0;j--);
}



//计时器初始化函数
void init()   
{

    //********计时器**********
        TMOD=0x21;                 //模式设置,00100001,可见采用的是定时器0,工作与模式1(M1=0,M0=1)。
        TR0=0;                         //不打开定时器
        TH0=(65536-46080)/256;// 由于晶振为11.0592,故所记次数应为46080,计时器每隔50000微秒发起一次中断。
        TL0=(65536-46080)%256;//46080的来历,为50000*11.0592/12
        ET0=1;                         //开定时器0中断
        EA=1;                         //开总中断


        //***************串口通信**********************
    TMOD=0X21;                        ////模式设置,00100001,可见采用的是定时器1,工作与模式1(M1=0,M0=1)
        SCON=0X50;                        //设置为工作方式1
        PCON=0X00;                        //0x00不加倍    0x80加倍
        TH1=0XFD;                    //计数器初始值设置,注意波特率是4800的
        TL1=0XF3D;                                                         
        ES=1;                                                //打开接收中断
        EA=1;                                                //打开总中断
        TR1=1;                                            //打开计数器                        

}



//数码管显示函数
void display(uchar fen1,uchar miao1)
{
        
        //*******分钟操作*********        
        unsigned char fenshi,fenge;
        unsigned char  miaoshi,miaoge;
        fenshi=fen1/10;
        fenge=fen1%10;
        
         
        dula=1;                //秒钟十位赋值   
        P0=table[fenshi];      
        dula=0;                 
       P0=0xff;               
        wela=1;
        P0=0xF7;
        wela=0;                 
        delayms(5);
               
        dula=1;                 //分钟十位赋值
        P0=table[fenge];
        dula=0;               
       P0=0xff;               
        wela=1;
        P0=0xEF;
        wela=0;               
        delayms(5);

        
        //********中间的一个横线*****
        dula=1;               
        P0=0x40;      
        dula=0;                 //打开段选位 .....秒钟个位赋值......关闭闭段选位
    P0=0xff;                //送段选数据前关闭所有所有显示,防止打开位选锁存器
        wela=1;
        P0=0xFB;
        wela=0;                 //打开段选位 、赋值、关闭闭段选位
        delayms(5);
        
        
        //*******秒钟操作*********        
        miaoshi =  miao1/10;
        miaoge  =  miao1%10;          //参数处理
            
        dula=1;               
        P0=table[miaoshi];      
        dula=0;                 //打开段选位 .....秒钟个位赋值......关闭闭段选位
    P0=0xff;                //送段选数据前关闭所有所有显示,防止打开位选锁存器
        wela=1;
        P0=0xFE;
        wela=0;                 //打开段选位 、赋值、关闭闭段选位
        delayms(5);
               
        dula=1;                 //秒钟十位赋值
        P0=table[miaoge];
        dula=0;               
       P0=0xff;               
        wela=1;
        P0=0xFD;
        wela=0;               
        delayms(5);        
}



//判断按键函数
unsigned char keyscan()
{
        unsigned char keyValue = 0; //保存键值

        if (K1==0)                        //检测按键K1是否按下
        {
                delayms(10);           //消除抖动

                if (K1==0)              //再次检测按键是否按下
                {
                        TR0=~TR0;        //启动或开始计时器******一开始时,这个按键按下去后才会启动
                          while(!K1);    //等待按键释放        
                }
        }
        if (K2==0)                //检测按键K1是否按下
        {
                delayms(10);        //消除抖动

                if (K2==0)        //再次检测按键是否按下
                {
                        miao=0;
                        fen=0;          //清零
                        lunci=0;         //清零同时,判别变量清零
                    while(!K2);    //等待按键释放        
                }
        }

        return keyValue;   //将读取到键值的值返回
}


//开始次一轮函数
void NextTurn ( unsigned char fenstop)
{        
        unsigned char m1;
        m1=fenstop;
        if(m1==CK1)                //当计时满CK1分钟时开始下一轮次
        {
                if (lunci==0)            //再次检测按键是否按下
                {
                        miao=0;
                        fen=0;              //清零
                        lunci=1;            //计次符号加1
                }
        }
}


//定时停止函数
void stop ( unsigned char fenstop)
{        
        unsigned char m1;
        m1=fenstop;
        if(m1==CK2)                //当计时满CK2分钟时计时停止(第二次记满时)
        {
                if (lunci==1)            //再次检测按键是否按下
                {
                           TR0=0;                                                //计时器停止
                        lunci=0;                 //判别变量清零
                }
        }
}



//蜂鸣器函数---提醒
void FengMing1(unsigned char CK11,unsigned char CK22)       //蜂鸣器为无源蜂鸣器,需要变频才能发声
{


        if((fen==CK11-1)&&(lunci==0)||(fen==CK22-1)&&(lunci==1))                    //4分钟的时候响
        {        
            if((miao>30)&&(miao<33))                  //分钟的时候响
                         beep = 0;
                else
                    beep= 1;
        }
}


//蜂鸣器函数---终止
void FengMing2(unsigned char CK11,unsigned char CK22)    //蜂鸣器为无源蜂鸣器,需要变频才能发声
{
        if((fen==CK11-1)&&(lunci==0)||(fen==CK22-1)&&(lunci==1))                    //4分钟的时候响
        {        
            if((miao>56)&&(miao<59))                    //4分钟的时候响
                         beep = 0;
                else
                    beep = 1;
        }
}


                        
                                
//主函数
void main()
{


        init();//初始化函数
        while(1)
        {
                keyscan();
                display(miao,fen);          //传递给秒表
                NextTurn(fen);         
                stop(fen);            //调用停止函数
                FengMing1(CK1,CK2);   //调用蜂鸣器提醒函数
                FengMing2(CK1,CK2);   //调用蜂鸣器提醒函数   
        }
}


//计时器中断函数
void time0() interrupt 1
{
        TH0=(65536-46080)/256;// 由于晶振为11.0592,故所记次数应为46080,计时器每隔50000微秒发起一次中断。
        TL0=(65536-46080)%256;//46080的来历,为50000*11.0592/12
        numt0++;        
        if(numt0==20)                //如果到了20次,说明1秒时间到
        {
                numt0=0;                //然后把num清0重新再计20次
                miao++;
                if(miao==60)
                {
                        miao=0;
                        fen++;      //分钟计时器开始计时
                        if(fen==60)
                                fen=0;
                }
        }               
}


//串口中断函数
void Usart() interrupt 4
{
        unsigned char receiveData;
        receiveData=SBUF;   //出去接收到的数据
        CK1=receiveData/16;    //赋值给全局变量
        CK2=receiveData%16;
        if ((CK1*16+CK2)==receiveData)

                SBUF=6;   //将接收到的数据放入到发送寄存器

        RI = 0;           //清除接收中断标志位
        while(!TI);                  //等待发送数据完成
        TI=0;                          //清除发送完成标志位
}



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2017-3-16 21:28 | 只看该作者
自己设置断点,看看在还剩余30秒时,你的CPU在干什么?

评分

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

查看全部评分

回复

使用道具 举报

板凳
ID:171306 发表于 2017-3-24 23:32 | 只看该作者
yzwzfyz 发表于 2017-3-16 21:28
自己设置断点,看看在还剩余30秒时,你的CPU在干什么?

我又改了下判别方法,这次换成还剩30秒时响,但最后不响了。。。是不是调用蜂鸣器的程序有问题啊
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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