郭天祥51单片机智能温度电子锁实验-附代码视频图片

概要

大三在读工科女生,分享学习成果,望有同频者可互相学习。

  本实验使用单片机实现一个具备密码验证、温度检测以及多种显示功能的综合系统。该系统能够通过密码验证来控制直流电机的运转,实现开锁与关锁功能,还集成了多种辅助模块,提升用户体验和系统的安全性与可靠性。通过LCD显示模块为用户提供直观的操作提示和信息反馈;利用LED指示模块展示系统的工作状态;蜂鸣器报警模块在密码错误等异常情况下持续发出警报;单总线通信实现温度传感器的数据采集,为系统增添更多功能维度;数码管模块用于显示密码输入正确与否的判断、温度等信息;矩阵按键模块则作为用户输入密码的接口。

整体架构流程

整体框架图

整体流程图

Proteus仿真图

硬件模块

温度传感器代码:

// 温度传感器相关函数
void dsreset(void) {
    uint i;
    DS = 0;
    i = 103;
    while (i > 0) i--;
    DS = 1;
    i = 4;
    while (i > 0) i--;
}

bit tmpreadbit(void) {
    uint i;
    bit dat;
    DS = 0; i++;
    DS = 1; i++; i++;
    dat = DS;
    i = 8;
    while (i > 0) i--;
    return (dat);
}

uchar tmpread(void) {
    uchar i, j, dat;
    dat = 0;
    for (i = 1; i <= 8; i++) {
        j = tmpreadbit();
        dat = (j << 7) | (dat >> 1);
    }
    return (dat);
}

void tmpwritebyte(uchar dat) {
    uint i;
    uchar j;
    bit testb;
    for (j = 1; j <= 8; j++) {
        testb = dat & 0x01;
        dat = dat >> 1;
        if (testb) {
            DS = 0;
            i++; i++;
            DS = 1;
            i = 8;
            while (i > 0) i--;
        } else {
            DS = 0;
            i = 8;
            while (i > 0) i--;
            DS = 1;
            i++; i++;
        }
    }
}

void tmpchange(void) {
    dsreset();
    delay(1);
    tmpwritebyte(0xcc);
    tmpwritebyte(0x44);
}

uint tmp() {
    uchar a, b;
    dsreset();
    delay(1);
    tmpwritebyte(0xcc);
    tmpwritebyte(0xbe);
    a = tmpread();
    b = tmpread();
    temp_value = b;
    temp_value <<= 8;
    temp_value = temp_value | a;
    f_temp = temp_value * 0.0625;
    temp_value = f_temp * 10 + 0.5;
    return temp_value;
}

// 显示温度后三位的函数
void DisplayTemperatureLastThree() {
    uint t = tmp();
    uchar digit1 = (t % 1000) / 100;  // 百位
    uchar digit2 = (t % 100) / 10;    // 十位
    uchar digit3 = t % 10;           // 个位
    Nixie(2, digit1);
    Nixie(3, digit2);
    Nixie(4, digit3);
}

温度传感器实时显示当前温度值。

LCD代码:

void write_com(uchar com) {
    lcdrs = 0; // 选择命令寄存器
    P0 = com;  // 将命令写入P0口
    delay(5);  // 短暂延时
    lcden = 1; // 使能LCD
    delay(5);  // 短暂延时
    lcden = 0; // 关闭使能
}

// LCD写数据函数
void write_data(uchar date) {
    lcdrs = 1; // 选择数据寄存器
    P0 = date; // 将数据写入P0口
    delay(5);  // 短暂延时
    lcden = 1; // 使能LCD
    delay(5);  // 短暂延时
    lcden = 0; // 关闭使能
}

// LCD初始化函数
void lcd_init() {
    write_com(0x38); // 设置16x2显示,5x7点阵,8位数据接口
    delay(5);
    write_com(0x0c); // 显示开,关闭光标
    delay(5);
    write_com(0x06); // 文字不动,地址自动+1
    delay(5);
    write_com(0x01); // 清屏
    delay(5);       // 延时等待清屏完成
}

// LCD显示字符串函数
void lcd_display(uchar *str, uchar line) {
    uchar i;
    write_com(0x80 + line); // 设置显示位置
    for (i = 0; str[i] != '\0'; i++) {
        write_data(str[i]); // 写入字符
        delay(5);           // 短暂延时
    }
}

当密码正确时,LCD 显示屏显示 “THANK YOU!!!”,当密码错误时,LCD 显示屏显示 “ERROR!” 。

矩阵键盘扫描代码:

// 矩阵键盘扫描函数
unsigned char MatrixKey() {
    unsigned char KeyNumber = 0;
    P3 = 0XFF;
    P3_0 = 0;
    if (P3_3 == 0) { KeyNumber = 1; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 2; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 3; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 4; return KeyNumber; }
    P3 = 0XFF;
    P3_7 = 0;
    if (P3_3 == 0) { KeyNumber = 5; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 6; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 7; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 8; return KeyNumber; }
    P3 = 0XFF;
    P3_0 = 0;
    if (P3_3 == 0) { KeyNumber = 9; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 10; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 11; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 12; return KeyNumber; }
    P3 = 0XFF;
    P3_7 = 0;
    if (P3_3 == 0) { KeyNumber = 13; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 14; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 15; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 16; return KeyNumber; }
    return KeyNumber;
}

本次实验使用到矩阵键盘,设定正确密码为:s17。

主函数分析:

// 主函数
void main() {
    Timer0_Init();
    lcd_init();  // 初始化LCD
    PassLen = my_strlen(Password);  // 使用自定义的 strlen 函数
    while (1) {
        // 上电即开始测试温度并显示后三位温度值
        tmpchange();
        DisplayTemperatureLastThree();

        if (isShow) {
            // 初始状态下,数码管显示提示输入密码相关信息,这里简单显示一个横线(可根据需求改更合适提示)
            ShowChar(0, 0);
            ShowChar(1, 0);
            ShowChar(3, 0);
            ShowChar(4, 0);
            ShowChar(5, 0);
            ShowChar(6, 0);
        } else {
            if (isTrue == 1) {
                // 密码验证成功后的数码管显示逻辑(已在中断函数里实现部分,这里可保持或添加更多)
            } else if (isTrue == 2) {
                // 密码验证失败后的数码管显示逻辑(已在中断函数里实现部分,这里可保持或添加更多)
            }
        }
    }

完整代码:

#include "reg52.h"
#include <stdio.h>

#define uchar unsigned char
#define uint unsigned int

// 自定义 strlen 函数
unsigned char my_strlen(char *str) {
    unsigned char len = 0;
    while (*str!= '\0') {
        len++;
        str++;
    }
    return len;
}

// 定义引脚
sbit dula = P2^6;  // P2.6
sbit wela = P2^7;  // P2.7
sbit dianji = P1^7; // 电机控制引脚
sbit led1 = P1^0;    // LED 控制引脚
sbit beep = P2^3;    // 蜂鸣器控制引脚
sbit DS = P2^2;      // 温度传感器引脚

// LCD引脚定义
sbit lcden = P3^4;   // LCD使能引脚 (使用P3^4)
sbit lcdrs = P3^5;   // LCD数据/命令选择引脚 (使用P3^5)

// 定义 P3 口的位变量
sbit P3_0 = P3^0;
sbit P3_1 = P3^1;
sbit P3_2 = P3^2;
sbit P3_3 = P3^3;
sbit P3_6 = P3^6;
sbit P3_7 = P3^7;

// 定义 P2 口的位变量
sbit P2_6 = P2^6;
sbit P2_7 = P2^7;

// 定义变量
uchar num = 0, show_num = 1;
uchar code table[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
unsigned char i = 0;
unsigned char NixieTable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x00};
unsigned char code Locations[] = {0x7e, 0x7d, 0x7b, 0x77, 0x2f, 0x1f, 0x3f};
unsigned char code ShowC[] = {0x40, 0x73, 0x79, 0x77, 0x7c, 0x39, 0x5e, 0x71, 0x76};
unsigned char PassLen = 0;
bit isShow = 1;
unsigned char isTrue = 0;
char Password[] = "6";
char temp[20] = {0};

// 温度相关变量
uint temp_value; // 温度值
float f_temp;    // 浮点温度值

// LCD显示相关变量
uchar code lcd_table[] = "   THANK YOU!!!   ";
uchar code lcd_table1[] = "    DXT XX XFQ   ";
uchar code lcd_error[] = "     ERROR!      ";

// 延时函数
void delay(uint ms) {
    uint i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--);
}

// 显示字符函数
void ShowChar(unsigned char Location, unsigned char Number) {
    P2_7 = 1;
    P0 = Locations[Location];
    P2_7 = 0;
    P2_6 = 1;
    P0 = ShowC[Number];
    P2_6 = 0;
    delay(1);
    P0 = 0X0;
}

// 在指定数码管位置显示数字(0 - F)的函数
void Nixie(unsigned char Location, unsigned char Number) {
    P2_7 = 1;
    P0 = Locations[Location];
    P2_7 = 0;
    P2_6 = 1;
    P0 = NixieTable[Number];
    P2_6 = 0;
    delay(1);
    P0 = 0X0;
}

// 字符串比较函数
bit MyStrCmp(char *a, char *b) {
    while (*a!= '\0' || *b!= '\0') {
        if (*a == *b) {
            a++;
            b++;
        } else {
            return 0;
        }
    }
    return 1;
}

// 矩阵键盘扫描函数
unsigned char MatrixKey() {
    unsigned char KeyNumber = 0;
    P3 = 0XFF;
    P3_0 = 0;
    if (P3_3 == 0) { KeyNumber = 1; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 2; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 3; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 4; return KeyNumber; }
    P3 = 0XFF;
    P3_7 = 0;
    if (P3_3 == 0) { KeyNumber = 5; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 6; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 7; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 8; return KeyNumber; }
    P3 = 0XFF;
    P3_0 = 0;
    if (P3_3 == 0) { KeyNumber = 9; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 10; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 11; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 12; return KeyNumber; }
    P3 = 0XFF;
    P3_7 = 0;
    if (P3_3 == 0) { KeyNumber = 13; return KeyNumber; }
    if (P3_2 == 0) { KeyNumber = 14; return KeyNumber; }
    if (P3_1 == 0) { KeyNumber = 15; return KeyNumber; }
    if (P3_6 == 0) { KeyNumber = 16; return KeyNumber; }
    return KeyNumber;
}

// 定时器初始化函数
void Timer0_Init() {
    TMOD = 0x01;
    TF0 = 0;
    TR0 = 1;
    TH0 = 64535 / 256;
    TL0 = 64535 % 256;
    ET0 = 1;
    EA = 1;
}

// LED 流水灯从上往下流动
void LED_Flow() {
    uchar i;
    for (i = 0; i < 8; i++) {
        P1 = ~(0x01 << i); // 从上往下流动
        delay(200);        // 延时控制流动速度
    }
}

// LED 全部闪烁
void LED_Blink() {
    P1 = 0x00; // 全部亮
    delay(500);
    P1 = 0xFF; // 全部灭
    delay(500);
}

// 温度传感器相关函数
void dsreset(void) {
    uint i;
    DS = 0;
    i = 103;
    while (i > 0) i--;
    DS = 1;
    i = 4;
    while (i > 0) i--;
}

bit tmpreadbit(void) {
    uint i;
    bit dat;
    DS = 0; i++;
    DS = 1; i++; i++;
    dat = DS;
    i = 8;
    while (i > 0) i--;
    return (dat);
}

uchar tmpread(void) {
    uchar i, j, dat;
    dat = 0;
    for (i = 1; i <= 8; i++) {
        j = tmpreadbit();
        dat = (j << 7) | (dat >> 1);
    }
    return (dat);
}

void tmpwritebyte(uchar dat) {
    uint i;
    uchar j;
    bit testb;
    for (j = 1; j <= 8; j++) {
        testb = dat & 0x01;
        dat = dat >> 1;
        if (testb) {
            DS = 0;
            i++; i++;
            DS = 1;
            i = 8;
            while (i > 0) i--;
        } else {
            DS = 0;
            i = 8;
            while (i > 0) i--;
            DS = 1;
            i++; i++;
        }
    }
}

void tmpchange(void) {
    dsreset();
    delay(1);
    tmpwritebyte(0xcc);
    tmpwritebyte(0x44);
}

uint tmp() {
    uchar a, b;
    dsreset();
    delay(1);
    tmpwritebyte(0xcc);
    tmpwritebyte(0xbe);
    a = tmpread();
    b = tmpread();
    temp_value = b;
    temp_value <<= 8;
    temp_value = temp_value | a;
    f_temp = temp_value * 0.0625;
    temp_value = f_temp * 10 + 0.5;
    return temp_value;
}

// 显示温度后三位的函数
void DisplayTemperatureLastThree() {
    uint t = tmp();
    uchar digit1 = (t % 1000) / 100;  // 百位
    uchar digit2 = (t % 100) / 10;    // 十位
    uchar digit3 = t % 10;           // 个位
    Nixie(2, digit1);
    Nixie(3, digit2);
    Nixie(4, digit3);
}

// LCD写命令函数
void write_com(uchar com) {
    lcdrs = 0; // 选择命令寄存器
    P0 = com;  // 将命令写入P0口
    delay(5);  // 短暂延时
    lcden = 1; // 使能LCD
    delay(5);  // 短暂延时
    lcden = 0; // 关闭使能
}

// LCD写数据函数
void write_data(uchar date) {
    lcdrs = 1; // 选择数据寄存器
    P0 = date; // 将数据写入P0口
    delay(5);  // 短暂延时
    lcden = 1; // 使能LCD
    delay(5);  // 短暂延时
    lcden = 0; // 关闭使能
}

// LCD初始化函数
void lcd_init() {
    write_com(0x38); // 设置16x2显示,5x7点阵,8位数据接口
    delay(5);
    write_com(0x0c); // 显示开,关闭光标
    delay(5);
    write_com(0x06); // 文字不动,地址自动+1
    delay(5);
    write_com(0x01); // 清屏
    delay(5);       // 延时等待清屏完成
}

// LCD显示字符串函数
void lcd_display(uchar *str, uchar line) {
    uchar i;
    write_com(0x80 + line); // 设置显示位置
    for (i = 0; str[i] != '\0'; i++) {
        write_data(str[i]); // 写入字符
        delay(5);           // 短暂延时
    }
}

// 定时器中断服务函数
void Timer0_ISR() interrupt 1 {
    unsigned char Key;
    TR0 = 0;
    if (isShow!= 1) {
        isShow = 1;
        isTrue = 0;
        i = 0;
        delay(3000);
    }
    Key = MatrixKey();
    if (Key!= 0) {
        switch (Key) {
            case 1: temp[i] = '1'; break;
            case 2: temp[i] = '2'; break;
            case 3: temp[i] = '3'; break;
            case 4: temp[i] = '4'; break;
            case 5: temp[i] = '5'; break;
            case 6: temp[i] = '6'; break;
            case 7: temp[i] = '7'; break;
            case 8: temp[i] = '8'; break;
            case 9: temp[i] = '9'; break;
            case 10: temp[i] = 'a'; break;
            case 11: temp[i] = 'b'; break;
            case 12: temp[i] = 'c'; break;
            case 13: temp[i] = 'd'; break;
            case 14: temp[i] = 'e'; break;
            case 15: temp[i] = 'f'; break;
            case 16: temp[i] = 'g'; break;
        }
        i++;
        if (i <= 6) {
            Nixie(0, i);
        }
        if (i >= PassLen) {
            bit isEq = MyStrCmp(temp, Password);
            if (isEq) {
                isShow = 0;
                isTrue = 1;
                beep = 0;       // 蜂鸣器滴一声
                delay(1000);
                beep = 1;
                dianji = 0;     // 电机停止
                ShowChar(0, 7);
                ShowChar(1, 8);
                lcd_display(lcd_table, 0x00);  // 显示"THANK YOU!!!"
                lcd_display(lcd_table1, 0x40); // 显示"DXT XX XFQ"
                while (isTrue == 1) {
                    LED_Flow(); // 流水灯从上往下流动
                }
            } else {
                isShow = 0;
                isTrue = 2;
                beep = 0;       // 蜂鸣器长响
                dianji = 1;     // 电机启动
                ShowChar(0, 4);
                ShowChar(1, 7);
                ShowChar(2, 7);
                lcd_display(lcd_error, 0x00); // 显示"ERROR!"
                while (isTrue == 2) {
                    LED_Blink(); // 流水灯全部闪烁
                }
            }
        }
    }
    TR0 = 1;
}

// 主函数
void main() {
    Timer0_Init();
    lcd_init();  // 初始化LCD
    PassLen = my_strlen(Password);  // 使用自定义的 strlen 函数
    while (1) {
        // 上电即开始测试温度并显示后三位温度值
        tmpchange();
        DisplayTemperatureLastThree();

        if (isShow) {
            // 初始状态下,数码管显示提示输入密码相关信息,这里简单显示一个横线(可根据需求改更合适提示)
            ShowChar(0, 0);
            ShowChar(1, 0);
            ShowChar(3, 0);
            ShowChar(4, 0);
            ShowChar(5, 0);
            ShowChar(6, 0);
        } else {
            if (isTrue == 1) {
                // 密码验证成功后的数码管显示逻辑(已在中断函数里实现部分,这里可保持或添加更多)
            } else if (isTrue == 2) {
                // 密码验证失败后的数码管显示逻辑(已在中断函数里实现部分,这里可保持或添加更多)
            }
        }
    }
}

技术细节

本次实验采用郭天祥STC89C52单片机完成,此代码用在其他单片机上需要更改引脚配置,仅用于学习,

小结

项目成果:

数码管上显示实时温度,通过矩阵键盘输入密码,输入过程中数码管实时显示已输入的密码位数,密码输入完成后,系统能够准确比对输入密码与预设密码,当密码正确时,数码管显示“H”,蜂鸣器发出一声提示音,电机跟随流水灯频率转动,LCD 显示屏显示 “THANK YOU!!!”,同时 LED 灯从上往下流动展示流水灯提示效果;当密码错误时,数码管显示“F”,蜂鸣器报警长响,LCD 显示屏显示 “ERROR!” ,LED 灯进行全部亮灭闪烁的报警提示效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值