×
关于关于关于1. 如何学习单片机7. LED 点阵的学习13.1602 液晶与串口的应用1.1 学习什么单片机7.1 C 语言变量的作用域13.1 通信时序解析1.2 如何学习单片机7.2 C 语言变量的存储类别13.2 1602 整屏移动1.3 单片机学习的准备工作7.3 LED 点阵的介绍13.3 多个 .c 文件的初步认识1.4 单片机开发环境搭建--Keil uVision4安装教程7.4 LED 点阵的图形显示13.4 单片机计算器实例1.5 Keil uVision4 简单使用教程7.5 LED 点阵的纵向移动13.5 串口通信原理和控制程序第一章问题汇总7.6 LED 点阵的横向移动14. I2C 总线与 EEPROM2. 点亮你的 LED 灯8. 单片机按键14.1 单片机 I2C 时序介绍2.1 单片机内部资源8.1 单片机最小系统解析14.2 I2C 寻址模式2.2 单片机最小系统8.2 C 语言函数的调用14.3 单片机 EEPROM 简介2.3 发光二极管(LED 灯)8.3 C 语言函数的形参和实参14.4 EEPROM 单字节读写操作时序2.4 特殊功能寄存器和位定义8.4 单片机按键介绍14.5 EEPROM 多字节读写操作时序2.5 新建一个工程8.5 ​单片机独立按键扫描程序14.6 EEPROM 的页写入2.6 第一个单片机程序8.6 单片机按键消抖程序14.7 I2C 和 EEPROM 的综合编程2.7 将程序下载到单片机8.7 单片机矩阵按键的扫描15. 实时时钟 DS13023. 单片机硬件基础知识学习8.8 简易加法计算器程序15.1 BCD 码介绍3.1 电磁干扰 EMI9. 步进电机与蜂鸣器15.2 单片机 SPI 通信接口3.2 单片机中去耦电容的应用9.1 单片机 IO 口的结构15.3 实时时钟芯片 DS1302 介绍3.3 三极管的的概念及其工作原理9.2 单片机上下拉电阻15.4 DS1302 的硬件信息3.4 单片机中三极管的应用9.3 电机的分类15.5 DS1302 寄存器介绍3.5 74HC138 三八译码器的应用9.4 28BYJ-48 步进电机原理15.6 DS1302 通信时序介绍3.6 LED 灯闪烁程序9.5 让电机转起来15.7 DS1302 的 BURST 模式4. 流水灯的实现9.6 转动精度与深入分析15.8 C 语言复合数据类型4.1 二进制、十进制和十六进制9.7 电机控制程序基础15.9 单片机电子时钟程序设计4.2 C 语言变量类型和范围9.8 实用的电机控制程序16. 红外通信与温度传感器4.3 C 语言基本运算符9.9 单片机蜂鸣器16.1 红外光的基本原理4.4 C 语言 for 循环语句10. 实例练习与经验积累16.2 红外遥控通信原理4.5 C 语言 while 循环语句10.1 单片机数字秒表程序16.3 NEC 协议红外遥控器4.6 C 语言函数的简单介绍10.2 PWM 的原理与控制程序16.4 温度传感器 DS18B204.7 单片机延时方法10.3 单片机交通灯实例17. 模数转换与数模转换4.8 LED 流水灯程序10.4 51单片机 RAM 区域的划分17.1 A/D 和 D/A 的基本概念5. 定时器与数码管基础10.5 单片机长短按键的应用17.2 A/D(模数转换)的主要指标5.1 逻辑电路与逻辑运算11. UART 串口通信17.3 PCF8591 硬件接口5.2 定时器介绍11.1 单片机串行通信介绍17.4 PCF8591 应用程序5.3 定时器的寄存器11.2 RS232 通信接口17.5 A/D 差分输入信号5.4 定时器的应用11.3 USB 转串口通信17.6 D/A 输出5.5 LED 数码管的介绍11.4 IO 口模拟 UART 串口通信17.7 单片机信号发生器程序5.6 数码管的真值表11.5 UART 串口通信的基本应用18. RS485 通信与 Modbus 协议5.7 数码管的静态显示11.6 通信实例与 ASCII 码18.1 RS485 通信6. 中断与数码管动态显示12. 1602 液晶介绍18.2 Modbus 通信协议介绍6.1 C 语言数组12.1 C 语言变量的地址18.3 Modbus 多机通信程序6.2 C 语言 if 语句12.2 C 语言指针变量的声明6.3 C 语言 switch 语句12.3 C 语言指针的简单示例6.4 数码管的动态显示12.4 C 语言指向数组元素的指针6.5 单片机数码管显示消隐12.5 ​C 语言字符数组和字符指针6.6 单片机中断系统12.6 1602 液晶介绍6.7 单片机中断的优先级12.7 1602 液晶的读写时序介绍12.8 1602 液晶指令介绍12.9 1602 液晶简单显示程序

9.9 单片机蜂鸣器控制程序和驱动电路


蜂鸣器从结构区分分为压电式蜂鸣器和电磁式蜂鸣器。压电式为压电陶瓷片发音,电流比较小一些,电磁式蜂鸣器为线圈通电震动发音,体积比较小。

按照驱动方式分为有源蜂鸣器和无源蜂鸣器。这里的有源和无源不是指电源,而是振荡源。有源蜂鸣器内部带了振荡源,如图9-8所示中,给了 BUZZ 引脚一个低电平,蜂鸣器就会直接响。而无源蜂鸣器内部是不带振荡源的,要让他响必须给 500 Hz~4.5 KHz 之间的脉冲频率信号来驱动它才会响。有源蜂鸣器往往比无源蜂鸣器贵一些,因为里边多了振荡电路,驱动发音也简单,靠电平就可以驱动,而无源蜂鸣器价格比较便宜,此外无源蜂鸣器声音频率可以控制,而音阶与频率又有确定的对应关系,因此就可以做出来“do re mi fa sol la si”的效果,可以用它制作出简单的音乐曲目,比如生日歌、两只老虎等等。

图 9-8 蜂鸣器电路原理图

我们来看一下图9-8的电路,蜂鸣器电流依然相对较大,因此需要用三极管驱动,并且加了一个100欧的电阻作为限流电阻。此外还加了一个 D4 二极管,这个二极管叫做续流二极管。我们的蜂鸣器是感性器件,当三极管导通给蜂鸣器供电时,就会有导通电流流过蜂鸣器。而我们知道,电感的一个特点就是电流不能突变,导通时电流是逐渐加大的,这点没有问题,但当关断时,经“电源-三极管-蜂鸣器-地”这条回路就截断了,过不了任何电流了,那么储存的电流往哪儿去呢,就是经过这个 D4 和蜂鸣器自身的环路来消耗掉了,从而就避免了关断时由于电感电流造成的反向冲击。接续关断时的电流,这就是续流二极管名称的由来。

蜂鸣器经常用于电脑、打印机、万用表这些设备上做提示音,提示音一般也很简单,就是简单发出个声音就行,我们用程序简单做了个 4 KHZ 频率下的发声和 1 KHZ 频率下的发声程序,同学们可以自己研究下程序,比较下实际效果。

#include <reg52.h>
sbit BUZZ = P1^6; //蜂鸣器控制引脚
unsigned char T0RH = 0; //T0 重载值的高字节
unsigned char T0RL = 0; //T0 重载值的低字节
void OpenBuzz(unsigned int frequ);
void StopBuzz();

void main(){
    unsigned int i;
    TMOD = 0x01; //配置 T0 工作在模式1,但先不启动
    EA = 1;
    while (1){ //使能全局中断
        OpenBuzz(4000); //以 4 KHz 的频率启动蜂鸣器
        for (i=0; i<40000; i++);
        StopBuzz(); //停止蜂鸣器
        for (i=0; i<40000; i++);
        OpenBuzz(1000); //以 1 KHz 的频率启动蜂鸣器
        for (i=0; i<40000; i++);
        StopBuzz(); //停止蜂鸣器
        for (i=0; i<40000; i++);
    }
}
/* 蜂鸣器启动函数,frequ-工作频率 */
void OpenBuzz(unsigned int frequ){
    unsigned int reload;//计算所需的定时器重载值
    reload = 65536 - (11059200/12)/(frequ*2); //由给定频率计算定时器重载值
    T0RH = (unsigned char)(reload >> 8); //16 位重载值分解为高低两个字节
    T0RL = (unsigned char)reload;
    TH0 = 0xFF; //设定一个接近溢出的初值,以使定时器马上投入工作
    TL0 = 0xFE;
    ET0 = 1; //使能 T0 中断
    TR0 = 1; //启动 T0
}
/* 蜂鸣器停止函数 */
void StopBuzz(){
    ET0 = 0; //禁用 T0 中断
    TR0 = 0; //停止 T0
}
/* T0 中断服务函数,用于控制蜂鸣器发声 */
void InterruptTimer0() interrupt 1{
    TH0 = T0RH; //重新加载重载值
    TL0 = T0RL;
    BUZZ = ~BUZZ; //反转蜂鸣器控制电平
}

另外用蜂鸣器来输出音乐,仅仅是好玩而已,应用很少,里边包含了音阶、乐谱的相关内容,程序也有一点复杂,所以就不详细给大家去讲解了。仅提供一个可以播放《两只老虎》的程序,大家可以下载到板子上玩玩,满足一下好奇心。

#include <reg52.h>
sbit BUZZ = P1^6; //蜂鸣器控制引脚
unsigned int code NoteFrequ[] = { //中音1-7 和高音1-7 对应频率列表
    523, 587, 659, 698, 784, 880, 988, //中音1-7
    1047, 1175, 1319, 1397, 1568, 1760, 1976 //高音1-7
};
unsigned int code NoteReload[] = { //中音1-7 和高音1-7 对应的定时器重载值
    65536 - (11059200/12) / (523*2), //中音1
    65536 - (11059200/12) / (587*2), //2
    65536 - (11059200/12) / (659*2), //3
    65536 - (11059200/12) / (698*2), //4
    65536 - (11059200/12) / (784*2), //5
    65536 - (11059200/12) / (880*2), //6
    65536 - (11059200/12) / (988*2), //7
    65536 - (11059200/12) / (1047*2), //高音1
    65536 - (11059200/12) / (1175*2), //2
    65536 - (11059200/12) / (1319*2), //3
    65536 - (11059200/12) / (1397*2), //4
    65536 - (11059200/12) / (1568*2), //5
    65536 - (11059200/12) / (1760*2), //6
    65536 - (11059200/12) / (1976*2), //7
};
bit enable = 1; //蜂鸣器发声使能标志
bit tmrflag = 0; //定时器中断完成标志
unsigned char T0RH = 0xFF; //T0 重载值的高字节
unsigned char T0RL = 0x00; //T0 重载值的低字节
void PlayTwoTiger();

void main(){
    unsigned int i;
    EA = 1; //使能全局中断
    TMOD = 0x01; //配置 T0 工作在模式1
    TH0 = T0RH;
    TL0 = T0RL;
    ET0 = 1; //使能 T0 中断
    TR0 = 1; //启动 T0

    while (1){
        PlayTwoTiger(); //播放乐曲--两支老虎
        for (i=0; i<40000; i++); //停止一段时间
    }
}
/* 两支老虎乐曲播放函数 */
void PlayTwoTiger(){
    unsigned char beat; //当前节拍索引
    unsigned char note; //当前节拍对应的音符
    unsigned int time = 0; //当前节拍计时
    unsigned int beatTime = 0; //当前节拍总时间
    unsigned int soundTime = 0; //当前节拍需发声时间
    //两只老虎音符表
    unsigned char code TwoTigerNote[] = {
    1,   2,   3, 1,    1,   2,   3, 1,     3, 4, 5,   3, 4, 5,
    5,6, 5,4, 3, 1,    5,6, 5,4, 3, 1,     1, 5, 1,   1, 5, 1,

    };
    //两只老虎节拍表,4 表示一拍,1 就是 1/4 拍,8 就是 2 拍
    unsigned char code TwoTigerBeat[] = {
    4,   4,   4, 4,   4,   4,   4, 4,    4, 4, 8,   4, 4, 8,
    3,1, 3,1, 4, 4,   3,1, 3,1, 4, 4,    4, 4, 8,   4, 4, 8,
    };

    //用节拍索引作为循环变量
    for (beat=0; beat<sizeof(TwoTigerNote); ){
        while (!tmrflag); //每次定时器中断完成后,检测并处理节拍
        tmrflag = 0;
        if (time == 0){ //当前节拍播完则启动一个新节拍
            note = TwoTigerNote[beat] - 1;
            T0RH = NoteReload[note] >> 8;
            T0RL = NoteReload[note];
            //计算节拍总时间,右移2位相当于除4,移位代替除法可以加快执行速度
            beatTime = (TwoTigerBeat[beat] * NoteFrequ[note]) >> 2;
            //计算发声时间,为总时间的 0.75,移位原理同上
            soundTime = beatTime - (beatTime >> 2);
            enable = 1; //指示蜂鸣器开始发声
            time++;
        }else{ //当前节拍未播完则处理当前节拍
            //当前持续时间到达节拍总时间时归零,
            //并递增节拍索引,以准备启动新节拍
            if (time >= beatTime){
                time = 0;
                beat++;
            }else{ //当前持续时间未达到总时间时,
                time++; //累加时间计数
                //到达发声时间后,指示关闭蜂鸣器,
                //插入 0.25*总时间的静音间隔,
                if (time == soundTime){
                    enable = 0; //用以区分连续的两个节拍
                }
            }
        }
    }
}
/* T0 中断服务函数,用于控制蜂鸣器发声 */
void InterruptTimer0() interrupt 1{
    TH0 = T0RH; //重新加载重载值
    TL0 = T0RL;
    tmrflag = 1;
    if (enable){ //使能时反转蜂鸣器控制电平
        BUZZ = ~BUZZ;
    }else{ //未使能时关闭蜂鸣器
        BUZZ = 1;
    }
}

分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)