为学习嵌入式做准备,重新拿起51单片机学习。此贴为学习笔记,仅记录易忘点,实用理论基础,并不是0基础。
资料参考:清翔零基础教你学51单片机

51单片机学习笔记

  • 1. C语言中的易忘点
    • 1.1 数据类型
    • 1.2 位运算符
    • 1.3 常用控制语句
    • 1.4 C51程序的基本结构
  • 2.电子电路基础
    • 2.1 电平
    • 2.2 I/O(引脚)
      • 2.2.1 P3口的第二用途
    • 2.3 电子元器件
      • 2.3.1 电阻:
      • 2.3.2 电容:
      • 2.3.3 蜂鸣器
        • 2.3.3.1 判断有源蜂鸣器和无源蜂鸣器
        • 2.3.3.2 驱动蜂鸣器
      • 2.3.4 常见符号
  • 3.单片机 基础知识点
    • 3.1 单片机最小系统
    • 3.2 基本时序
  • 4. 51单片机基础例程(I/O外设)
    • 4.1 点亮LED灯
      • 4.1.1编程知识点
        • 4.1.1.1 位定义
      • 4.1.2 编程
    • 4.2 LED闪烁
      • 4.2.1 编程知识点
        • 4.2.1.1 变量作用域
        • 4.2.1.2 软件延时
      • 4.2.2 编程
    • 4.3 流水灯
      • 4.3.1 编程知识点
        • 4.3.1.1宏定义
        • 4.3.1.2 函数的定义
          • 4.3.1.3 延时函数
        • 4.3.1.4 循环移位函数
          • 4.3.1.4.1 循环移位函数与左移和右移运算符的区别
      • 4.3.2 编程
    • 4.4 数码管静、动态显示
      • 4.4.1 单个数码管--==静态==显示原理
      • 4.4.2 74HC573锁存器工作原理
      • 4.4.3 多个数码管--==动态==显示原理
      • 4.4.4 编程知识点
        • 4.4.4.1 数组的定义与引用
      • 4.4.5 编程
        • 4.4.5.1 共阴极数码管,静态显示(只亮一个数码管)
        • 4.4.5.2 共阴极数码管,动态显示
    • 4.5 非编码键盘
      • 4.5.1 独立键盘
      • 4.5.2 矩阵键盘
        • 1.硬件接线
        • 2.扫描
      • 4.5.3 编程知识点
        • 4.5.3.1程序去抖
        • 4.5.3.2 开关语句
      • 4.5.4 编程
        • 4.5.4.1 独立键盘
        • 4.5.4.2 矩阵键盘

1. C语言中的易忘点

1.1 数据类型

在这里插入图片描述

1.2 位运算符

~  按位取反
<< 左移
>> 右移
& 按位与
^ 按位异或
| 按位或

异或:相同取0,不同取1.
在这里插入图片描述

1.3 常用控制语句

条件 if
循环while 、 for
开关switch

1.4 C51程序的基本结构

#include <reg52.h> 		//包含51单片机头文件void main()		//主函数
{}

C语言设置的程序中只允许有一个main函数。程序总是从main函数开始运行的,main函数是void型(无返回值)。

2.电子电路基础

2.1 电平

数字电路中只有两种电平:高电平和低电平。
高电平:5V
低电平:0V

TTL电平规定高电平输出电压>2.4V,低电平输出电压<0.4V	

计算机串口使用的是RS232电平
高电平:-12V
低电平:+12V
Tips:单片机与计算机串口通信时需要使用电平转换芯片,把RS232电平转为TTL电平后单片机才能识别。

2.2 I/O(引脚)

在这里插入图片描述
例程中
P0接LED,P2^3接蜂鸣器。

2.2.1 P3口的第二用途

在这里插入图片描述

2.3 电子元器件

2.3.1 电阻:

常用的贴片电阻封装:0402、0603、0805、1206、1210
贴片电阻读数参考:贴片电阻上的字符是如何表示电阻的?

103,那么10是有效数字,3表示10的3次方,所以103表示的阻值就是10x10^{3}
1502,150是有效数字,2表示10的2次方,所以,1502表示的阻值就是150*10^{2}
5R6=5.6Ω、R16=0.16Ω
01C就是10k

2.3.2 电容:

电容的作用:储能,滤波,通交流隔直流,旁路,耦合,补偿,充放电等

1F(法拉)	 = 1000000μF(微法)
1μF(微法)= 1000nF(纳法)
1nF(纳法) = 1000pF(皮法)

2.3.3 蜂鸣器

2.3.3.1 判断有源蜂鸣器和无源蜂鸣器

可以用万用表电阻档Rxl档测试:用黑表笔接蜂鸣器 "+"引脚,红表笔在另一引脚上来回碰触,如果触发出咔、咔声的且电阻只有8Ω(或16Ω)的是无源蜂鸣器;如果能发出持续声音的,且电阻在几百欧以上的,是有源蜂鸣器。

2.3.3.2 驱动蜂鸣器

由于蜂鸣器的工作电流一般比较大,以致于单片机的I/O 口是无法直接驱动的,所以要利用放大电路来驱动,一般使用三极管来放大电流就可以了。
(除此之外还有一些其他驱动方式:PWM 输出口直接驱、I/O 口定时翻转电平驱动蜂鸣器方式)
在这里插入图片描述

2.3.4 常见符号

在这里插入图片描述

3.单片机 基础知识点

3.1 单片机最小系统

电源 (给整个系统提供能量)
单片机芯片 (运行程序/处理数据)
晶振电路 (给单片机工作提供节拍)
复位电路 (单片机上电时需要复位使程序从头开始运行)
在这里插入图片描述

3.2 基本时序

振荡周期: 也称时钟周期, 是指为单片机提供时钟脉冲信号的振荡源的周期。

机器周期: 一个机器周期包含 12 个时钟周期。 在一个机器周期内, CPU可以完成一个独立的操作。

例如计算外部晶振频率为11.0592Mhz的单片机一个机器周期所需的时间:
1/11.0592 * 12 ≈ 1.085μS
说明:“1/(11.0592*1000000)”乘以106把Mhz转为hz再乘以“12”是12个时钟周期等于一个机器周期最终值为秒,把这个单位为秒的值乘以106所得值约等于1.085微秒。

4. 51单片机基础例程(I/O外设)

例程中LED位共阳极!
点亮开发板上LED灯只需要控制P1口输出低电平即可
(编程时给P1口赋值“0”)
在这里插入图片描述

4.1 点亮LED灯

普通发光二极管工作压降为:1.6v ~ 2.1 V。
工作电流为:1~20mA
注意:二极管需要上拉电阻。
否则电流=(5V-2.1V)/0Ω,电流无限大
有电阻后,电流=(5V-2.1V)/1kΩ,约等于3mA.
在这里插入图片描述

4.1.1编程知识点

4.1.1.1 位定义

关键字:sbit
功能:位定义
一般格式: sbit 标识符 = 地址值;

例如:sbit LED1 = P1^0;
注意:地址值中P1的“P”必须为大写的P

4.1.2 编程

#include <reg52.h> //引用51头文件sbit LED1 = P1^0; //位定义void main()	//主函数
{LED1 = 0;//点亮P1.0上的LED		
}

4.2 LED闪烁

4.2.1 编程知识点

4.2.1.1 变量作用域
全局变量:在函数体外定义的变量通常为全局变量,作用范围:从定义开始的整个程序局部变量:在函数体内定义的变量通常为局部变量,作用范围:函数体内
4.2.1.2 软件延时

软件延时例如:

unsigned int i;
i=65535;
while(i);

4.2.2 编程

实现:P1口上所有LED闪烁

#include <reg52.h>//包含51头文件unsigned int i;//0~65535void main()//main函数自身会循环
{while(1)//大循环{P1 = 0;	//点亮P1口8个LEDi = 65535;while(i--);//软件延时P1 = 0xff;//1111 1111 熄灭P1口8个LEDi = 65535;while(i--);//软件延时	}	
}   

按位取反 闪烁写法:

#include <reg52.h>unsigned int i;//0~65535void main()//main函数自身会循环
{P1 = 0xff;//熄灭8位LEDwhile(1) //大循环{P1 = ~P1;	//使用按位取反运算符使LED闪烁i = 65535;while(i--);//软件延时}	
}   

4.3 流水灯

4.3.1 编程知识点

4.3.1.1宏定义

理解成 用define/ typedef 取小名

#define uchar unsigned char
注意宏定义后面不能加分号,它是预处理指令不是语句。

其中用“uchar”直接替换了unsigned char
此时我们可以用uchar去定义变量类型如:uchar i;等价于unsigned char i;

【C语言】typedef与define的区别

typedef,我们可以为基本类型(如int、float)或自定义的结构体、联合体等定义新的名称。define,定义常量、函数替换宏、条件编译等,它的作用范围更为广泛。所有满足条件的宏定义在预处理阶段都会被替换为指定的文本。
4.3.1.2 函数的定义

自定义函数一般格式为:

函数类型 函数名 (形式参数表)
{局部变量定义函数体语句
}
4.3.1.3 延时函数

自定义函数:延时函数delay(毫秒级)

void delay(unsigned int z)
{unsigned int x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
}

给形参z赋值,如延时100毫秒:delay(100);

4.3.1.4 循环移位函数
标准库函数: intrins.h

内部函数:

字符型循环左移:_crol_
字符型循环右移:_cror_
#include <intrins.h>
void test_crol (void) {unsigned char a;unsigned char b;a = 0xFE;      //1111 1110b = _crol_(a,1); // b now is 0xFD  二进制为1111 1101
}
4.3.1.4.1 循环移位函数与左移和右移运算符的区别

循环左移是把最高位移到最低位上,
左移运算符是把最高位移除最低位补0

4.3.2 编程

实现:流水灯一直左循环

#include <reg52.h>	 //包含51头文件
#include <intrins.h> //包含移位标准库函数头文件#define uint unsigned int
#define uchar unsigned charuchar temp;//LED灯相关变量
/*====================================
函数	: delay(uint z)
参数	:z 延时毫秒设定,取值范围0-65535
返回值	:无
描述	:12T/Fosc11.0592M毫秒级延时
====================================*/
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--); 		
} void main()//main函数自身会循环
{temp = 0xfe;P1 = temp; //1111 1110  初值LED1亮delay(100);//毫秒级延时 100毫秒while(1){temp = _crol_(temp, 1);//循环左移P1 = temp;//移位完成后赋值给P1 每个一个灯点亮delay(100);//毫秒级延时 100毫秒}	
}  

4.4 数码管静、动态显示

4.4.1 单个数码管–静态显示原理

有共阳、共阴极,例程使用共阴!即b图左边。
在这里插入图片描述
共阴极数码码表:

0x3F,  //"0"
0x06,  //"1"
0x5B,  //"2"
0x4F,  //"3"
0x66,  //"4"
0x6D,  //"5"
0x7D,  //"6"
0x07,  //"7"
0x7F,  //"8"
0x6F,  //"9"
0x77,  //"A"
0x7C,  //"B"
0x39,  //"C"
0x5E,  //"D"
0x79,  //"E"
0x71,  //"F"
0x76,  //"H"
0x38,  //"L"
0x40,  //"-"
0x00,  //熄灭

4.4.2 74HC573锁存器工作原理

锁存器作用:可以把数据输入端与输出端进行隔离或连接
左边D为输入,右边Q为输出
在这里插入图片描述
在这里插入图片描述
输出口Q要想输出高低电平OE脚必须接GND。
LE脚为时,输出端Q随输入端D的数据而变化。
LE脚为时,输出端Q数据保持不变,输入端D数据变化不会改变Q的数据。
在这里插入图片描述

4.4.3 多个数码管–动态显示原理

段选和位选

位选:选择哪一个数码管亮
段选:该数码管怎么亮(数码管里的二极管怎么亮)

工作流:
打开位选锁存器->指定某个数码管->关闭位选锁存器,
打开段选锁存器->指定亮什么数字->关闭段选锁存器,
因为扫描周期短,所以肉眼可以看到多数码管同时亮 不同的数字。

4.4.4 编程知识点

4.4.4.1 数组的定义与引用

数组是一组有序数据的集合,数组中每一个数据都是同一数据类型。数组中的元素可以用数组名和下标来唯一确定。

数组的一般格式定义如下:

数据类型 数组名[常量表达式] = {元素表};

例如:

unsigned char tabel[3] ={0x3F, 0x06, 0x5B, };
P0 = tabel[0]; //P0此时的值为0x3F

4.4.5 编程

4.4.5.1 共阴极数码管,静态显示(只亮一个数码管)
#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管位选////毫秒级延时函数定义
//void delay(uint z)
//{
//	uint x,y;
//	for(x = z; x > 0; x--)
//		for(y = 114; y > 0 ; y--); 		
//} void main()//main函数自身会循环
{WE = 1;//打开位选锁存器P0 = 0XFE; //1111 1110 选通第一位数码管WE = 0;//锁存位选数据DU = 1;//打开段选锁存器P0 = 0X06;//0000 0110 显示“1”DU = 0;//锁存段选数据while(1){}	
}  
4.4.5.2 共阴极数码管,动态显示
#include <reg52.h>//包含51头文件
#include <intrins.h>//包含移位标准库函数头文件#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选//共阴数码管段选表0-9
uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};/*====================================
函数	: delay(uint z)
参数	:z 延时毫秒设定,取值范围0-65535
返回值	:无
描述	:12T/Fosc11.0592M毫秒级延时
====================================*/
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--); 		
} /*====================================
函数	:display(uchar i)
参数	:i 显示数值,取值范围0-255
返回值	:无
描述	:三位共阴数码管动态显示
====================================*/
void display(uchar i)
{uchar bai, shi, ge;bai = i / 100; //236 / 100  = 2shi = i % 100 / 10;	//236 % 100 / 10 = 3ge  = i % 10;//236 % 10 =6//第一位数码管  		P0 = 0XFF;//清除断码WE = 1;//打开位选锁存器P0 = 0XFE; //1111 1110WE = 0;//锁存位选数据DU = 1;//打开段选锁存器P0 = tabel[bai];//DU = 0;//锁存段选数据delay(5);//第二位数码管P0 = 0XFF;//清除断码WE = 1;//打开位选锁存器P0 = 0XFD; //1111 1101WE = 0;//锁存位选数据DU = 1;//打开段选锁存器P0 = tabel[shi];//DU = 0;//锁存段选数据delay(5);//第三位数码管P0 = 0XFF;//清除断码WE = 1;//打开位选锁存器P0 = 0XFB; //1111 1011WE = 0;//锁存位选数据DU = 1;//打开段选锁存器P0 = tabel[ge];//DU = 0;//锁存段选数据delay(5);
}void main()//main函数自身会循环
{	while(1){display(236); //数码管显示函数}	
}  

4.5 非编码键盘

4.5.1 独立键盘

每个按键占用一个IO口,当按键数量较多时,IO口利用效率不高,
但程序简单,适用于所需按键较少的场合。

在这里插入图片描述
在这里插入图片描述
按键一端与IO口连接,另外一端接地。I/O进行检测,
按键按下会被检测到电平,未按下被检测为电平。

4.5.2 矩阵键盘

电路连接复杂,但提高了IO口利用率,软件编程较复杂。
适用于使用大量按键的场合。

在这里插入图片描述
上图为4行和4列,一共16个按键组成。

确定矩阵键盘上哪一个按键被按下可以采用列扫描和行扫描。
列扫描时先把接在列上面的所有IO口拉高,接在行上的所有IO置低。
当其中有一列内任何一个按键按下那么整条列线都会被拉低。
1.硬件接线
P3口的高4位(P3.4~P3.7)作为列线(输出)
P3口的低4位(P3.0~P3.3)作为行线(输入)
uchar cord_l,cord_h;//声明列线和行线的值的储存变量P3 = 0xf0;//1111 0000
2.扫描

扫描分为两步:列扫描和行扫描,通过检测电平变化确定按键位置。
step1–列判断:行线(P3.0 ~ P3.7)为0,列线(P3.4 ~ P3.7)为1,即P3=0xf0。
当四列中,某一列被按下,列线的对应的值就会改变。

  cord_l = P3 & 0xf0;// 只储存列线值 (f0的0作用:无论行线是多少,都不保存,写0)			
例:2行2列的S11按下,读到L=0xd0(图中从下P37往上P30,1101 0000)

step2–行判断:在列判断后,保留读到的列线值,行线值写1。即用读到的列线值 或 0x0f。

例:0xd0|0x0f (1101 0000|00001111)得到1101 1111,
2行2列的S11按下,导致P31的1变为0,即变为1101 1101 (0xdd)
0xdd&0x0f=0x0d,此为行线值
  P3 = cord_l | 0x0f;cord_h = P3 & 0x0f;// 只储存行线值(0f的0作用:无论列线是多少,都不保存,写0)

在这里插入图片描述
step3:
列线值+行线值

return (cord_l + cord_h);//返回键值码

4.5.3 编程知识点

4.5.3.1程序去抖

在这里插入图片描述

if(key_s3 == 0)//判断S3是否被按下{delay(20);//按键消抖if(key_s3 == 0){...while(!key_s3);//松手检测}	}
4.5.3.2 开关语句
switch (表达式)
{case 常量表达式1: 语句1breakcase 常量表达式2: 语句2break}

4.5.4 编程

4.5.4.1 独立键盘

实现:按下开发板左下角S2按键数码管值+1,最大到9按下S3按下,值减一,最小减到0

#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管位选
sbit key_s2 = P3^0;//独立按键S2
sbit key_s3 = P3^1;//独立按键S3
uchar num;//数码管显示的值//共阴数码管段选表0-9
uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};//毫秒级延时函数定义
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--); 		
} void main()//main函数自身会循环
{	num = 0; WE = 1;//打开位选锁存器P0 = 0XFE; //1111 1110WE = 0;//锁存位选数据while(1){if(key_s2 == 0)//判断S2是否被按下{delay(20);//按键消抖if(key_s2 == 0){if(num != 9)//如果值不等于9则+1,功能把值限定为小于9num++;while(!key_s2);//松手检测}	}if(key_s3 == 0)//判断S3是否被按下{delay(20);//按键消抖if(key_s3 == 0){if(num > 0)	//如果大于0则执行减一num--;while(!key_s3);//松手检测}	}//松手之后刷新显示DU = 1;//打开段选锁存器P0 = tabel[num];//DU = 0;//锁存段选数据}	
}  
4.5.4.2 矩阵键盘

实现:矩阵键盘

#include <reg52.h>
#define uchar unsigned char
#define uint  unsigned int
sbit we = P2^7;
sbit du = P2^6;
uchar code leddata[]={ 0x3F,  //"0"0x06,  //"1"0x5B,  //"2"0x4F,  //"3"0x66,  //"4"0x6D,  //"5"0x7D,  //"6"0x07,  //"7"0x7F,  //"8"0x6F,  //"9"0x77,  //"A"0x7C,  //"B"0x39,  //"C"0x5E,  //"D"0x79,  //"E"0x71,  //"F"0x76,  //"H"0x38,  //"L"0x37,  //"n"0x3E,  //"u"0x73,  //"P"0x5C,  //"o"0x40,  //"-"0x00,  //熄灭0x00  //自定义};
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
}uchar KeyScan()	//带返回值的子函数
{uchar cord_l,cord_h;//声明列线和行线的值的储存变量P3 = 0xf0;//1111 0000if( (P3 & 0xf0) != 0xf0)//判断是否有按键按下{delay(5);//软件消抖if( (P3 & 0xf0) != 0xf0)//判断是否有按键按下{cord_l = P3 & 0xf0;// 储存列线值P3 = cord_l | 0x0f;cord_h = P3 & 0x0f;// 储存行线值while( (P3 & 0x0f) != 0x0f );//松手检测return (cord_l + cord_h);//返回键值码}	}}void KeyPro()
{switch( KeyScan() ){//第一行键值码case 0xee: P0 = leddata[0];		break;case 0xde: P0 = leddata[1];		break;case 0xbe: P0 = leddata[2];		break;case 0x7e: P0 = leddata[3];		break;//第二行键值码case 0xed: P0 = leddata[4];		break;case 0xdd: P0 = leddata[5];		break;case 0xbd: P0 = leddata[6];		break;case 0x7d: P0 = leddata[7];		break;//第三行键值码case 0xeb: P0 = leddata[8];		break;case 0xdb: P0 = leddata[9];		break;case 0xbb: P0 = leddata[10];	break;case 0x7b: P0 = leddata[11];	break;//第四行键值码case 0xe7: P0 = leddata[12];	break;case 0xd7: P0 = leddata[13];	break;case 0xb7: P0 = leddata[14];	break;case 0x77: P0 = leddata[15];	break;}	
}void main()
{we = 1;//打开位选P0 = 0;//八位数码管全显示we = 0;//锁存位选du = 1;//打开段选端P0 = leddata[22];while(1){KeyPro();//提取键值码并且送不同数值给数码管显示}
}

实现:按下矩阵键盘和独立键盘任意键,数码管显示相应数值初始显示“-”横

#include <reg52.h>//包含51头文件
#include <intrins.h>//包含移位标准库函数头文件#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
uchar num;//数码管显示的值
uchar KeyValue = 20;//按键值 显示-//共阴数码管段选表
uchar  code tabel[]= {
//0		1	 2     3     4     5     6     7     8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9     A     B	   C	 D	   E	 F		H	 L	 
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x76, 0x38,
//n	   u	  -	  熄灭
0x37, 0x3E, 0x40, 0x00 };/*====================================
函数	: delay(uint z)
参数	:z 延时毫秒设定,取值范围0-65535
返回值	:无
描述	:12T/Fosc11.0592M毫秒级延时
====================================*/
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--); 		
} 
/*====================================
函数	:KeyScan()
参数	:无
返回值	:无
描述	:4*4矩阵键盘与独立键盘扫描
按键按下KeyValue全局变量值发生相应变化
====================================*/
void KeyScan()
{//4*4矩阵键盘扫描P3 = 0XF0;//列扫描if(P3 != 0XF0)//判断按键是否被按下{delay(10);//软件消抖10msif(P3 != 0XF0)//判断按键是否被按下{switch(P3) //判断那一列被按下{case 0xe0:	KeyValue = 0;	break;//第一列被按下case 0xd0:	KeyValue = 1;	break;//第二列被按下case 0xb0:	KeyValue = 2;	break;//第三列被按下case 0x70:	KeyValue = 3;	break;//第四列被按下 }P3 = 0X0F;//行扫描switch(P3) //判断那一行被按下{case 0x0e:	KeyValue = KeyValue;	break;//第一行被按下case 0x0d:	KeyValue = KeyValue + 4;	break;//第二行被按下case 0x0b:	KeyValue = KeyValue + 8;	break;//第三行被按下case 0x07:	KeyValue = KeyValue + 12;	break;//第四行被按下 }while(P3 != 0X0F);//松手检测	}}P3 = 0XFF;//独立按键扫描if(P3 != 0XFF){delay(10);//软件消抖10msif(P3 != 0XFF){switch(P3) //判断那一行被按下{case 0xfe:	KeyValue = 16;	break;//S2被按下case 0xfd:	KeyValue = 17;	break;//S3被按下case 0xfb:	KeyValue = 18;	break;//S4被按下case 0xf7:	KeyValue = 19;	break;//S5被按下 }while(P3 != 0XFF);//松手检测			}	}}void main()//main函数自身会循环
{WE = 1;//打开位选锁存器P0 = 0XFE; //1111 1110WE = 0;//锁存位选数据DU = 1;//打开段选锁存器while(1){KeyScan();//20个按键键盘扫描P0 = tabel[KeyValue];//显示按键值}	
}  

在这里插入图片描述

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

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

相关文章

Arrays.asList() add方法报错java.lang.UnsupportedOperationException

1. 问题说明 记录一下遇到的这个bug&#xff0c;下面是段个简化后的问题重现代码。 public class Test {public static void main(String[] args) {List<Integer> list Arrays.asList(1, 2, 3);list.add(4);} }2. 原因分析 我们看一下Arrays.asList(…) 的源码&#xff…

克罗均线策略思路

一个基于移动平均线的交易策略&#xff0c;主要通过比较不同周期的移动平均线来生成买卖信号。该策略交易逻辑思路和特点&#xff1a;交易逻辑思路1. 多头交易逻辑&#xff1a;- 当当前周期的收盘价高于其4周期移动平均线&#xff0c;并且4周期移动平均线高于9周期移动平均线&a…

Go语言--语法基础7--函数定义与调用--自定义函数

函数是基本的代码块&#xff0c;用于执行一个任务。Go 语言最少有 1 个 main() 函数。你可以通过函数来划分不同功能&#xff0c;逻辑上每个函数执行的是指定的任务。函数声明告诉了编译器函数的名称、返回类型和参数。函数三要素名称 》功能参数 》接口返回值 》结果函数分类内…

Ollama模型库模型下载慢完美解决(全平台)

前言在我们从ollama下载模型时,会发现ollama最开始下载速度很快,能达到10-20MB/s但到了后期,速度就会越来越慢,最终降低到10-20kb/s下载一个模型大多需要1到1.5小时这是因为ollama服务器负荷过大的问题思路如果在下载中终断下载,在用ollama run恢复下载,速度就会又提上去,但3-4…

web:js的模块导出/导入

一般web页面中&#xff0c;html文件通过标签script引用js文件。但是js文件之间的引用要通过import/exprot进行导入/导出&#xff0c;同时还要在html文件中对js文件的引用使用type属性标注。在下面的例子中&#xff0c;html页面<!DOCTYPE html> <html lang"en&quo…

关于Web前端安全防御之安全头配置

一、核心安全头的作用 1. X-Content-Type-Options: nosniff 该响应头用于阻止浏览器对资源的 MIME 类型进行 “嗅探”&#xff08;猜测&#xff09;&#xff0c;强制浏览器严格遵守服务器返回的 Content-Type 头部声明。 风险背景&#xff1a; 浏览器默认会对未明确声明类型…

C++ : 反向迭代器的模拟实现

一、reverse_iterator.h#pragma once namespace txf { //外界传什么类型的iteator&#xff0c;它就用什么iterator 初始化 , list用_list_iterator<T,T&,,T*> ,vector<T> 用T*template<class Iterator,class Ref,class Ptr>//在这个反向迭代器中涉及到…

自动化与配置管理工具 ——SaltStack

一、SaltStack 概述1.1 核心特性SaltStack 是一款开源的自动化运维工具&#xff0c;采用客户端 - 服务器&#xff08;C/S&#xff09;架构&#xff0c;以高效、灵活和可扩展著称。其核心特性包括&#xff1a;高性能架构&#xff1a;基于 ZeroMQ 消息队列&#xff0c;支持大规模…

Rust → WebAssembly 的性能剖析全指南

一、用优化&#xff08;Release&#xff09;构建 ⚡ 务必在做性能测量前使用 优化模式 构建你的 WASM。默认情况下&#xff1a; wasm-pack build → Release 优化wasm-pack build --dev 或 cargo build → Debug&#xff0c;性能大打折扣 优化编译能开启 LLVM 的各项优化和 LT…

第15届蓝桥杯Pthon青少组_国赛_中/高级组_2024年9月7日真题

更多内容请查看网站&#xff1a;【试卷中心 -----> 蓝桥杯----> Python----> 国赛】 网站链接 青少年软件编程历年真题模拟题实时更新 第15届蓝桥杯Pthon青少组_国赛_中/高级组_2024年9月7日真题 一、单选题 第 1 题 单选题 下列运算符中&#xff0c;表示并集的…

【Django】-9- 单元测试和集成测试(上)

一、Django 项目单元 & 集成测试准备 &#x1f447;依赖安装&#xff08;给项目装 “测试小帮手”&#x1f37c;&#xff09;pdm add -d black isort flake8 pytest pytest-django pytest-coverage &#x1f449; 这行命令像在给项目 “采购” 测试工具&#xff1a;black …

VUE-第二季-01

目录 1.Vue程序初体验 1.1 下载并安装vue.js 1.2 第一个Vue程序 1.3 Vue的data配置项 1.4 Vue的template配置项 1.5 Vue实例 和 容器 的关系是&#xff1a;一夫一妻制 2.Vue核心技术 2.0 Vue的模板语法 2.0.1 插值语法 插值语法总结&#xff1a; 2.0.2 指令语法 指…

Android 15 中禁用/启用应用的系统级方法

在 Android 15 的开发中,有时我们需要以系统级权限来控制应用的启用状态。本文将介绍如何使用 PackageManager 来实现应用的禁用和启用功能。 核心方法 在 Android 15 代码中,可以使用以下方法来禁用或启用应用: packageManager.setApplicationEnabledSetting(pkg,Packag…

2025网络工程师技能图谱(附思维导图)

------------比较全面&#xff0c;供学习参考路线图。-----------------------

【ROS2】rclcpp::Node 常用 API

ROS 系列学习教程(总目录) ROS2 系列学习教程(总目录) 目录1. 构造函数2. 节点名称相关3. 获取log对象句柄4. 回调组相关5. Topic发布与订阅6. Service服务端与客户端1. 构造函数 public:Node(const std::string & node_name, const NodeOptions & options NodeOptio…

自动驾驶:技术、应用与未来展望——从开创到全面革新交通出行

一、引言1.1 研究背景与意义在过去的几十年里&#xff0c;随着科技的飞速发展&#xff0c;自动驾驶技术逐渐从科幻小说中的概念走进了现实生活。从最初简单的辅助驾驶功能&#xff0c;到如今高度自动化的自动驾驶系统&#xff0c;这一领域的进步正深刻地改变着我们的出行方式和…

【gradle】插件那些事

文章目录 1. 前言 2. 插件相关介绍 2.1 gradle插件的apply 2.2 引入自定义插件 2.3 常见构建任务 2.4 gradle生命周期 2.5 gradle的惰性属性&可注入的服务 2.6 常见命令 检查依赖树 查看tasks 构建扫描 查看多项目构建的结构 显示所选项目的构建脚本依赖项 指定控制台模式来…

测试平台如何重塑CI/CD流程中的质量协作新范式

测试平台如何重塑CI/CD流程中的质量协作新范式 在DevOps革命席卷全球软件行业的今天&#xff0c;测试的角色正在经历前所未有的转变。传统的"测试最后"模式正在被"测试全程"的新理念所取代&#xff0c;这一转变背后是测试平台与CI/CD流程深度融合带来的质量…

node.js不同环境安装配置

node.js不同环境安装配置 Windows环境安装配置 一、Node.js是什么&#xff1f; ​ Node.js是一个基于Chrome V8引擎的[JavaScript运行环境]。 Node.js使用了一个事件驱动、非阻塞式I/O 的模型&#xff0c;Node.js是一个让JavaScript运行在服务端的开发平台&#xff0c;它让J…

深度学习-读写模型网络文件

模型网络文件是深度学习模型的存储形式&#xff0c;保存了模型的架构、参数等信息。读写模型网络文件是深度学习流程中的关键环节&#xff0c;方便模型的训练、测试、部署与共享。1. 主流框架读写方法&#xff08;一&#xff09;TensorFlow保存模型可以使用 tf.saved_model.sav…