1.嵌入式
嵌入式 (Embedded)指的是一种专用计算机系统 ,它被"嵌入"或内建到一个更大的设备、产品或系统中,作为其核心控制部分,专门用于执行特定的任务或功能 。通俗来讲++就是以应用为中心,以计算机技术为基础,软硬件可裁剪的专用计算机系统。++
2.51单片机
51单片机 是指由Intel公司于1980年推出的MCS-51系列单片机 及其所有兼容产品。它不是某一个芯片,而是一个架构家族的统称。虽然Intel早已停产,但众多厂商(如STC、Atmel、NXP等)生产的兼容芯片至今仍被广泛使用。

核心特征
-
经典架构:基于Intel的MCS-51指令集(CISC架构)
-
8位处理器:一次处理8位数据
-
哈佛结构:程序存储器和数据存储器分开
-
资源精简:
-
4KB-64KB Flash程序存储器
-
128B-1KB RAM数据存储器
-
32个I/O口(4组8位口:P0、P1、P2、P3)
-
3.基础概念
CPU:Central Processing Unit(中央处理器)数据运算、指令处理,CPU性能越高,完成指令处理和数据运算的速度越快
MCU:Micro Ctronller Unit(微控制器),集成度比较高,将所有功能集成到芯片中(CPU、RAM、ROM、定时器、UART、IO),简单控制, 成本低
MPU:Micro Processing Unit(微处理器),集成度低,只有一块单独的CPU,需外接外设、存储模块,复杂应用领域,跑Linux操作系统,成本高
GPU:Graphics Processing Unit(图形处理器),图形处理、图形渲染(GPU性能越好,图形显示的质量越好)
NPU:Neural Processing Unit(神经网络处理器),AI推理、硬件加速,神经网络处理(卷积运算)-> 华为Mate60 达芬奇NPU AI自动优化照片
FPU:Floating Point Unit(浮点数运算单元),完成浮点数的运算和处理(完全遵循IEEE 754),大部分集成在CPU内部
SOC:System On Chip(片上系统),集成度比较高,将多个芯片集成到一块芯片上(存储芯片、外设芯片)
4.单片机芯片内部结构
**1. 中央处理单元 (CPU):**执行指令、进行算术和逻辑运算、控制整个系统。
2.存储器系统(ROM只读存储器&RAM随机存储器):
Read-Only Memory,只读存储器,存放单片机程序,指令,掉电数据不丢失。
Random Access Memory,随机访问存储器,存放临时变量、临时数据,掉电数据丢失。
3.并行I/O端口 (32个引脚):
分为P0(8位,开漏输出,可作为数据/地址总线复用口),P1(8位,准双向I/O口,最常用的通用I/O口),P2(8位,准双向I/O口,可作为高8位地址总线),P3口(8位,准双向I/O口,具有第二功能:其中P3.0:RXD(串行输入),P3.1:TXD(串行输出),P3.2:INT0(外部中断0),P3.3:INT1(外部中断1),P3.4:T0(定时器0输入),P3.5:T1(定时器1输入),P3.6:WR(外部数据存储器写选通),P3.7:RD(外部数据存储器读选通)
4.定时器/计数器
计数功能:对外部脉冲计数
定时功能:对内部时钟脉冲计数
5.串行通信口 (UART)
全双工异步串行通信,与PC、传感器、其他单片机通信。
6.中断系统
7.时钟电路
由外部晶振或时钟源产生。
8.特殊功能寄存器 (SFR)
9.三大总线
地址总线:用来寻找RAM中的地址,所能寻址的最大范围2^8,256byte,单向。
数据总线:通过地址总线去获取数据,数据交互双向。
控制总线:时序控制、IO控制、中断。
5.原理图

MCU单片机芯片:
STC89C52RC、DIP40 封装:双列直插式,40个引脚,划分成4组(端口 寄存器 unsigned char P2;)
网络编号(如图写在cpu上的,如P1.0):在实际电路中的一个编号,避免物理连线,相同网络的编号的引脚在实际电路中是彼此互通;
引脚号(1-40)
6.位运算
6.1 |
将二进制中的对应位的bit进行比较,如果有一个bit为1,结果为1;如果都为0,结果为0;
应用场景:指定位置1
unsigned char t = 0x64;
将bit0和bit7置1:
t |= (1 << 0) | (1 << 7);
6.2 &
将二进制中的对应位的bit进行比较,如果全为1,结果为1;如果有一个0,结果为0;
应用场景:指定位清0
unsigned char t = 0xFF;
将bit 0 和 bit7 清0:
t &= ~(1 << 0);
t &= ~ (1 << 7);
7.LED模块

P20-P27分别控制8个LED灯,低有效
因此我们可以写一些控制LED灯的函数:
cs
#include <reg51.h>
void LED_INIT(void)//初始化
{
P2 = 0xff;
}
void LED_AllOn(void)//全亮
{
P2 = 0;
}
void LED_AllOff(void)//全灭
{
P2 = 0xff;
}
void LED_Nor(void)//翻转
// 使用异或运算实现按位取反
// 异或运算规则:0 ^ 1 = 1, 1 ^ 1 = 0
{
P2 = P2 ^ 0xff;
}
void LED_Show(unsigned int n)//指定某个灯亮
{
P2 = ~n;// 对参数n按位取反后赋值给P2口
// 假设n的二进制位代表LED状态:1表示要点亮,0表示要熄灭
// 取反是因为:如果LED是低电平有效,需要将逻辑1转换为低电平
// 例如:n = 0x01 (0000 0001) → 取反后为 0xFE (1111 1110)
// 表示只点亮最低位的LED,其他熄灭
}
控制8个灯亮灭反转
cs
#include <reg51.h>
#include <led.h>
#include <dalay.h>
int main(void)
{
int i = 0;
LED_INIT();
while(1)
{
LED_Nor();
delay(10000);
}
return 0;
}
控制1~8,8~1实现流水灯
cs
#include <reg51.h>
#include <led.h>
#include <dalay.h>
int main(void)
{
int i = 0;
LED_INIT();
while(1)
{
for(i = 0;i < 8; i++)
{
LED_Show(1<<i);
delay(1000);
LED_AllOff();
delay(1000);
}
for(i = 7;i > 0;i--)
{
LED_Show(1<<i);
delay(1000);
LED_AllOff();
delay(1000);
}
}
return 0;
}
8.数码管模块

P10~P13控制那个数码管工作,称为位选
P00~P07控制数码管那个管子工作,称为段选
因此我们可以封装一些控制数码管的函数:
cs
#include <reg51.h>
#include <delay.h>
//段码表
unsigned int Seg[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//位选
void Select_Bit(unsigned int n)
{
P1 &=~(0x0f << 0);//p1寄存器低四位清零
P1 |= (1 << n);
}
//段选
void Select_Seg(unsigned int n)
{
P0 = Seg[n];
}
// 数码管动态显示
void Digiter_Show(unsigned int n) // 例如传入 1234
{
int m = 0; // 用于存储每一位的数字(0-9)
int t = 0; // 用于记录当前显示的数码管位置(位选索引)
// 循环直到所有位数都处理完毕
while (n != 0)
{
m = n % 10; // 取n的个位数,例如:1234 % 10 = 4
P0 = 0; // 清空段选数据,先熄灭所有段,消除残影
Select_Bit(t++); // 选择要显示的数码管位置(位选)
// t++ 表示先使用当前t的值,然后t自增1
// 第一次调用:t=0,选择第0位数码管
// 第二次调用:t=1,选择第1位数码管,以此类推
Select_Seg(m); // 在选定的数码管上显示数字m(段选)
// 例如:m=4时,显示数字"4"
delay(100); // 延时一段时间,让当前数字稳定显示
// 延时时间影响显示亮度和闪烁频率
n /= 10; // 去掉已经处理的个位数,准备处理下一位
// 例如:1234 / 10 = 123
}
控制单个数码管显示:
cs
#include <reg51.h>
#include <digiter.h>
#include <delay.h>
int main(void)
{
int i = 0;
while(1)
{
for(i = 0;i < 10;i++)
{
Select_Bit(0);
Select_Seg(i);
delay(100000);
}
}
return 0;
}
控制四个数码管动态显示:0~9999
cs
#include <reg51.h>
#include <digiter.h>
#include <delay.h>
int main(void)
{
int i = 0;
while(1)
{
for (i = 0; i <= 9999; i++)
{
Digiter_Show(i);
}
}
return 0;
}