当前位置: 首页 > news >正文

C51 单片机学习(一):基础外设

参考

  • 51单片机入门教程

1. 单片机简介

1.1 定义

  • 单片机(Micro Controller Unit,简称 MCU)
    • 内部集成了 CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能
    • 单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED 等)的控制
    • 单片机跟计算机相比,单片机算是一个袖珍版计算机,一个芯片就能构成完整的计算机系统。但在性能上,与计算机相差甚远,但单片机成本低、体积小、结构简单,在生活和工业控制领域大有所用
    • 应用领域:智能仪表、实时工控、通讯设备、导航系统、家用电器等

1.2 STC89C52 单片机

  • STC 公司 51 单片机系列,8 位,RAM(512 字节),ROM(8K,Flash),工作频率 12MHz

    • STC89C52RC 的晶振集成在芯片内部,工作频率为 11.0592MHz
    • 单片机晶振的作用:利用一种能将电能和机械能相互转换的晶体,在单片机中提供一个精确的时钟信号,以便单片机能够正确执行其功能

    51 单片机为什么叫 51?

    • 是因为这种单片机最初采用的是英特尔公司的 8051 指令系统。随着时间的推移,有多家公司生产了兼容 8051 指令系统的单片机,它们虽然功能各异,但是核心架构相同,因此都被统称为 51 单片机
    • “51” 在这里代表了 8051 架构,也就是 Intel 公司发明的一种早期的单片控制器架构
  • 命名规则
    在这里插入图片描述

在这里插入图片描述

1.3 单片机内部结构图

  • 静态随机存取存储器(Static Random-Access Memory,SRAM)是随机存取存储器的一种,所谓的 “静态”,是指这种存储器只要保持通电,里面储存的数据就可以恒常保持
  • 只读存储器(Read-Only Memory,ROM)以非破坏性读出方式工作,只能读出无法写入信息,信息一旦写入后就固定下来,即使切断电源,信息也不会丢失,所以又称为固定存储器
  • 闪存是一种非易失性(Non-Volatile)内存,在没有电流供应的条件下也能够长久地保持数据
  • 单片机通过配置寄存器来控制内部线路的连接,通过内部不同线路的连接来实现不同电路以完成不同功能
    在这里插入图片描述

在这里插入图片描述

1.4 单片机管脚图

在这里插入图片描述

1.5 单片机最小系统

在这里插入图片描述

1.6 单片机核心原理图

在这里插入图片描述

2. LED

2.1 简介

  • 发光二极管(Light Emitting Diode,LED),用于照明、广告灯、指引灯、屏幕,是一种冷光源,因此比较环保且响应速度快,左图:左边是正极、右边是负极
    在这里插入图片描述

2.2 LED 原理图

在这里插入图片描述

  • 单片机上 RP9 上的数字 102:前面两位数是一个有效数字 10,第三位数字就是倍率 00,102 = 10*10^2 = 1KΩ(电阻或电容的通用读数方式),此处的电阻也称为限流电阻
  • 单片机可以通过控制 IO 口的输出模式和电平状态来实现对 IO 口输出高低电平的控制
    • 1、设置 IO 口为输出模式:在单片机的相应寄存器中设置 IO 口对应的引脚为输出模式
    • 2、控制 IO 口输出高低电平:将 IO 口对应的引脚设置为期望输出的电平,通常使用高电平表示逻辑 “1”,低电平表示逻辑 “0”

    单片机 TTL 电平:高电平 5V,低电平 0V,LED 具有单向导电性,当 LED 的正端接了高电位,负端连接了低电位,且正负端电位差超过 1.8V 以上时,LED 就会亮起来

2.3 进制转换

在这里插入图片描述

2.4 C51 数据类型

在这里插入图片描述

2.5 示例代码

  • 2-1 点亮一个 LED
#include <REGX52.H>  // 定义寄存器和端口(识别 P2 口)void main() {P2 = 0xFE;  // 1111 1110,0x 前缀表示 十六进制,引脚配置为 “低电平有效”// P2 = 0x55;  // 0101 0101,8 个 LED 灯间隔点亮while (1) {}
}
  • 2-2 LED 闪烁
#include <REGX52.H>
#include <INTRINS.H>  // _nop_(); 需要的头文件void Delay500ms() {  // @12.000 MHzunsigned char i, j, k;_nop_();  // 空操作命令,确保编译器不会对后续的循环优化i = 4;j = 205;k = 187;// 外层循环的条件是 i != 0// 内层两层循环的条件分别是 j != 0 && k != 0do {do {while (--k);  // 循环耗时操作} while (--j);    // 嵌套循环耗时操作} while (--i);
}void main() {while(1) {P2 = 0xFE;     // 1111 1110Delay500ms();  // 单片机当中每次都是以 MHZ 速度运行,闪烁太快人眼看不出,因此要加延迟函数P2 = 0xFF;     // 1111 1111Delay500ms();}
}
  • 2-3 LED 流水灯(固定延时时间)
#include <REGX52.H>
#include <INTRINS.H>void Delay500ms() {  // @12.000 MHzunsigned char i, j, k;_nop_();i = 4;j = 205;k = 187; do {do {while (--k);} while (--j);} while (--i);
}void main() {while (1) {P2 = 0xFE;  // 1111 1110Delay500ms();P2 = 0xFD;  // 1111 1101Delay500ms();P2 = 0xFB;  // 1111 1011Delay500ms();P2 = 0xF7;  // 1111 0111Delay500ms();P2 = 0xEF;  // 1110 1111Delay500ms();P2 = 0xDF;  // 1101 1111Delay500ms();P2 = 0xBF;  // 1011 1111Delay500ms();P2 = 0x7F;  // 0111 1111Delay500ms();}
}
  • 2-4 LED 流水灯2(自定义延时时间)
#include <REGX52.H>void Delay1ms(unsigned int xms);  // @12.000MHzvoid main() {while (1) {P2 = 0xFE;  // 1111 1110Delay1ms(100);P2 = 0xFD;  // 1111 1101Delay1ms(100);P2 = 0xFB;  // 1111 1011Delay1ms(100);P2 = 0xF7;  // 1111 0111Delay1ms(100);P2 = 0xEF;  // 1110 1111Delay1ms(100);P2 = 0xDF;  // 1101 1111Delay1ms(100);P2 = 0xBF;  // 1011 1111Delay1ms(100);P2 = 0x7F;  // 0111 1111Delay1ms(100);}
}void Delay1ms(unsigned int xms)	{  // @12.000MHzunsigned char i, j;while (xms) {i = 2;j = 239;do {while (--j);} while (--i);xms--;}
}

3. 独立按键

3.1 按键介绍

  • 轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开
    在这里插入图片描述

3.2 独立按键原理图

  • 单片机上电时所有 IO 口默认都是高电平,那么按键没有按下时这个 IO 口就是高电平,按下后这个 IO 口就变成低电平,寄存器会检测 IO 口的电平,然后再读回这个寄存器中
    在这里插入图片描述

3.3 C51 数据运算

在这里插入图片描述

3.4 C51 基本语句

在这里插入图片描述

3.5 按键的抖动

  • 对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动
    在这里插入图片描述

3.6 示例代码

  • 3-1 独立按键控制 LED 亮灭
#include <REGX52.H>void main() {while (1) {if (P3_1 == 0 || P3_0 == 0) {  // 如果 K1 按键(RXD,P3_1)或 K2 按键(TXD,P3_0)按下P2_0 = 0;  // LED1 输出 0,点亮} else {P2_0 = 1;  // LED1 输出 1,熄灭}}
}
  • 3-2 独立按键控制 LED 状态
#include <REGX52.H>void Delay(unsigned int xms) {unsigned char i, j;while (xms) {i = 2;j = 239;do {while (--j);} while (--i);xms--;}
}void main() {while (1) {if (P3_1 == 0) {        // 如果 K1 按键按下Delay(20);          // 延时,以消除按键抖动带来的影响while (P3_1 == 0);  // 判断 K1 按键是否仍处于按下状态,松手检测Delay(20);          // 延时,以消除按键抖动带来的影响P2_0 = ~P2_0;       // LED1 取反}}
}
  • 3-3 独立按键控制 LED 显示二进制
#include <REGX52.H>void Delay(unsigned int xms) {unsigned char i, j;while (xms--) {i = 2;j = 239;do {while (--j);} while (--i);}
}void main() {unsigned char LEDNum = 0;   // 无符号字符型(所占1字节 = 8bit位)刚好对应着 8 位二进制的数据while (1) {if (P3_1 == 0) {        // 如果 K1 按键按下Delay(20);          // 延时消抖while (P3_1 == 0);  // 判断 K1 按键是否仍处于按下状态,松手检测Delay(20);          // 延时消抖LEDNum++;           // 变量自增,用于切换 LED 灯的状态// P2 口上电之后和单片机的 IO 上电一样都是默认的是高电平:1111 1111P2 = ~LEDNum;       // 变量取反输出给 LED,控制 LED 灯的亮灭}}
}
  • 3-4 独立按键控制 LED 移位
// K1 = P3_1;K2 = P3_0;K3 = P3_2;K4 = P3_3
#include <REGX52.H>void Delay(unsigned int xms);
unsigned char LEDNum;  // 全局变量定义默认为 0void main() {P2 = ~0x01;     // 上电默认 LED1 点亮while (1) {if (P3_1 == 0) {       // 如果 K1 按键按下Delay(20);while (P3_1 == 0);Delay(20);LEDNum++;            // LEDNum 自增if (LEDNum >= 8)	 // 限制 LEDNum 自增范围LEDNum = 0;P2 = ~(0x01 << LEDNum);	 // LED 的第 LEDNum 位点亮}if (P3_0 == 0) {     // 如果 K2 按键按下Delay(20);while (P3_0 == 0);Delay(20);if (LEDNum == 0)    // LEDNum 减到 0 后变为 7LEDNum = 7;else                // LEDNum 未减到 0,自减LEDNum--;P2 = ~(0x01 << LEDNum);  // LED 的第 LEDNum 位点亮}}
}void Delay(unsigned int xms) {unsigned char i, j;while (xms--) {i = 2;j = 239;do {while (--j);} while (--i);}
}

4. 数码管

4.1 简介

  • LED 数码管:一种简单、廉价的显示器,是由多个发光二极管封装在一起组成 “8” 字型的器件
    • 数码管分共阳数码管和共阴数码管
      • 共阳数码管:把 8 段 LED 的正极并在一起作为公共端连接在 5V 上(共阳极),然后 8 个 LED 通过单片机的 8 个 IO 端口输出高低电平使其决定点亮哪几个段
    • 数码管其实就是 8 个段的发光二极管,只点亮其中的几个段即可显示出数字或字母用来表达信息
      在这里插入图片描述

4.2 数码管的引脚定义

  • 以共阴极为例(下图右上),若要显示数字 6

    • 1、把共阴极的公共端(位选端)接地/负极,即给这个数据 “0” 或是低电平
    • 2、把段码 A、C、D、E、F、G 接正极,即给这个数据 “1” 或是高电平
      在这里插入图片描述
  • 以共阴极为例(下图右上),若要在第三位数码管显示数字 1

    • 1、把共阴极的公共端(位选端)当中的第三位数码管接地/负极,即给这个数据 “0” 或是低电平
    • 2、再给 1、2、4 上的位选给 “1” 或是高电平
      在这里插入图片描述

4.3 数码管原理图

  • LED1~LED8 都是接到 138 译码器上的输出端,138 译码器原理如下

    • 把 P22、P23、P24 三个端口变成 8 个端口(LED1~LED8)来控制
    • 左边的 A、B、C 是输入端(正极),右边 Y0~Y7 是输出端(负极)
      • C 是高位、B 在中间、A 是低位
      • C B A 按高、低位排序后,再将二进制转换为十进制数,对应着输出端 Y0~Y7,例如 C B A:0 0 0 = Y0,C B A:0 0 1 = Y1(对应 LED2),C B A:1 0 1 = Y5,C B A:1 1 0 = Y6
    • 右下角三个引脚称为使能端(相当于一种开关,如果使能电平有效,它就可以工作)
  • 74HC245 芯片作用:也称双向数据缓冲器,用来提高芯片驱动能力

  • 电容 CC2 作用:起到电源滤波作用,使得芯片的供电更加稳定

  • RP4 电阻:限流作用,100R 单位为 Ω
    在这里插入图片描述

  • 位选

    • 如 C B A = 0 1 1 = Y3 = LED4,LED4 就是有效的/允许显示数码管的,那么其它的数码管是不能被允许显示的/不是有效的
  • 段选

    • 选中之后,就是给 P0 口段码的数据:假设给上数据,经过缓冲送到公共端的段码端。那么,送到段码端就会显示数码管相对应的数字,P0 口给上数据是从高位到低位给上段码端的

4.3 C51 数组 & 子函数

  • 数组:把相同类型的一系列数据统一编制到某一个组别中,可以通过数组名 + 索引号简单快捷的操作大量数据

    int x[3];         // 定义一组变量(3个)
    int x[]={1,2,3};  // 定义一组变量并初始化x[0];             //引用数组的第0个变量
    x[1];             //引用数组的第1个变量
    x[2];             //引用数组的第2个变量
    // 引用 x[3] 时,数组越界,读出的数值不确定,应避免这种操作
    
  • 子函数:将完成某一种功能的程序代码单独抽取出来形成一个模块,在其它函数中可随时调用此模块,以达到代码的复用和优化程序结构的目的

    void Function(unsigned char x, y) {}返回值 函数名(形参){函数体
    }
    

4.4 数码管段码表

在这里插入图片描述

4.5 数码管驱动方式

  • 单片机直接扫描:硬件设备简单,但会耗费大量的单片机 CPU 时间
  • 专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可(如下述 TM1640
    在这里插入图片描述

4.6 示例代码

  • 4-1 静态数码管显示
#include <REGX52.H>// 数码管段码表
unsigned char NixieTable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};// Location:数码管的位置,Number:显示数码管的数字
void Nixie(unsigned char Location, Number) {switch (Location) {  // 位码输出case 1:P2_4 = 1; P2_3 = 1; P2_2 = 1;break;case 2:P2_4 = 1; P2_3 = 1; P2_2 = 0;break;case 3:P2_4 = 1; P2_3 = 0; P2_2 = 1;break;case 4:P2_4 = 1; P2_3 = 0; P2_2 = 0;break;case 5:P2_4 = 0; P2_3 = 1; P2_2 = 1;break;case 6:P2_4 = 0; P2_3 = 1; P2_2 = 0;break;case 7:P2_4 = 0; P2_3 = 0; P2_2 = 1;break;case 8:P2_4 = 0; P2_3 = 0; P2_2 = 0;break;}P0 = NixieTable[Number];  // 段码输出
}void main() {Nixie (2, 3);    // 在数码管的第 2 位置显示 3while (1) {}
}
  • 4-2 动态数码管显示
#include <REGX52.H>// 数码管段码表
unsigned char NixieTable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};//延时子函数
void Delay(unsigned int xms) {unsigned char i, j;while (xms--) {i = 2;j = 239;do {while (--j);} while (--i);}
}// Location:数码管的位置,Number:显示数码管的数字
void Nixie(unsigned char Location, Number) {switch (Location) {  // 位码输出case 1:P2_4 = 1; P2_3 = 1; P2_2 = 1;break;case 2:P2_4 = 1; P2_3 = 1; P2_2 = 0;break;case 3:P2_4 = 1; P2_3 = 0; P2_2 = 1;break;case 4:P2_4 = 1; P2_3 = 0; P2_2 = 0;break;case 5:P2_4 = 0; P2_3 = 1; P2_2 = 1;break;case 6:P2_4 = 0; P2_3 = 1; P2_2 = 0;break;case 7:P2_4 = 0; P2_3 = 0; P2_2 = 1;break;case 8:P2_4 = 0; P2_3 = 0; P2_2 = 0;break;}P0 = NixieTable[Number];  // 段码输出Delay(1);                 // 显示一段时间P0 = 0x00;                // 段码清 0,消影
}void main() {while (1) {Nixie(1, 1);    // 在数码管的第 1 位置显示 1
//		Delay(20);Nixie(2, 2);    // 在数码管的第 2 位置显示 2
//		Delay(20);Nixie(3, 3);    // 在数码管的第 3 位置显示 3
//		Delay(20);}
}

5. 模块化编程和 LCD 调试工具

5.1 模块化编程

  • 传统方式编程
    • 所有的函数均放在 main.c 里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路
  • 模块化编程
    • 把各个模块代码放在不同 .c 文件里,在 .h 文件里提供外部可调用函数的声明,其它 .c 文件想使用其中的代码时,只需 #include “XXX.h” 文件即可,模块化编程可极大的提高代码可读性、可维护性、可移植性等
      • .c 文件:函数、变量的定义
      • .h 文件:可被外部调用的函数、变量的声明
  • 注意事项
    • 任何自定义的变量、函数在调用前必须有定义或声明(同一个.c)
    • 使用到的自定义函数的 .c 文件必须添加到工程参与编译
    • 使用到的 .h 文件必须要放在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义)
      在这里插入图片描述

5.2 C 预编译

  • C 语言的预编译以 # 开头,作用是在真正的编译开始之前,对代码做一些处理(预编译)
    在这里插入图片描述

5.3 LCD1602 调试工具

  • 使用 LCD1602 液晶屏作为调试窗口,提供类似 printf 函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示
    • LCD1602 连接的口是 P0 口 还占用三个 P2 口,所以使用 LCD1602 液晶屏后,三个 LED 就不能进行使用,数码管也不能使用

在这里插入图片描述

  • LCD1602 原理图
    在这里插入图片描述

5.4 使用示例

#include <REGX52.H>
#include <LCD1602.H>int main(void) {unsigned int Number = 51;signed int negative = -1;LCD_Init();while (1) {LCD_ShowChar(1, 1, 'W');LCD_ShowString(1, 2, "XH");LCD_ShowNum(1, 4, Number,2);LCD_ShowSignedNum(1, 7, negative, 1);LCD_ShowHexNum(2, 1, 0xFF, 2);LCD_ShowBinNum(2, 4, 0x00, 8);}
}

6. 矩阵键盘

6.1 简介

  • 在键盘中按键数量较多时,为了减少 I/O 口的占用,通常将按键排列成矩阵形式,采用逐行或逐列的 “扫描”,就可以读出任何位置按键的状态
    在这里插入图片描述

  • 扫描

    • 数码管扫描(输出扫描)
      • 原理:显示第 1 位 → 显示第 2 位 → 显示第 3 位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果
    • 矩阵键盘扫描(输入扫描)
      • 原理:读取第 1 行(列) → 读取第 2 行(列) → 读取第 3 行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果

    以上两种扫描方式的共性:节省 I/O 口

  • 单片机 IO 口模式

    • 单片机的 IO 口是一种弱上拉的模式,又被称作是准双向口(input,output 既可以输入又可以输出)
  • 为什么单片机它的 IO 口是默认为高电平呢?

    • 是因为有一个上拉电阻把低电平变成高电平了,所以才导致单片机是高电平
    • 还有一个是当口线输出为 1 的时候驱动能力很弱,允许外部装置将其拉低
    • 当引脚的输出为低电平的时候,它的驱动能力很强,可以吸收相当大的电流
    • 单片机中 P1、P2、P3 都是一种弱上拉的一种模式

6.2 矩阵键盘原理图

在这里插入图片描述

6.3 使用示例

  • MatrixKey.h
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__unsigned char MatrixKey();#endif
  • MatrixKey.c
#include <REGX52.H>
#include "Delay.h"/*** @brief  矩阵键盘读取按键键码* @param  无* @retval KeyNumber 按下按键的键码值如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回 0
*/
unsigned char MatrixKey() {unsigned char KeyNumber = 0;P1 = 0xFF;P1_3 = 0;if (P1_7 == 0) {Delay(20); while(P1_7 == 0); Delay(20); KeyNumber = 1;}if (P1_6 == 0) {Delay(20); while(P1_6 == 0); Delay(20); KeyNumber = 5;}if (P1_5 == 0) {Delay(20); while(P1_5 == 0); Delay(20); KeyNumber = 9;}if (P1_4 == 0) {Delay(20); while(P1_4 == 0); Delay(20); KeyNumber = 13;}P1 = 0xFF;P1_2 = 0;if (P1_7 == 0) {Delay(20); while(P1_7 == 0); Delay(20); KeyNumber = 2;}if (P1_6 == 0) {Delay(20); while(P1_6 == 0); Delay(20); KeyNumber = 6;}if (P1_5 == 0) {Delay(20); while(P1_5 == 0); Delay(20); KeyNumber = 10;}if (P1_4 == 0) {Delay(20); while(P1_4 == 0); Delay(20); KeyNumber = 14;}P1 = 0xFF;P1_1 = 0;if (P1_7 == 0) {Delay(20); while(P1_7 == 0); Delay(20); KeyNumber = 3;}if (P1_6 == 0) {Delay(20); while(P1_6 == 0); Delay(20); KeyNumber = 7;}if (P1_5 == 0) {Delay(20); while(P1_5 == 0); Delay(20); KeyNumber = 11;}if (P1_4 == 0) {Delay(20); while(P1_4 == 0); Delay(20); KeyNumber = 15;}P1 = 0xFF;P1_0 = 0;if (P1_7 == 0) {Delay(20); while(P1_7 == 0); Delay(20); KeyNumber = 4;}if (P1_6 == 0) {Delay(20); while(P1_6 == 0); Delay(20); KeyNumber = 8;}if (P1_5 == 0) {Delay(20); while(P1_5 == 0); Delay(20); KeyNumber = 12;}if (P1_4 == 0) {Delay(20); while(P1_4 == 0); Delay(20); KeyNumber = 16;}return KeyNumber;
}
  • main.c
#include <REGX52.H>
#include "Delay.h"      // 包含 Delay 头文件
#include "LCD1602.h"    // 包含 LCD1602 头文件
#include "MatrixKey.h"  // 包含矩阵键盘头文件unsigned char KeyNum;void main() {LCD_Init();	  // LCD 初始化LCD_ShowString(1, 1, "MatrixKey:");  // LCD 显示字符串while (1) {KeyNum = MatrixKey();  // 获取矩阵键盘键码if (KeyNum) {  // 如果有按键按下LCD_ShowNum(2, 1, KeyNum, 2);  // LCD  显示键码}}
}

6.4 矩阵键盘密码锁

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"unsigned char KeyNum;
unsigned int Password, Count;void main() {LCD_Init();LCD_ShowString(1, 1, "Password:");while (1) {KeyNum = MatrixKey();if (KeyNum) {if (KeyNum <= 10)	{    // 如果 S1~S10 按键按下,输入密码if (Count<4) {       // 如果输入次数小于 4Password *= 10;  // 密码左移一位Password += KeyNum % 10;  // 获取一位密码Count++;    // 计次加一}LCD_ShowNum(2, 1, Password, 4);    // 更新显示}if (KeyNum == 11) {   // 如果 S11 按键按下,确认if (Password == 2345) {   // 如果密码等于正确密码LCD_ShowString(1, 14, "OK ");   // 显示 OKPassword = 0;    // 密码清零Count = 0;       // 计次清零LCD_ShowNum(2, 1, Password, 4);   // 更新显示} else {LCD_ShowString(1, 14, "ERR");  // 显示 ERRPassword = 0;    // 密码清零Count = 0;		 // 计次清零LCD_ShowNum(2, 1, Password, 4);  // 更新显示}}if (KeyNum == 12) {   // 如果 S12 按键按下,取消Password = 0;     // 密码清零Count = 0;        // 计次清零LCD_ShowNum(2, 1, Password, 4);  // 更新显示}}}
}

相关文章:

C51 单片机学习(一):基础外设

参考 51单片机入门教程 1. 单片机简介 1.1 定义 单片机&#xff08;Micro Controller Unit&#xff0c;简称 MCU&#xff09; 内部集成了 CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能单片机的任务是信息采集&#xff08;依靠传感器&#xff09;、处…...

Docker容器引擎镜像创建

目录 一、镜像的创建 &#xff08;一&#xff09;基于现有镜像创建 1.启动一个镜像&#xff0c;在容器里做修改 2.将修改后的容器提交为新的镜像 &#xff08;二&#xff09;基于本地模板创建 &#xff08;三&#xff09;基于Dockerfile 创建 1.联合文件系统&#xff08…...

布尔逻辑与逻辑门

计算机为什么使用二进制&#xff1a; 计算机的元器件晶体管只有 2 种状态&#xff0c;通电&#xff08;1&#xff09;& 断电&#xff08;0&#xff09;&#xff0c;用二进制可直接根据元器件的状态来设计计算机。而且&#xff0c;数学中的“布尔代数”分支&#xff0c;可以…...

opencv-python计算视频光流

光流基本概念 光流表示的是相邻两帧图像中每个像素的运动速度和运动方向。具体&#xff1a;光流是空间运动物体在观察成像平面上的像素运动的瞬时速度&#xff0c;是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系&#xf…...

Spring 中获取 Bean 对象的三种方式

目录 1、根据名称获取Bean 2、根据Bean类型获取Bean 3、根据 Bean 名称 Bean 类型来获取 Bean&#xff08;好的解决方法&#xff09; 假设 Bean 对象是 User&#xff0c;并存储到 Spring 中&#xff0c;注册到 xml 文件中 public class User {public String sayHi(){retur…...

centos系统安装Ward服务器监控工具

简介 Ward是一个简约美观多系统支持的服务器监控面板 安装 1.首先安装jdk yum install java-1.8.0-openjdk-devel.x86_64 2.下载jar wget 3.启动 java -jar ward-1.8.8.jar 体验 浏览器输入 http://192.168.168.110:4000/ 设置服务名设置为:myserver 端口号:5000 点击…...

计算机网络-数据交换方式(电路交换 报文交换 分组交换及其两种方式 )

文章目录 为什么要数据交换&#xff1f;总览电路交换电路交换的各个阶段建立连接数据传输释放连接 电路交换的特点电路交换的优缺点 报文交换报文交换流程报文交换的优缺点 分组交换分组交换流程分组交换的优缺点 数据交换方式的选择分组交换的两种方式数据报方式数据报方式的特…...

【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]

阅读导航 引言一、设计模式概念&#xff08;了解&#xff09;二、单例模式1. 饿汉模式&#xff08;1&#xff09;概念&#xff08;2&#xff09;模拟实现&#xff08;3&#xff09;优缺点&#xff08;4&#xff09;适用场景 2. 懒汉模式&#xff08;1&#xff09;概念&#xff…...

【创建vue项目的两种方式】

Vue环境搭建 NodeJs安装包安装淘宝镜像 环境搭建webpack安装全局安装vue/cli查看模板创建项目1.webpack2. vue-cli NodeJs安装包 下载链接&#xff1a;官网链接 下载下来后&#xff0c;直接傻瓜式的安装即可。 通过在cmd控制台输入以下命令查看是否安装成功 node -v因为适配某…...

2. HarmonyOS应用开发DevEcoStudio准备-1

2. HarmonyOS应用开发DevEcoStudio准备-1 下载 DevEco Studio 进入HUAWEI DevEco Studio产品页产品页。 单击下载列表右侧的按钮&#xff0c;下载 DevEco Studio。 安装 DevEco Studio 下载完成后&#xff0c;双击下载的 deveco-studio-xxxx.exe&#xff0c;进入 DevEco St…...

《二叉树》——3(层序遍历)

目录 前言&#xff1a; 层序遍历: 解析&#xff1a; 前言&#xff1a; 本文主讲链式二叉树的层序遍历&#xff0c;在前面的张篇blog我们初步实现了链式二叉树递归部分的内容&#xff0c;对于递归算法的学习和思维方式我们仍然需要不断加强&#xff0c;所以将对链式二叉树进行…...

HarmonyOS应用开发者基础认证考试答案

HarmonyOS应用开发者基础认证考试答案 一、判断题 1.Ability是系统调度应用的最小单元&#xff0c;是能够完成一个独立功能的组件。一个应用可以包含一个或多个Ability。 正确(True) 2.所有使用Component修饰的自定义组件都支持onPageShow&#xff0c;onBackPress和onPageHide…...

【前端素材】bootstrap3 实现地产置业公司source网页设计

一、需求分析 地产置业公司的网页通常是该公司的官方网站&#xff0c;旨在向访问者提供相关信息和服务。这些网页通常具有以下功能&#xff1a; 公司介绍&#xff1a;网页通常包含有关公司背景、历史、核心价值观和使命等方面的信息。此部分帮助访问者了解公司的身份和目标。 …...

C++ 数论相关题目 博弈论 Nim游戏

给定 n 堆石子&#xff0c;两位玩家轮流操作&#xff0c;每次操作可以从任意一堆石子中拿走任意数量的石子&#xff08;可以拿完&#xff0c;但不能不拿&#xff09;&#xff0c;最后无法进行操作的人视为失败。 问如果两人都采用最优策略&#xff0c;先手是否必胜。 输入格式…...

机器学习---无偏估计

1. 如何理解无偏估计 无偏估计&#xff1a;就是我认为所有样本出现的概率⼀样。 假如有N种样本我们认为所有样本出现概率都是 1/N。然后根据这个来计算数学期望。此时的数学期望就是我们平常讲 的平均值。数学期望本质就 是平均值。 2. 无偏估计为何叫做“无偏”&#xff1…...

C语言基础13

今天是学习嵌入式相关内容的第十四天&#xff0c;以下是今日所学内容 1.结构体: 1.结构体类型定义 2.结构体变量的定义 3.结构体元素的访问 4.结构体的存储 内存对齐 结构体整体的大小必须为最大基本类型长度的整数倍 5.结构体作为函数参数 值传递 练习:定…...

【Java】Maven配置加载到全局

Maven配置加载到全局 <build><plugins><plugin><artifactId>maven-resources-plugin</artifactId><configuration><encoding>utf-8</encoding><useDefaultDelimiters>true</useDefaultDelimiters></configura…...

右手螺旋线定则

通电螺线管中的安培定则&#xff08;安培定则二&#xff09;&#xff1a;用右手握住通电螺线管&#xff0c;让四指指向电流的方向&#xff0c;那么大拇指所指的那一端是通电螺线管的N极。...

2024 高级前端面试题之 React 「精选篇」

该内容主要整理关于 React 模块的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 React模块精选篇 1. 如何理解React State不可变性的原则2. JSX本质3. React合成事件机制4. setState和batchUpdate机制5. 组件渲染和更新过程6. Diff算法相…...

OSPF协议解析及相关技术探索(C/C++代码实现)

OSPF&#xff08;开放最短路径优先&#xff09;是一种用于自治系统&#xff08;AS&#xff09;内部的路由协议&#xff0c;它是基于链路状态算法的。OSPF的设计目的是为了提供一种可扩展、快速收敛和高效的路由解决方案。 OSPF概念和特点 概念 自治系统&#xff08;AS&#…...

如何恢复已删除的照片?

在这篇综合文章中发现恢复丢失照片的有效且免费的方法。无论您使用的是智能手机、iPhone、Windows 计算机、Mac、SD 卡还是数码相机&#xff0c;我们都提供有关如何恢复已删除照片的分步说明。此外&#xff0c;学习一些有价值的技巧&#xff0c;以防止将来意外删除照片。 意外…...

VMware虚拟机安装macOS

VMware虚拟机安装macOS 文章目录 VMware虚拟机安装macOS先看效果一、准备工作①&#xff1a;镜像资源下载②&#xff1a;虚拟机③&#xff1a;安装macOS所必要的插件 二、开始安装①&#xff1a;创建新的虚拟机②&#xff1a;自定义硬件③&#xff1a;开启虚拟机 先看效果 一、…...

API管理协作工具:Apipost

相信无论是前端&#xff0c;还是后端的测试和开发人员&#xff0c;都遇到过这样的困难。不同工具之间数据一致性非常困难、低效。多个系统之间数据不一致&#xff0c;导致协作低效、频繁出问题&#xff0c;开发测试人员痛苦不堪。 API管理的难点在哪&#xff1f; 开发人员在 …...

GPT-SoVITS 本地搭建踩坑

GPT-SoVITS 本地搭建踩坑 前言搭建下载解压VSCode打开安装依赖包修改内容1.重新安装版本2.修改文件内容 运行总结 前言 传言GPT-SoVITS作为当前与BertVits2.3并列的TTS大模型&#xff0c;于是本地搭了一个&#xff0c;简单说一下坑。 搭建 下载 到GitHub点击此处下载 http…...

【教学类-34-02】20240130纸尺2.0 (A4横版5条,刻度25*5=125CM,有图案)

作品展示&#xff1a; 背景需求&#xff1a; 设计了纸尺的基本模板 【教学类-34-01】20240130纸尺1.0 &#xff08;A4横版5条&#xff0c;刻度25*5125CM&#xff09;-CSDN博客文章浏览阅读194次&#xff0c;点赞5次&#xff0c;收藏5次。【教学类-34-01】20240130纸尺1.0 &am…...

iText操作pdf

最近有个任务是动态的创建pdf根据获取到的内容&#xff0c;百度到的知识点都比较零散&#xff0c;官方文档想必大家也不容易看懂。下文是我做出的汇总 public class CreatePdfUtils {public static void create(){//准备File file new File("C:\\code\\base-project-back…...

关于SQLite 的下载与使用。配合python

win系统下&#xff1a; SQLite Download Page Precompiled Binaries for Windows sqlite-tools-win-x64-3450000.zip (4.77 MiB) 解压后&#xff0c;找个位置。然后设置环境变量指定位置。 可以手动建立.db文件。 也可以通过代码建立&#xff1a; 如下代码就是建立一个db文件。…...

java面向对象基础(面试)

一、面向对象基础 1. 面向对象和面向过程的区别 面向过程把解决问题的过程拆成一个个方法&#xff0c;通过一个个方法的执行解决问题。面向对象会先抽象出对象&#xff0c;然后用对象执行方法的方式解决问题。 2.创建一个对象用什么运算符?对象实体与对象引用有何不同? n…...

【C++修行之道】STL(初识list、stack)

目录 一、list 1.1list的定义和结构 以下是一个示例&#xff0c;展示如何使用list容器: 1.2list的常用函数 1.3list代码示例 二、stack 2.1stack的定义和结构 stack的常用定义 2.2常用函数 2.3stack代码示例 一、list 1.1list的定义和结构 list的使用频率不高&#…...

【环境配置】安装了pytorch但是报错torch.cuda.is_availabel()=Flase

解决思路&#xff1a;import torch正常&#xff0c;说明torch包安装正常&#xff0c;但是不能和gpu正常互动&#xff0c;猜测还是pytroch和cuda的配合问题 1.查看torch包所需的cuda版本 我的torch是2.0.1&#xff0c;在现在是比较新的包&#xff0c;需要12以上的cuda支持&…...