文章目录
- 1.认识蜂鸣器
- 2.控制原理
- 3.蜂鸣器实战应用
-
- 需求分析
- 代码编写
-
- 步骤一代码编写及分析
- test.h的固定模板
- [Tips:提示:"test\test.c(14): error C16: unprintable character 0xA3 skipped](#Tips:提示:“test\test.c(14): error C16: unprintable character 0xA3 skipped)
- [Tips:"test\test.c(14): warning C137: constant in condition expression"](#Tips:“test\test.c(14): warning C137: constant in condition expression”)
- 实现主要代码
- 实现完整功能的test.c代码
- Tips:C语言的逻辑运算符
- 总结
- 课后练习
1.认识蜂鸣器
反面包上黑胶的是有源蜂鸣器。
在背面裸露的一块线路板的是无源蜂鸣器。
YX55675-无源蜂鸣器模块的资料
提取码:nl73
区别
1、有源蜂鸣器内部带震荡源,所以只要一通电就会叫(一边高电平,一边低电平),而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫(必须不断给高低电平)。
2、价格不同,有源蜂鸣器要比无源蜂鸣器贵,贵在里面多了震荡源。有源容易控制。播放音乐无源的更好。
围绕这个有源蜂鸣器展开我们的实验。
2.控制原理
原理图:
三极管基极如果是低电平,则SS8550发射至集电极导通,接BEEP1正极,BEEP1负极接地。
C35电容起到简单滤波作用。
P54引脚给高电平关闭
P54引脚给低电平打开
这里我们尝试自己动手写一段,结合上一节课的按钮点灯,这里要实现:按钮按一下打开蜂鸣器,按钮按一下关闭蜂鸣器的程序!(先自己尝试一下,再来看看我写的!)
实现蜂鸣器控制原理
需要背诵的按键单触发代码:
C
if (KEY1 == 0)
{
delay_ms(10);
if (KEY1 == 0)
{
while(KEY1 == 0);
BEEP = !BEEP;
}
}
3.蜂鸣器实战应用
实物图:
需求分析
本节选择控制8个LED(LED1~LED8)和KEY1(开关),KEY2按键(功能选择)。
按键2,LED 8,蜂鸣器*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的固定模板
C
#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函数:
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总电源
P6 = 0X00; //全部点亮
delay_ms(200); //延迟200ms
P6 = 0XFF; //全部关闭
}
}
}
}
头文件中需要包含函数的声明,如:
C
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函数:
C
while(1) //死循环
{
if( DeviceState != DEVSTATE_CONFIGURED ) //判断USB是否连接成功,最新版usb.h中该有定义
continue;
if( bUsbOutReady ) //判断有没有接收到数据
{
usb_OUT_done(); //接收应答(固定格式)
}
Test();
}
test.h中定义:
C
#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中实现第一步功能中自定义变量及函数的代码:
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按下,根据开机变量的不同,选择不同的执行代码。
C
else
{
Run_Flag = 0; //已关机
BEEP = 0; //打开蜂鸣(提醒)
delay_ms(10); //延迟10ms
BEEP = 1; //关闭蜂鸣
P2 = 0XFF; //状态指示全部关闭
P40 = 1; //关闭总电源LED
}
步骤三:状态选择按键代码编写及分析
开机后,按键2按下,蜂鸣10ms,LED1-8轮流点亮,表示切换煲汤、烧水等功能。
实现代码:
C
/*=======================按下按键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代码如下:
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持续闪烁,表示正在工作,且在工作的时候无法切换功能。