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);  // 更新显示}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/442763.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【轮式平衡机器人】——TMS320F28069片内外设之ADC

一、ADC概述 这一部分不是我们的重点&#xff0c;原理分类啥的这里简要说明&#xff01; 步骤&#xff1a;采样、保持、量化、编码 将采样电平&#xff08;模拟值&#xff09;转换为数字值的方法&#xff1a;直接比较型&#xff08;并行ADC、逐次逼近型ADC&#xff09;&…

常用抓包软件集合(Fiddler、Charles)

1. Fiddler 介绍&#xff1a;Fiddler是一个免费的HTTP和HTTPS调试工具&#xff0c;支持Windows平台。它可以捕获HTTP和HTTPS流量&#xff0c;并提供了丰富的调试和分析功能。优点&#xff1a;易于安装、易于使用、支持多种扩展、可以提高开发效率。缺点&#xff1a;只支持Wind…

小白水平理解面试经典题目Leetcode 412. Fizz Buzz【Java实现】

412 FizzBuzz 小白渣翻译&#xff1a; 给定一个整数 n &#xff0c;返回一个字符串数组 answer &#xff08;从 1 开始索引&#xff09;&#xff0c;其中&#xff1a; answer[i] “FizzBuzz” 如果 i 能被 3 和 5 整除。answer[i] “Fizz” 如果 i 能被 3 整除。answer[i]…

安泰高压放大器电路设计方案是什么

高压放大器是电子设备中常用的一种放大器类型&#xff0c;用于将低电压信号放大到高电压输出。本文将介绍高压放大器电路设计的基本原理和方案&#xff0c;涵盖关键设计考虑因素以及常用的电路拓扑结构。 一、设计考虑因素 放大倍数&#xff1a;高压放大器的设计首要考虑因素是…

互联网创业这么热,为何个人站长消失了?

有没有发现&#xff0c;这几年互联网创业的人突然冒出来很多&#xff0c;正是互联网创业热的时候&#xff0c;有一批人却在这个时代消失不见了。不错&#xff0c;就是站长&#xff0c;这到底是为什么呢&#xff1f;是站长转型不力&#xff0c;还是时代的必然呢&#xff1f;甚至…

cad设计绘图工具:AutoCAD 2024 for Mac中文激活版

AutoCAD 2024 for Mac是一款专业的CAD设计绘图工具&#xff0c;适用于各种类型的建筑、机械、电子和图形设计项目。 软件下载&#xff1a;AutoCAD 2024 for Mac中文激活版下载 以下是该软件的一些主要功能和特点&#xff1a; 强大的绘图和编辑工具&#xff1a;AutoCAD提供了丰富…

sketchup草图大师模型网怎么样?

SketchUp草图大师模型网是一个提供SketchUp模型下载和分享的平台&#xff0c;如建e网等&#xff0c;用户可以在上面找到大量的SU模型&#xff0c;并学习一些SketchUp的使用技巧。该网站模型种类丰富&#xff0c;涵盖了建筑、景观、室内等不同领域&#xff0c;同时也有一些教程&…

Linux——安装MySQL

1、安装mysql8.0.35 1.1、安装步骤 1.更新包列表&#xff0c;首先&#xff0c;确保您的系统已更新到最新状态。运行以下命令来更新包列表和安装最新的软件包&#xff1a; sudo apt update sudo apt upgrade2.安装MySQL服务器&#xff1a;运行以下命令来安装MySQL服务器&…

RISC-V指令格式

RISC-V指令格式 1 RISC-V指令集命名规范2 RISC-V指令集组成2.1 基础整数指令集2.2 扩展指令集 3 RISC-V指令格式3.1 指令表述3.2 指令格式 本文属于《 RISC-V指令集基础系列教程》之一&#xff0c;欢迎查看其它文章。 1 RISC-V指令集命名规范 前面提到过RV32I&#xff0c;这是…

ONLYOFFICE | 免费开源办公神器新选择

目录 前言&#xff1a; 1、什么是ONLYOFFICE&#xff1f; 2、ONLYOFFICE下载使用 3、ONLYOFFICE团队协作云办公功能 4、ONLYOFFICE 8.0新版本的亮点功能 4.1、显示协作者头像 4.2、插件 UI 界面更新 4.3、可填写的 PDF 表单 5、最后 前言&#xff1a; 一个好的开发工具…

【伪类·HTML】

伪类 在 CSS 中&#xff0c;伪类是添加到选择器的关键字&#xff0c;给指定元素设置一些特殊状态&#xff0c;以 : 开头。 链接有以下四个状态。这四种状态也称之为超链接的伪类。 对于超链接的伪类&#xff0c;推荐的使用顺序是&#xff1a; :link - :visited - :hover - :a…

【极数系列】Flink集成DataSource读取Socket请求数据(09)

文章目录 01 引言02 简介概述03 基于socket套接字读取数据3.1 从套接字读取。元素可以由分隔符分隔。3.2 windows安装netcat工具&#xff08;1&#xff09;下载netcat工具&#xff08;2&#xff09;安装部署&#xff08;3&#xff09;启动socket端口监听 04 源码实战demo4.1 po…