AT24C02密码锁,LCD1602显示,51单片机。

#include <REGX52.H>
#include <Buttons.h>
#include <AT24C02.h>
#include <LCD1602.h>
#include <Delay.h>
#include <security.h>
#include <Buzzer.h>

unsigned char Original_Password[6] = {0};  // 原始密码数组
unsigned char Now_Password[6] = {0};      // 当前输入的密码数组

/**
 * @brief 开门操作函数
 */
void Open_Door()
{
    LCD_ShowString(1,1 ,"door is open   ");  // 在第一行显示门已开
}

/**
 * @brief 关门操作函数
 */
void Off_Door()
{
    LCD_ShowString(1,1 ,"door is Off    ");  // 在第一行显示门已关
}

/**
 * @brief 主函数
 */
void main()
{
    char Door_status_flag = 0;  // 门的状态标志,0 表示关,1 表示开

    LCD_Init();  // 初始化 LCD
    Buzzer_Init();  // 初始化蜂鸣器
    Boorbell_Init();  // 初始化门铃
    Password_Init(Original_Password);  // 初始化密码

    while (1)
    {
        switch (Read_JZ_Buttons())  // 根据读取的按键值进行处理
        {
        case key_up:  // 向上按键
            if(Password_Input(Now_Password)){  // 输入密码
                if(Password_Proofread(Original_Password, Now_Password)){  // 验证密码
                    Door_status_flag = 1;  // 密码正确,门状态设为开
                   doorbell_Start();
                }
            }
            break;
        case key_down:  // 向下按键
            Door_status_flag = 0;  // 门状态设为关
            break;
        case key_mode:  // 模式按键
            if(Password_Change(Original_Password)){  // 修改密码
                Buzzer_On();  // 蜂鸣器响
                Delay_ms(50);  // 延时
                Buzzer_Off();  // 蜂鸣器停
            }
            break;
        case key_OK:  // 确定按键
            doorbell_Start();  // 启动门铃
            break;
        default:
            break;
        }
        if (Door_status_flag )  // 根据门的状态显示相应信息
        {
            Open_Door();
        } else {
            Off_Door();
        }
    }
}
#include <Delay.h>

/**
 * @brief 实现毫秒级延时的函数
 * @param ms 要延时的毫秒数
 */
void Delay_ms(unsigned int ms)
{
    int i,j;
    // 通过双重循环实现延时
    for(i=ms;i>0;i--) 
        for(j=114;j>0;j--); 
}
#ifndef __DELAY_H
#define __DELAY_H

/**
 * @brief 声明一个毫秒级延时函数
 * @param ms 要延时的毫秒数
 */
void Delay_ms(unsigned int ms);

#endif
#include <Buttons.h>
#include <REGX52.H>
#include <Delay.h>

// 读取普通按钮状态的函数
unsigned char Read_Buttons(void)
{
    unsigned char Button = 0x00; // 初始化按钮状态变量为 0

    // 如果按钮状态不是全 1(即有按钮按下)
    if(SW!= 0xff) {
        Delay_ms(20); // 延时 20 毫秒消抖
    } else {
        return Button; // 如果没有按钮按下,直接返回初始状态 0
    }

    // 判断各个按钮是否按下,若按下则将对应位设为 1
    if(sw1 == 0) Button = Button | 0x01;
    if(sw2 == 0) Button = Button | 0x02;
    if(sw3 == 0) Button = Button | 0x04;
    if(sw4 == 0) Button = Button | 0x08;

    // 等待按钮释放
    while(SW!= 0xff);
    Delay_ms(20);
    return Button;
}

// 读取矩阵按钮状态的函数
unsigned char Read_JZ_Buttons(void)
{
    unsigned char Button = 0x00; // 初始化按钮状态变量为 0
    unsigned char Button_SMzb;
    unsigned char i = 4;

    SW = 0xff; // 设置某个端口为全 1
    sw_x1 = 0;
    sw_x2 = 0;
    sw_x3 = 0;
    sw_x4 = 0;

    // 如果按钮状态与预期一致
    if(SW!= SW_Cmp) {
        Delay_ms(20); // 延时 20 毫秒消抖
    } else {
        return Button; // 如果状态符合预期,直接返回初始状态 0
    }

    // 通过循环依次检查不同的按钮组合
    while (i--)
    {
        switch (i)
        {
            case 3:
                Button_SMzb = 0x10; // 设置一个中间变量的值
                SW = 0xff;
                sw_x1 = 0;
                break;
            case 2:
                Button_SMzb = 0x20;
                SW = 0xff;
                sw_x2 = 0;
                break;
            case 1:
                Button_SMzb = 0x40;
                SW = 0xff;
                sw_x3 = 0;
                break;
            case 0:
                Button_SMzb = 0x80;
                SW = 0xff;
                sw_x4 = 0;
                break;
            default:
                break;
        }

        // 判断各个按钮是否按下,若按下则将对应位设为 1,并与中间变量组合
        if(sw1 == 0)Button |= 0x01 | Button_SMzb;
        if(sw2 == 0)Button |= 0x02 | Button_SMzb;
        if(sw3 == 0)Button |= 0x04 | Button_SMzb;
        if(sw4 == 0)Button |= 0x08 | Button_SMzb;
    }

    SW = 0xff;
    sw_x1 = 0;
    sw_x2 = 0;
    sw_x3 = 0;
    sw_x4 = 0;
    while(SW!= SW_Cmp);
    Delay_ms(20);

    SW = 0xff;
    return Button;
}
#ifndef __BUTTONS_H
#define __BUTTONS_H

#include <REGX52.H>

//矩阵按键地址定义
#define key1 0x11
#define key2 0x12
#define key3 0x14
#define key4 0x18
#define key5 0x21
#define key6 0x22
#define key7 0x24
#define key8 0x28

#define key9 0x41
#define key10 0x42
#define key11 0x44
#define key12 0x48
#define key13 0x81
#define key14 0x82
#define key15 0x84
#define key16 0x88

#define key_empty 0x00

#define key_OK      key16
#define key_Cancel  key15
#define key_mode    key4
#define key_up      key8
#define key_down    key12

// 定义四个按钮对应的引脚
sbit sw1 = P3^0;
sbit sw2 = P3^1;
sbit sw3 = P3^2;
sbit sw4 = P3^3;

// 定义矩阵按键的四个按钮对应的引脚
sbit sw_x1 = P3^4;
sbit sw_x2 = P3^5;
sbit sw_x3 = P3^6;
sbit sw_x4 = P3^7;

// 定义宏,方便使用按钮名称
#define sw_y1 sw1
#define sw_y2 sw2
#define sw_y3 sw3
#define sw_y4 sw4

// 定义宏,表示连接按钮的端口
#define SW  P3

// 根据不同的扫描方式定义宏
#define SW_Cmp 0x0f //x 扫描
// #define SW_Cmp 0xf0 //y 扫描

// 声明三个函数
unsigned char Read_Buttons(void);
unsigned char Read_JZ_Buttons(void);

#endif
#include <REGX52.H>


#define AT24C02_ADDRESS		0xA0

sbit I2C_SCL=P1^6;
sbit I2C_SDA=P1^5;

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
}

/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}
#ifndef __AT24C02_H__
#define __AT24C02_H__

/**
 * @brief 向 AT24C02 芯片指定地址写入一个字节的数据
 * 
 * @param WordAddress 要写入数据的地址
 * @param Data 要写入的数据
 */
void AT24C02_WriteByte(unsigned char WordAddress,Data);

/**
 * @brief 从 AT24C02 芯片指定地址读取一个字节的数据
 * 
 * @param WordAddress 要读取数据的地址
 * @return unsigned char 读取到的数据
 */
unsigned char AT24C02_ReadByte(unsigned char WordAddress);

#endif
#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^7;
sbit LCD_RW=P2^6;
sbit LCD_EN=P2^5;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}
#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif
#include <security.h>
#include <AT24C02.h>
#include <Delay.h>
#include <REGX52.H>
#include <Buttons.h>
#include <LCD1602.h>
#include <Buzzer.h>
#include <string.h>

/**
 * @brief 将密码写入 AT24C02 存储
 * @param Password 指向密码的指针
 */
void Password_Write(unsigned char* Password)
{
    unsigned char i;
    for(i = 0 ; i < 6 ; i++)
    {
        AT24C02_WriteByte(i, Password[i]);
        Delay_ms(5);
    }
}

/**
 * @brief 从 AT24C02 读取密码
 * @param Password 用于存储读取到的密码的指针
 */
void Password_Read(unsigned char* Password)
{
    unsigned char i;
    for(i = 0 ; i < 6 ; i++)
    {
        Password[i] = AT24C02_ReadByte(i);
    }
}

/**
 * @brief 初始化密码相关操作
 * @param Password 指向密码的指针
 */
void Password_Init(unsigned char* Password)
{
    if (P3_0 == 0){  // 检查某个引脚状态
        AT24C02_WriteByte(6, 0);  // 写入特定地址
        while (P3_0 == 1);
        Buzzer_On();  // 打开蜂鸣器
        Delay_ms(1000);  // 延时 1000ms
        Buzzer_Off();  // 关闭蜂鸣器
    }

    if (AT24C02_ReadByte(6) == 1)  // 读取特定地址的值
    {
        Password_Read(Password);  // 读取密码
        return;
    } else {
        Password_Write(Initial_Password);  // 写入初始密码
        AT24C02_WriteByte(6, 1);  // 写入标志
    }
}

/**
 * @brief 解析按键值得到数字或符号
 * @return 解析后的结果
 */
unsigned char Key_Numbers_Parsing(void)
{
    unsigned char Result = Read_JZ_Buttons();
    switch (Result)
    {
    //7~9
    case key1:Result = '7';
        break;
    case key2:Result = '8';
        break;
    case key3:Result = '9';
        break;

    //4~6
    case key5:Result = '4';
        break;
    case key6:Result = '5';
        break;
    case key7:Result = '6';
        break;

    //1~3
    case key9:Result = '1';
        break;
    case key10:Result = '2';
        break;
    case key11:Result = '3';
        break;

    //0
    case key13:Result = '0';
        break;
    //'.'
    case key14:Result = '.';
        break;

    default:
        break;
    }
    return Result;
}

/**
 * @brief 处理密码输入过程
 * @param Input_Password 用于存储输入密码的指针
 * @return 输入是否完成的标志
 */
char Password_Input(unsigned char* Input_Password)
{
    unsigned char i = 6;
    unsigned char key;

    LCD_ShowString(1, 1, "Enter password:");
    LCD_ShowString(2, 1, "               ");

    while(i--)
    {
        while (1)
        {
            key = Key_Numbers_Parsing();
            if(key == key_mode){  // 模式键
                LCD_ShowString(2, 1, "               ");
                return 0;
            }
            if (key){  // 有有效按键
                break;
            }
        }
        
        switch (key)
        {
        case key_Cancel:i = 6;  // 取消键
            LCD_ShowString(2, 1, "               ");
            break;
        case key_mode:return 0;  // 模式键
            break;
        default:Input_Password[5-i] = key;  // 存储输入的字符
            LCD_ShowChar(2, 6-i, '*');  // 显示*
            Buzzer_On();  // 打开蜂鸣器
            Delay_ms(50);  // 延时 50ms
            Buzzer_Off();  // 关闭蜂鸣器
            break;
        }
    }
    LCD_ShowString(1, 1, "               ");
    LCD_ShowString(2, 1, "               ");
    return 1;
}

/**
 * @brief 比较原始密码和输入的当前密码是否一致
 * @param Original_password 原始密码
 * @param Now_Password 当前输入的密码
 * @return 密码是否一致的标志
 */
char Password_Proofread(unsigned char* Original_password, unsigned char* Now_Password)
{
    unsigned char i;

    for (i = 0; i < 6; i++)
    {
        if(Original_password[i]!= Now_Password[i]){  // 逐个字符比较
            return 0;
        }
    }
    return 1;
}

/**
 * @brief 处理密码修改操作
 * @param Password 指向密码的指针
 * @return 密码修改是否成功的标志
 */
char Password_Change( unsigned char* Password)
{
    unsigned char Input_password[6];
    unsigned char i;

    LCD_ShowString(1, 1, "Please enter   ");
    LCD_ShowString(2, 1, "old password   ");
    Delay_ms(1500);
    LCD_ShowString(1, 1, "               ");
    LCD_ShowString(2, 1, "               ");

    while (1)
    {
        Password_Input(Input_password);  // 输入旧密码
        if(Password_Proofread(Password, Input_password)){  // 验证旧密码
            LCD_ShowString(1, 1, "Please enter   ");
            LCD_ShowString(2, 1, "New password   ");
            Delay_ms(1500);
            LCD_ShowString(1, 1, "               ");
            LCD_ShowString(2, 1, "               ");
            break;
        } else {
            LCD_ShowString(1, 1, "Wrong password!");  // 旧密码错误提示
            Delay_ms(1500);
            if (Read_JZ_Buttons()!= key_mode){  // 检查按键
                LCD_ShowString(1, 1, "               ");
                return 0;
            } 
        }  
    }

    while (1)
    {
        if (Password_Input(Input_password)){  // 输入新密码
            break;
        } else{
            return 0;
        }
    }
    
    for ( i = 0; i < 6; i++)
    {
        Password[i] = Input_password[i];  // 保存新密码
    }
    Password_Write(Password);  // 写入新密码
    LCD_ShowString(1, 1, "successful!    ");  // 显示修改成功
    Delay_ms(1500);
    LCD_ShowString(1, 1, "               ");

    return 1;
}
#ifndef __SECURITY_H
#define __SECURITY_H

/**
 * @brief 定义初始密码
 */
#define Initial_Password (unsigned char*)"000000"

/**
 * @brief 将密码写入存储
 * @param Password 指向密码的指针
 */
void Password_Write(unsigned char* Password);

/**
 * @brief 从存储读取密码
 * @param Password 用于存储读取到的密码的指针
 */
void Password_Read(unsigned char* Password);

/**
 * @brief 初始化密码相关操作
 * @param Password 指向密码的指针
 */
void Password_Init(unsigned char* Password);

/**
 * @brief 解析按键值得到数字或符号
 * @return 解析后的结果
 */
unsigned char Key_Numbers_Parsing(void);

/**
 * @brief 处理密码输入过程
 * @param Input_Password 用于存储输入密码的指针
 * @return 输入是否完成的标志
 */
char Password_Input(unsigned char* Input_Password);

/**
 * @brief 比较原始密码和输入的当前密码是否一致
 * @param Original_password 原始密码
 * @param Now_Password 当前输入的密码
 * @return 密码是否一致的标志
 */
char Password_Proofread(unsigned char* Original_password, unsigned char* Now_Password);

/**
 * @brief 处理密码修改操作
 * @param Password 指向密码的指针
 * @return 密码修改是否成功的标志
 */
char Password_Change( unsigned char* Password);

#endif
#include <Buzzer.h>

#define beep Buzzer

/**
 * 定义变量用于控制蜂鸣器状态和定时器计数
 */
unsigned char ding,dong,flag,stop;
unsigned int n;

// 蜂鸣器启动函数
/**
 * @brief 启动蜂鸣器并设置相关定时器
 */
void Buzzer_On()
{
    TR0 = 1;
    Buzzer = 0;
}

// 蜂鸣器关断函数
/**
 * @brief 关闭蜂鸣器并设置相关定时器
 */
void Buzzer_Off()
{
    TR0 = 0;
    Buzzer = 1;
}

/**
 * @brief 初始化蜂鸣器相关定时器和中断设置
 */
void Buzzer_Init()
{
    TMOD |= 0x00;  // 定时器 0 工作模式 0
    TH0 = (8192 - 5000) / 32;  // 初值计算,假设定时 5ms
    TL0 = (8192 - 5000) % 32;
    EA = 1;  // 开总中断
    ET0 = 1;  // 允许定时器 0 中断
}

/**
 * @brief 初始化门铃相关定时器、中断设置和相关标志
 */
void Boorbell_Init()
{
    TMOD |= 0x10;  // 定时器 1 方式 1
    TH1 = 0xFF;
    TL1 = 0x06;  // 定时 250us
    // TR1 = 1;
    EA = 1;
    ET1 = 1;

    ding = 0;  // 叮声音  计数标志
    dong = 0;  // 咚声音  计数标志
    n = 0;  // 定时 0.5s 标志
    flag = 0;
    stop = 0;  // 结束标志
}

/**
 * @brief 定时器 0 中断服务函数,控制蜂鸣器状态取反
 */
void Buzzer_ISR() interrupt 1
{
    Buzzer = ~Buzzer;  // 蜂鸣器状态取反
}

/**
 * @brief 定时器 1 中断服务函数,控制门铃声音和相关标志
 */
void time1() interrupt 3  // 定时器 1 中断服务函数
{
    n++;
    TH1 = 0xFF;
    TL1 = 0x06;  // 250us

    if(n == 2000)  // 定时 0.5s  叮响 0.5 秒,咚响 0.5 秒
    {
        n = 0;
        if(flag == 0)
        {
            flag = ~flag;
        }
        else
        {
            flag = 0;
            stop = 1;
            TR1 = 0;  // 关闭定时器 1
        }
    }

    if(flag == 0)
    {  // 通过改变定时计数时间可以改变门铃的声音
        ding++;  // 叮
        if(ding == 1)
        {
            ding = 0;
            beep = ~beep;
        }
    }
    else
    {
        dong++;
        if(dong == 2)  // 咚
        {
            dong = 0;
            beep = ~beep;
        }
    }
}
#ifndef __BUZZER_H
#define __BUZZER_H

#include <REGX52.H>

/**
 * @brief 定义蜂鸣器控制引脚
 */
sbit Buzzer = P1^0;  

/**
 * @brief 启动门铃(可能是通过设置某个定时器)
 */
#define doorbell_Start() TR1=1

/**
 * @brief 打开蜂鸣器
 */
void Buzzer_On();

/**
 * @brief 关闭蜂鸣器
 */
void Buzzer_Off();

/**
 * @brief 初始化蜂鸣器相关设置
 */
void Buzzer_Init();

/**
 * @brief 初始化门铃相关设置
 */
void Boorbell_Init();

#endif

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值