找回密码
 立即注册
查看: 551|回复: 0

学习笔记|STC32G单片机视频开发教程(冲哥)|第八集(上):蜂鸣器应用

[复制链接]

12

主题

7

回帖

84

积分

注册会员

积分
84
发表于 2023-8-22 11:06:35 | 显示全部楼层 |阅读模式
本帖最后由 打酱油的工程师 于 2023-8-22 11:15 编辑

1.认识蜂鸣器
反面包上黑胶的是有源蜂鸣器。





在背面裸露的一块线路板的是无源蜂鸣器。





http://pan.baidu.com/s/1ZwB27T9UAEHtQFtLspOMKA 提取码:nl73

区别
1、有源蜂鸣器内部带震荡源,所以只要一通电就会叫(一边高电平,一边低电平),而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫(必须不断给高低电平)。 2、价格不同,有源蜂鸣器要比无源蜂鸣器贵,贵在里面多了震荡源。有源容易控制。播放音乐无源的更好。 围绕这个有源蜂鸣器展开我们的实验。

2.控制原理
原理图:




三极管基极如果是低电平,则SS8550发射至集电极导通,接BEEP1正极,BEEP1负极接地。 C35电容起到简单滤波作用。 P54引脚给高电平关闭 P54引脚给低电平打开 这里我们尝试自己动手写一段,结合上一节课的按钮点灯,这里要实现:按钮按一下打开蜂鸣器,按钮按一下关闭蜂鸣器的程序!(先自己尝试一下,再来看看我写的!)

实现蜂鸣器控制原理
需要背诵的按键单触发代码:

                if (KEY1 == 0)
                {
                        delay_ms(10);
                        if (KEY1 == 0)
                        {
                                while(KEY1 == 0);
                                BEEP = !BEEP;
                        }

                }
3.蜂鸣器实战应用
实物图:




需求分析
本节选择控制8个LED(LED1~LED8)和KEY1(开关),KEY2按键(功能选择)。 按键2,LED8,蜂鸣器*1 1、按键1按下,蜂鸣10ms,开始自检, LED1-8全部点亮200ms在熄灭,表示开机。 2.开机后,按键2按下,蜂鸣10ms,LED1-8轮流点亮,表示切换煲汤、烧水等功能。 3.开机后按键1再次按下,蜂鸣10ms,LED全部熄灭,表示关机。

代码编写
步骤一代码编写及分析
先在项目文件夹下新建test子目录,在目录中新建test.c和test.h。 将test.c加入工程:






test.h的固定模板

#ifndef        __TEST_H   //判断是否有test.h
#define __TEST_H


#include "COMM/stc.h"  //调用头文件
#include "COMM/usb.h"




#endif
test.c加入test.h的引用,test.c文件添加进入工程,添加include文件引用路径:

将define文件移至test.h,通过之前添加的include,其他文件都可以访问到该预定义。

之后写需求功能。 第一步,编写状态变量及test函数:


#include "test.h"


bit  Run_Flag = 0; //0-1开关机变量
u8   Run_Mode = 0; //0-8 模式几 0:没有模式


void Test(void)   //电磁炉的功能
{
        if (KEY1 == 0)   //开关机键
        {
            delay_ms(10);
            if (KEY1 == 0)
            {
                while(KEY1 == 0);   //按钮按下,并等待按钮松开
                if (Run_Flag = 0)  //表示还没有开机
                {
                    Run_Flag = 1;   //开机变量改为1,表示已经开机
                    BEEP = 0;       //打开蜂鸣
                    delay_ms(10);   //延迟10ms
                    BEEP = 1;       //关闭蜂鸣
                    P40 = 0;        //打开了LED总电源
                    P6 = 0X00;      //全部点亮
                    delay_ms(200);   //延迟200ms
                    P6 = 0XFF;      //全部关闭
                }
            }


        }
}


头文件中需要包含函数的声明,如:

void delay_ms(u16 ms);
void Test(void);
开始编译,提示“test\test.c(10): warning C140: 'delay_ms' undefined; assuming 'extern int delay_ms()'”: 原因是delay_ms未在test.h中定义,需要先移动过来,如果仅复制,则会提示以下错误:




Tips:提示:“test\test.c(14): error C16: unprintable character 0xA3 skipped
test\test.c(14): error C16: unprintable character 0xA9 skipped” 这是因为:keil里面出现了中文输入法时写的标点,例如: //lcm_w_word("abc您好");  不能出现全角的任何字符,包括空格在内任何标点符号和空格都只能在英文的状态下输入,提示这个错误的话 把全角的字符或者标点替换一下即可,但是正常情况是看不到的,你只有加入了//才能发现的

Tips:“test\test.c(14): warning C137: constant in condition expression”
在if()里面不应该使用=,而应该使用==,使用=就相当于变量赋值一个常量了,所以编译器提示告警。接下来如果有else if,会接着提示:“warning C294: unreachable code”(本例无else if,故未出现。)

实现主要代码
main.c中增加Test函数:

while(1) //死循环
    {
                if( DeviceState != DEVSTATE_CONFIGURED )         //判断USB是否连接成功,最新版usb.h中该有定义
                        continue;
                if( bUsbOutReady )    //判断有没有接收到数据
                {
                        usb_OUT_done(); //接收应答(固定格式)
                }
                Test();
        }
test.h中定义常量及函数:

#ifndef        __TEST_H   //判断是否有test.h
#define __TEST_H


#include "COMM/stc.h"  //调用头文件
#include "COMM/usb.h"

#define MAIN_Fosc 24000000UL

#define KEY1 P32
#define KEY2 P33

#define BEEP P54  //定义一个BEEP控制引脚

void delay_ms(u16 ms);
void Test(void);


#endif
test.c中实现第一步功能中自定义变量及函数的代码:

#include "test.h"

bit  Run_Flag = 0; //0-1开关机变量
u8   Run_Mode = 0; //0-8 模式几 0:没有模式

void Test(void)   //电磁炉的功能
{
                if (KEY1 == 0)   //开关机键,第一步骤代码段
                {
                        delay_ms(10);
                        if (KEY1 == 0)
                        {
                                //while(KEY1 == 0);        //按钮按下,并等待按钮松开
                                if (Run_Flag == 0)  //表示还没有开机
                                {
                                        Run_Flag = 1;   //开机变量改为1,表示已经开机
                                        BEEP = 0;                //打开蜂鸣
                                        delay_ms(10);   //延迟10ms
                                        BEEP = 1;                //关闭蜂鸣
                                        P40 = 0;                //打开了LED总电源
                                        P2 = 0X00;                //全部点亮
                                        delay_ms(300);   //延迟200ms
                                        P2 = 0XFF;                 //全部关闭
                                }
                        }

                }
}

void delay_ms(u16 ms)        //unsigned int
{
        u16 i;
        do
        {
                i = MAIN_Fosc/6000;
                while(--i);
        }while(--ms);
}
执行完代码后,蜂鸣响1声,8个状态等全亮后关闭,之后再按其他按键无响应,待补充后续功能代码。

步骤二:关机代码编写及分析
开机后按键1再次按下,蜂鸣10ms,LED全部熄灭,P40总电源指示灯熄灭,表示关机。 基础的功能状态都是key1按下,根据开机变量的不同,选择不同的执行代码。

                                else
                                {
                                        Run_Flag = 0;   //已关机
                                        BEEP = 0;                //打开蜂鸣(提醒)
                                        delay_ms(10);   //延迟10ms
                                        BEEP = 1;                //关闭蜂鸣
                                        P2 = 0XFF;                //状态指示全部关闭
                                        P40 = 1;                //关闭总电源LED
                                }
步骤三:状态选择按键代码编写及分析
开机后,按键2按下,蜂鸣10ms,LED1-8轮流点亮,表示切换煲汤、烧水等功能。 实现代码:


/*=======================按下按键2,执行本段代码=====================*/
                if (KEY2 == 0)   //开关机键
                {
                        delay_ms(10);  //防抖
                        if (KEY2 == 0)
                        {
                                while(KEY2 == 0);        //等待按键松开,将要执行
/*=======================还没有开机的情况下,执行本段代码=====================*/
                                if (Run_Flag == 0)  //表示还没有开机
                                {
                                        BEEP = 0;                //打开蜂鸣
                                        delay_ms(10);   //延迟10ms
                                        BEEP = 1;                //关闭蜂鸣
                                        Run_Mode++;                //每次按下,模式+1(移至下一个led)
                                        if (Run_Mode > 8)  //如果模式大于8,回到模式1
                                                Run_Mode = 1;  //Run_Mode超过8后清零,回到第一个灯


                                        P2 = ~(1<< (Run_Mode - 1));        //最先想到的“1<< Run_Mode”是错误写法,执行结果是8个灯中每次移动仅1个不亮。
                                                                                                //灯是低电平点亮,1<< Run_Mode,即1<<1,左移以后为0000 0010,仅1个LED灭,继续左移,尾部补0,还是只有1个LED灭
                                                                                                //解决方法:RunMode先减1,再左移,最后全部取反。这里用~为全取反。而!是位取反。
                                                                                                //P2 = 0XFX;  P6<< 1 + 1;  也可以实现
                                }
实现完整功能的test.c代码
执行时发现第一次按键时,如果是开机状态,0位灯不亮,则需要在关机代码中加入Run_Mode = 0;   //模式清零。 实现完整功能的test.c代码如下:

#include "test.h"

bit  Run_Flag = 0; //0-1开关机变量
u8   Run_Mode = 0; //0-8 模式几 0:没有模式

void Test(void)   //电磁炉的功能
{
                if (KEY1 == 0)   //开关机键
                {
                        delay_ms(1000);  //长按1s开机
                        if (KEY1 == 0)
                        {
                                //while(KEY1 == 0);        //按钮按下,并等待按钮松开
/*=======================还没有开机的情况下,执行本段代码=====================*/
                                if (Run_Flag == 0)  //表示还没有开机
                                {
                                        Run_Flag = 1;   //开机变量改为1,表示已经开机
                                        BEEP = 0;                //打开蜂鸣
                                        delay_ms(10);   //延迟10ms
                                        BEEP = 1;                //关闭蜂鸣
                                        P40 = 0;                //打开了LED总电源
                                        P2 = 0X00;                //全部点亮
                                        delay_ms(300);   //延迟200ms
                                        P2 = 0XFF;                 //全部关闭
                                }
/*=======================已经开机的状态下,执行关机操作=====================*/
                                else
                                {
                                        Run_Flag = 0;   //标记已关机
                                        BEEP = 0;                //打开蜂鸣(提醒)
                                        delay_ms(10);   //延迟10ms
                                        BEEP = 1;                //关闭蜂鸣
                                        P2 = 0XFF;                //状态指示全部关闭
                                        P40 = 1;                //关闭总电源LED
                                        Run_Mode = 0;   //模式清零
                                }
                        }

                }
/*=======================按下按键2,执行本段代码=====================*/
                if (KEY2 == 0)   //状态选择键被按下
                {
                        delay_ms(10);  //防抖
                        if (KEY2 == 0)
                        {
                                while(KEY2 == 0);        //等待按键松开,将要执行
                                {
                                        BEEP = 0;                //打开蜂鸣
                                        delay_ms(10);   //延迟10ms
                                        BEEP = 1;                //关闭蜂鸣
                                        Run_Mode++;                //每次按下,模式+1(移至下一个led)
                                        if (Run_Mode > 8)  //如果模式大于8,回到模式1
                                                Run_Mode = 1;  //Run_Mode超过8后清零,回到第一个灯
                                        P2 = ~(1<< (Run_Mode - 1));        //错误写法,执行结果是8个灯中仅1个不亮
                                                                                                //灯是低电平点亮,1<< Run_Mode,即1<<1,左移以后为0000 0010,仅1个LED灭,继续左移,尾部补0,还是只有1个LED灭
                                                                                                //解决方法:RunMode先减1,再左移,最后全部取反。这里用~为全取反。而!是位取反。
                                                                                                //P2 = 0XFX;  P6<< 1 + 1;  也可以实现
                                }

                        }

                }
}

void delay_ms(u16 ms)        //unsigned int
{
        u16 i;
        do
        {
                i = MAIN_Fosc/6000;
                while(--i);
        }while(--ms);
}
Tips:C语言的逻辑运算符
一、与运算 && 与运算需要使用关键字符&&,表示将两个或者多个表达式连接成一个,所有表达式必须都为TRUE,整个表达式才为TRUE,否则为false。 二、或运算 || 或运算需要使用关键字符||,表示将两个或者多个表达式连接成一个,任意一个表达式为TRUE,整个表达式就为TRUE;只有当所有表达为false的时候,整个表达式才为false。 三、非运算 ! 非运算需要使用关键字符!,用于将单个表达式结果取反。 如果原表达式的结果为false,在表达式前面加上运算符!结果取反之后就是TRUE;如果原计算结果是TRUE,在表达式前面加上运算符!结果取反之后就是false。

总结
1.了解蜂鸣器怎么使用
2.尝试去使用蜂鸣器

课后练习
增加按键3,按下后表示启动,选择的对应的功能的LED持续闪烁,表示正在工作,且在工作的时候无法切换功能。




欢迎大家访问我的CSDN:打酱油的工程师
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:22 , Processed in 0.111435 second(s), 45 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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