目录
前言
这些笔记是根据江科大的51单片机教学视频自编的,大家可以在观看视频的同时,参考我的笔记并撰写适合自己的笔记。如果发现有错误或不清晰的地方,欢迎大家在评论区一起讨论。希望我们能互相勉励,共同进步,并在这条路上越走越远。
持续更新......
一、单片机及开发板介绍
1.简介
1.单片机,英文Micro Controller Unit,简称MCU
2.内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等系列电脑的常用硬件功能
3.单片机的任务是信息采集 (依靠传感器)、处理(依靠CPU) 和硬件设备(例如电机,LED等) 的控制
4.单片机跟计算机相比,单片机算是一个袖珍版计算机,一个芯片就能构成完整的计算机系统。但在性能上,与计算机相差甚远,但单片机成本低、体积小、结构简单,在生活和工业控制领域大有所用
5.同时,学习使用单片机是了解计算机原理与结构的最佳选择
2.应用领域
单片机的使用领域已十分广泛,如智能仪表、实时工控、通讯设备导航系统、家用电器等。各种产品一旦用上了单片机,就能起到使产品升级换代的功效,常在产品名称前冠以形容词一“智能型”如智能型洗衣机等
3.STC89C52单片机
4.单片机命名规则
STC是公司名
89是系列
C代表工作电压:5.5V~3.8V
52:程序及RAM空间大小:8K字节程序空间及512字节RAM空间
5.相关了解
Vcc代表电源正极,GND代表电源负极
单片机方向:单片机上方有一个缺口,缺口的左边是1号引脚,缺口朝上
6.认识开发板
电子元件,具体来说是一个电位器(Potentiometer)。电位器是一种可调电阻器,它允许通过改变电阻值来调节电路中的电压或电流。这种元件通常用于控制音量、亮度、速度等参数。
7.stc-isp型号
二、LED介绍
1.简介
中文名:发光二极管
英文名:Light Emitting Diode
第一张图,左边是正极,右边是负极
第二张图小的那个部分是正极,大的代表负极
第三张图,引脚长的是正极,短脚是负极
2.数据格式
102=1000,10后面加两个0,10是有效数字,2是倍率,即10*100
eg:473 //47*10^3
1001 //100*10
3.原理图
蓝色的是电阻,用来限流的
VCC是正极
(1)高低电频
高是5V,低是0V
输出高电频不亮,低电频亮
1是高电频,0是低电频
4.寄存器
CPU通过控制寄存器来控制硬件电路,硬件电路执行我们想要的功能
有关寄存器的详细了解请移动到最后一部分,查看相关知识补充
5.进制转换
详细进制转换请看最后*相关知识补充*部分
6.相关代码及现象
1111 1110是使得P20为0,让它成为低电频
三、LED闪烁
结合上面的知识和江科大51单片机的视频,闪烁就会变得很容易,让我们接下来直接看代码吧
1.代码部分
LED灯500ms闪烁一次
最右侧的灯在闪烁
2.现象![](https://img-blog.csdnimg.cn/direct/437a8e46cfeb4cd197e2b6bbb040325b.jpeg)
现象是最右侧的灯在闪烁,图片无法呈现,大家见谅啦!
四、LED流水灯
1.代码部分
灯从右至左依次闪烁,时间间隔为500ms
2.流水灯改进,可控制延迟时间
五、独立按键控制LED灯的亮灭
1.轻触按键
按键相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开
单片机上电的时候,所有的io口默认的都是高电频,按键没有按下,保持的就是高电频,如果按下按钮,保持的就是低电频
2.操作
(1)srf是定义8位整个寄存器的,srf是操作8位的,P2=0xFE;
(2)sbit P2_2 = =0xA2 //sbit是操作1位的
- P2_0=0; //只用输入0或1,因为它是操纵一位的,非0就代表1
(1)独立按键
RXD是P3_1
3.代码和引脚
六、独立按键控制LED的状态
1.按键的抖动
对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动
2.按键的消抖
(1)硬件消抖
- 加个电路,把线经过这个电路,里面经过一些触发器等等,将抖动进行过滤
(2)软件消抖
- 通过软件来处理,在检测到按键按下,可以延时一会,等它的抖动消除,松手的时候也延时一会,然后再进行操作
- 用延时消抖,可以使得按下再松开后控制灯的亮灭
七、独立按键控制LED显示二进制
1.unsigned char
- 无符号字符型,0-255,刚好是8位的二进制数字,和P2口和寄存器都是一样的,都是8位,一般用它来表示寄存器
- P2默认的初始值是1111 1111为高电频
- 1111 1111 +1 = 0000 0000
2.相关代码![](https://img-blog.csdnimg.cn/direct/3c3b833dd9724c079fb9f7214fb06aeb.jpeg)
LEDNum初始值是0,为0000 0000,然后+1为0000 0001,最后取反得到1111 1110
八、独立按键控制LED移位
1.移位运算
要用到<<移位运算,详细的移位运算请看最后一部分
2.LED移位控制
进行LED移位控制,向左移位
向左,右移位
九、静态数码管显示
1.LED数码管
数码管是一种简单、廉价的显示器,是由多个发光的二极管封装在一起组成“8”字型的器件。
2.数码管引脚
一个数码管由8个LED组成
3.连接方式
共阴极连接,8个LED阴极都连到了一个端口上
共阳极连接,8个LED的阳极都连接在一个引脚上
4.段的名称
最上面是A,顺时针以此B,C,F,E,F,中间是G,加一个小数点DP
这些段加起来是8个,与8位字节一一对应
5.引脚定义
左下角是1号引脚,逆时针依次2,3,4,5,6......
引脚连接
公共正极是3,8号引脚,然后A段对应的负极是7号引脚,B段对应的负极是6号引脚......
6.点亮一个6
公共端阴极接在了负极上,负极接地或者低电频,负极接好后,这个叫位选
B和DP不需要被点亮,10111110是这个LED的段码
共阳极,公共端接在阳极
阳极接高电频,阴极接低电频,01000001是这个LED的段码
7.四位一体数码管
共12个引脚,他们的公共端单独引出来,他们的位选段端连在一起
显示数字1
在第3位显示数字1
LED1-8接在138译码器的输出端
ABC控制LED1—8
ABC为输入端,Y0-Y7是输出端,需要接电源,G1,G2A,G2B是使能端,是一种电源开关,如果使能电频有效,他就会工作,无效他就不工作
G1接高电频1,G2A,G2B接低电频0,就可以工作了
输入端,C是高位,B,A是低位
38线译码器,三根线到8根线
将ABC高低位排序,排序后为CBA,它是二进制,转化为10进制的数,就会对应输出
举例
eg:CBA对应000,则10进制为0,所以Y0有效,Y0为低电频
CBA对应001,则10进制为1,所以Y1有效,Y1为低电频
双向数据缓冲器
用来进行数据缓冲,给它一个数据,缓冲器就是提升驱动能力的
DIR,是双向,将左边数据缓冲到右边,或者从右边读回来,但是一般数据从左到右
DIR接高电频就会把数据从左边送到右边,低电频从右边送到左边
高电频驱动能力比较弱,低电频驱动能力较强,所以LED采用低电频点亮
左边的就是控制信号,控制信号只需要很微弱,缓冲器就能够接受,再通过电源获取能量,然后再输出到引脚,驱动数码管以比较亮的形式显示
8.电容
一个1法拉的超级电容,3.6V电压的情况下,差不多是1mAh
电容储存的电量和电池相比实在是太小太小了,电容的好处就是充放电速度比电池快得多,当然电流也大得多。
中间的转换时10的3次
作用时稳定电源,给芯片供电更加的稳定,叫做电源滤波
9.排阻
100R代表100欧姆
限流作用,防止数码管的电流过大,是四位一体的排阻
点亮第四个LED,显示为6,0111 1110转换为16进制为0x7D,0x7D是6的段码
数组里是0-9的段码,switch是控制是第几个LED
十、动态数码管显示
1.静态数码管上123会连续闪烁
2.会产生消影
3.消影
消隐:位选 段选 位选 段选 位选 段选 位选 段选 位选 段选不断重复
- 在很短的时间里,上一位数据就会串到下一位数据里面去,下一个位选出来了以后,上一个段选还在显示
- 消影的方法:
- 位选 段选 清零 位选 段选
位选:选择哪个数码管亮
段选:让选择的数码管两亮什么,段选是共用的
4.改进后
加入一个延时,防止它一下变暗
然后清零,就不会发生串位
5.数码管驱动方式
(1)单片机直接扫描
硬件设备简单,但会耗费大量的单片机CPU时间
(2)专用驱动芯片
内部自带显存、扫描电路,单片机只需告诉它显示什么即可
只需要两根线就可以控制16个数码管
十一、模块化编程
1.传统方式编程
所有的函数均放在main.c里,若使用的模块比较多则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路
2.模块化编程
把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要#include“xxxh”文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等
3.LCD1602调试工具
使用LCD1602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。
4.模块化编程框图
5.模块化编程注意事项
.c文件:函数、变量的定义
.h文件:可被外部调用的函数、变量的声明
任何自定义的变量、函数在调用前必须有定义或声明 (同一个.c)
使用到的自定义函数的.c文件必须添加到工程参与编译
使用到的.h文件必须要放在编译器可寻找到的地方 (工程文件夹根目录、安装目录、自定义)
6.C预编译
C语言的预编译以#开头,作用是在真正的编译开始之前,对代码做些处理(预编译)
#include 的作用就是将<REGX52.H>的东西里的内容拿出来
#ifndef #define #endif 是防止重复定义
就是用来对程序某些部分是否编译进行一个选择
7.<>和""的区别
<>是从安装目录里选择.h文件
""是在自己程序目录里寻找文件
十二、LCD1602调试工具
1.相关函数
使用LCD1602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。(目的是要会使用函数)
2.显示
在第一行、第一列显示A
显示字符串
显示数字123
显示有符号数字
显示16进制数
显示二进制数
显示加法
加入延时函数,让其每秒+1
持续更新......
*相关知识补充*
1.寄存器
寄存器是计算机硬件中用于存储和处理数据的一个小而高速的存储区域。它们是计算机处理器的一部分,负责暂时存储数据、指令和地址信息,以便CPU在执行指令时能够快速访问所需的信息。
可以将寄存器想象成计算机的“工作台”,计算机在执行各种操作时,需要在工作台上放置并快速使用一些工具和材料。与计算机中的其他存储设备(如内存和硬盘)相比,寄存器的容量较小,但速度极快。这是因为寄存器直接位于处理器内部,能够在极短的时间内读取和写入数据。
寄存器的主要类型包括:
- 通用寄存器:用于存储临时数据和操作数。例如,在进行加法运算时,操作数和结果可以存储在通用寄存器中。
- 专用寄存器:用于特定功能,例如程序计数器(存储当前正在执行的指令地址)、堆栈指针(指向堆栈顶的地址)等。
- 标志寄存器:用于存储处理器状态和操作结果的标志,例如零标志(表示运算结果是否为零)、进位标志(表示运算是否产生进位)等。
寄存器的设计使其能够在处理器执行指令时提供极高的速度和效率,确保计算机能够快速处理复杂的计算和数据操作。
2.进制转换
(1)常见进制简介
-
二进制(Binary):
- 基数:2
- 数字:0, 1
- 每一位称为一个“比特”(bit)
-
十进制(Decimal):
- 基数:10
- 数字:0-9
- 最常用的进制系统,也是我们日常生活中使用的系统
-
八进制(Octal):
- 基数:8
- 数字:0-7
-
十六进制(Hexadecimal):
- 基数:16
- 数字:0-9, A-F(其中A-F分别代表10-15)
(2)进制转换方法
二进制与十进制互转
-
二进制转十进制:
- 方法:将二进制数的每一位乘以对应的2的幂,然后求和。
- 示例:
1101₂
转换为十进制- 计算过程:1×2³ + 1×2² + 0×2¹ + 1×2⁰ = 8 + 4 + 0 + 1 = 13
- 结果:
1101₂ = 13₁₀
-
十进制转二进制:
- 方法:将十进制数除以2,记录余数,然后逆序排列余数。
- 示例:
13₁₀
转换为二进制- 计算过程:13 ÷ 2 = 6 余 1;6 ÷ 2 = 3 余 0;3 ÷ 2 = 1 余 1;1 ÷ 2 = 0 余 1
- 结果:
13₁₀ = 1101₂
二进制与八进制互转
-
二进制转八进制:
- 方法:将二进制数从右往左每三位分组,然后每组转换为一个八进制数。
- 示例:
1101101₂
转换为八进制- 计算过程:
1 101 101
;转换为八进制:1 5 5
- 结果:
1101101₂ = 155₈
- 计算过程:
-
八进制转二进制:
- 方法:将八进制数每一位转换为对应的三位二进制数。
- 示例:
155₈
转换为二进制- 计算过程:
1
转换为001
,5
转换为101
,5
转换为101
- 结果:
155₈ = 1101101₂
- 计算过程:
二进制与十六进制互转
-
二进制转十六进制:
- 方法:将二进制数从右往左每四位分组,然后每组转换为一个十六进制数。
- 示例:
11011011₂
转换为十六进制- 计算过程:
1101 1011
;转换为十六进制:D B
- 结果:
11011011₂ = DB₁₆
- 计算过程:
-
十六进制转二进制:
- 方法:将十六进制数每一位转换为对应的四位二进制数。
- 示例:
DB₁₆
转换为二进制- 计算过程:
D
转换为1101
,B
转换为1011
- 结果:
DB₁₆ = 11011011₂
- 计算过程:
十进制与其他进制互转
-
十进制转八进制:
- 方法:将十进制数不断除以8,记录余数,然后逆序排列余数。
- 示例:
83₁₀
转换为八进制- 计算过程:83 ÷ 8 = 10 余 3;10 ÷ 8 = 1 余 2;1 ÷ 8 = 0 余 1
- 结果:
83₁₀ = 123₈
-
八进制转十进制:
- 方法:将八进制数的每一位乘以对应的8的幂,然后求和。
- 示例:
123₈
转换为十进制- 计算过程:1×8² + 2×8¹ + 3×8⁰ = 64 + 16 + 3 = 83
- 结果:
123₈ = 83₁₀
-
十进制转十六进制:
- 方法:将十进制数不断除以16,记录余数,然后逆序排列余数。
- 示例:
254₁₀
转换为十六进制- 计算过程:254 ÷ 16 = 15 余 14 (E);15 ÷ 16 = 0 余 15 (F)
- 结果:
254₁₀ = FE₁₆
-
十六进制转十进制:
- 方法:将十六进制数的每一位乘以对应的16的幂,然后求和。
- 示例:
FE₁₆
转换为十进制- 计算过程:15×16¹ + 14×16⁰ = 240 + 14 = 254
- 结果:
FE₁₆ = 254₁₀
(3)小结
进制转换的核心在于理解每种进制的基数和权重,并能熟练进行幂次计算和余数记录。这些基本概念不仅适用于进制转换,还在计算机体系结构、数据表示和编程中起着至关重要的作用。
3.C51数据类型
4.C51数据运算
5.C语言移位运算
移位运算是C语言中一种非常重要且高效的位运算操作,用于操作二进制位。移位运算符分为左移运算符和右移运算符,分别用于将二进制位向左或向右移动。移位运算主要有以下几种类型:
(1)左移运算符(<<)
左移运算符用于将一个数的二进制位向左移动指定的位数,右边补0。左移运算相当于对该数乘以2的幂次。
语法:
result = value << n;
value
:要进行左移操作的数。n
:左移的位数。result
:左移后的结果。
示例:
int a = 5; // 二进制为:0000 0101
int b = a << 2; // 左移2位后,二进制为:0001 0100,十进制为:20
printf("%d\n", b); // 输出:20
(2)右移运算符(>>)
右移运算符用于将一个数的二进制位向右移动指定的位数,左边补符号位(对于有符号整数)或补0(对于无符号整数)。右移运算相当于对该数除以2的幂次(取整)。
语法:
result = value >> n;
value
:要进行右移操作的数。n
:右移的位数。result
:右移后的结果。
示例:
int a = 20; // 二进制为:0001 0100
int b = a >> 2; // 右移2位后,二进制为:0000 0101,十进制为:5
printf("%d\n", b); // 输出:5
(3)算术右移与逻辑右移
算术右移(Arithmetic Right Shift):保持符号位不变,左侧补符号位(适用于有符号整数)。
逻辑右移(Logical Right Shift):左侧补0(适用于无符号整数)。
注意: 在C语言中,对于有符号整数,右移的行为是与实现相关的,但通常是算术右移。对于无符号整数,总是进行逻辑右移。
(4)使用移位运算的常见场景
快速乘法和除法:
- 左移一位相当于乘以2,左移n位相当于乘以2的n次方。
- 右移一位相当于除以2,右移n位相当于除以2的n次方(取整)。
位掩码操作: 移位运算常用于位掩码操作,例如设置、清除或检查特定位
unsigned char mask = 0x01 << 3; // 设置掩码以访问第四位(从0开始计数)
高效的计算: 移位运算比乘法和除法操作更高效,常用于性能关键的代码中。
(5)示例代码
下面是一些使用移位运算的示例代码:
#include <stdio.h>
int main() {
int a = 5; // 0000 0101
int leftShift = a << 2; // 0001 0100
int rightShift = a >> 1; // 0000 0010
printf("Left shift: %d\n", leftShift); // 输出:20
printf("Right shift: %d\n", rightShift); // 输出:2
// 位掩码示例
unsigned char mask = 0x01 << 3; // 0000 1000
unsigned char value = 0x0F; // 0000 1111
unsigned char result = value & mask; // 0000 1000
printf("Bit mask result: %d\n", result); // 输出:8
return 0;
}
在这个示例中,我们展示了左移和右移的基本用法,以及如何使用位掩码操作特定位。通过这些基本操作,可以实现许多复杂的位级操作和优化。