51单片机学习笔记5 流水灯实现及蜂鸣器控制
开发板的LED灯连接到GPIO的P2口的P20~P27:LED采用共阳极接法。这种接法的好处是点亮LED不需要I/O口输出很大功率电流;GPIO在输出低电平时LED亮。这里简单给P2口赋值0或1实现GPIO口开关,实际只操作P20端口。由于输出低点平点亮,所以给0x01取反,除了最低位其它位都会变成高电平,效果就是最低位LED亮。(2) 使用算术左移实现流水灯让0x01里的1使用先左移到合适位置,
51单片机学习笔记5 流水灯实现及蜂鸣器控制
一、流水灯
本章节要实现的功能是开发板的LED灯轮流点亮。
1. 硬件电路
开发板的LED灯连接到GPIO的P2口的P20~P27:
LED采用共阳极接法。这种接法的好处是点亮LED不需要I/O口输出很大功率电流;GPIO在输出低电平时LED亮。
2. 代码实现
(1)types.h
为方便后面操作,定义一个types.h用来定义变量类型,位置放在 includes/ 目录下:
#ifndef __TYPES_H__
#define __TYPES_H__
// 定义无符号8位整型数据类型
typedef unsigned char u8;
// 定义无符号16位整型数据类型
typedef unsigned int u16;
#endif
设置引用路径:
(2) 点亮一个LED的基本操作
这里简单给P2口赋值0或1实现GPIO口开关,实际只操作P20端口。由于输出低点平点亮,所以给0x01取反,除了最低位其它位都会变成高电平,效果就是最低位LED亮。
#include "reg52.h"
#include "types.h"
#define LED_PORT P2
void delay_10us(u16 ten_us){
while(ten_us--);
}
void main(){
while(1){
LED_PORT=~0x00;
delay_10us(50000);
LED_PORT=~0x01;
delay_10us(50000);
}
}
(3) 使用算术左移实现流水灯
下面代码控制移位关键是 ~(0x01<<i)
操作。
-
0x01 << i
:这是一个位运算操作,表示将十六进制数0x01
(二进制为00000001
)左移i
位。左移操作将在二进制数的右端补零。因此,0x01 << i
的结果是在二进制数00000001
的基础上向左移动i
位,即将1
逐位左移i
位。 -
~(0x01 << i)
:这是一个按位取反的操作,用于翻转0x01 << i
的每一位,即将0x01 << i
中的每一位0
变为1
,每一位1
变为0
。 -
LED_PORT = ~(0x01 << i);
:这是将翻转后的结果赋值给LED_PORT
变量。- 例如,如果
i=0
,则0x01 << 0
等于00000001
,经过按位取反操作后,得到11111110
,即只有最右侧的LED亮起。 - 如果
i=1
,则0x01 << 1
等于00000010
,经过按位取反操作后,得到11111101
,即第二个LED亮起。 - 以此类推,不断地改变
i
的值,可以控制不同LED的亮灭,从而实现LED的流水灯效果。
- 例如,如果
#include "reg52.h"
#include "types.h"
// 定义LED的端口为P2
#define LED_PORT P2
// 延时函数,延时一段时间
void delay_10us(u16 ten_us){
while(ten_us--);
}
void main(){
int i=0;
while(1){
// 控制LED的亮灭, ~(0x01<<i) 为按位取反的操作,实现LED流水灯的效果
LED_PORT = ~(0x01<<i);
i++;
if(i>7) i=0;
// 延时一段时间,控制LED的流动速度
delay_10us(50000);
}
}
(4) 使用库文件左移函数
这里要使用系统intrins.h库。下面的循环流水灯使用变量 direction 来表示方法,只占用一个bit即可。
crol 与 <<
最大区别是,左移后溢出部分自动补到最右侧,其函数定义为:
unsigned char _crol_(unsigned char value, unsigned char count);
参数说明:
- value:待左移的字节。
- count:左移的位数。
例如,如果 value 的二进制表示为 11001010,count 为 3,则经过 crol 函数处理后,结果为 01010110。左移 3 位后,最高位的 1 移出,而原来的最低位 1 移到了最高位,其余位依次向左移动。
main程序内容:
#include "reg52.h"
#include "types.h"
#include "intrins.h"
// 定义LED的端口为P2
#define LED_PORT P2
// 延时函数,延时一段时间
void delay_10us(u16 ten_us){
while(ten_us--);
}
void main(){
int i=0;
bit direction=0;
while(1){
//
LED_PORT = _crol_(0xFE, i);
if(direction==0){
i++;
if(i>=7){
direction=1;
i=7;
}
}else{
i--;
if(i<0){
i=1;
direction=0;
}
}
delay_10us(50000*(i+1));
}
}
这里延时计算把i值也带进去了,会产生类似跳跃的效果。
二、蜂鸣器
1. 蜂鸣器介绍
蜂鸣器是一种常见的声音发生器,它通过振动产生声音。通常情况下,蜂鸣器被设计成小型的电子器件,可广泛应用于各种电子设备中。
主要分类:
- 压电蜂鸣器:通过施加电压使压电晶体振动来产生声音。它们通常具有较高的效率和较低的功耗。
- 磁性蜂鸣器:通过电流在电磁铁上产生磁场,从而使得磁性振膜振动,产生声音。这种类型的蜂鸣器通常功耗较大,但可以产生较大的声音。
- 共振蜂鸣器:利用共振腔体和振膜的共振效应产生声音。这种蜂鸣器体积较小,功耗较低,但声音相对较小。
2. 硬件电路
(1)原理图
蜂鸣器需要30mA左右电流进行驱动,51的I/O口驱动能力比较弱,一般不会直接使用I/O口来驱动蜂鸣器,需要使用放大电路。
开发板使用了ULN2003D来驱动蜂鸣器,原理图如下:
蜂鸣器接在ULN2003D的12脚,通过单片机的P25来进行控制。
需要注意的是,beep 连的引脚,同时也是LED6的引脚。
(2)ULN2003介绍
-
ULN2003是高耐压、大电流复合晶体管阵列,由七个硅NPN 复合晶体管组成。一般采用DIP—16 或SOP—16 塑料封装。
-
ULN2003灌电流可达500mA,并且能够在关态时承受50V 的电压,输出还可以在高负载电流并行运行。它可以直接驱动继电器等负载;输入5VTTL电平,输出可达500mA/50V。
-
ULN2003D 常用于驱动大功率负载,如步进电机、继电器、蜂鸣器等。
注意3.3V的高电平也可以直接驱动输入端I/O口。
内部结构图:
引脚接线图
3. 代码实现
beep_utils.h
#ifndef __BEEP_UTILS_H__
#define __BEEP_UTILS_H__
#include <reg52.h>
#include "types.h"
/**
* 蜂鸣器端口
*/
sbit BEEP_PORT = P2^5;
/**
* 蜂鸣器发声一段时间
*/
void beep(u16 high, u16 low, u16 times);
#endif
beep_utils.c
#include "beep_utils.h"
#include "common_utils.h"
#include "types.h"
/**
* @brief 打开蜂鸣器
*/
void beep_on(){
BEEP_PORT = 1;
}
/**
* @brief 关闭蜂鸣器
*/
void beep_off(){
BEEP_PORT = 0;
}
/**
* @brief 蜂鸣器发声
*/
void beep_once(u16 high, u16 low){
beep_on();
delay(high);
beep_off();
delay(low);
}
/**
* @brief 蜂鸣器发声一段时间
*/
void beep(u16 high, u16 low, u16 times){
u16 i;
for(i = 0; i < times; i++){
beep_once(high, low);
}
}
main
#include <reg52.h>
#include "beep_utils.h"
#include "led_utils.h"
#include "common_utils.h"
/**
* @brief 主函数
*/
main()
{
// 关闭所有led
led_all_off();
// 打开第1个led
led_on(0);
led_on(7);
beep(10, 10, 100);
while(1)
{
delay(10000);
}
}
本文代码开源地址:
https://gitee.com/xundh/learn51
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)