一、核心基础概念
裸机
裸机开发指代码直接与硬件交互,不依赖操作系统(OS),通过直接操作寄存器或硬件接口实现功能,是嵌入式入门(如LED、按键控制)的常用开发模式。
Soc(系统级芯片)
未明确展开,通常指集成多个功能模块的芯片,可包含CPU/MCU核心、内存、外设(如GPIO、UART)等,是复杂嵌入式设备(如手机、物联网网关)的核心。
核心计算/控制芯片(CPU、MPU、MCU、GPU)
四者均为芯片级核心,核心区别在于功能定位与集成度,覆盖从通用计算到专用控制的不同场景:
- CPU(中央处理器):通用计算核心,负责执行计算机指令运算,是PC、服务器等设备的“大脑”,不直接集成专用外设。
- MPU(微处理器):可理解为“无集成外设的CPU”,需外接内存、存储和外设才能工作,常见于高端嵌入式设备(如手机SoC中的应用处理器)。
- MCU(微控制器):“微型计算机”,高度集成(含CPU核心、RAM/ROM内存、GPIO/UART等外设),体积小、成本低,是LED控制、传感器采集等简单场景的核心,典型例子为C8051单片机、STM32。
- GPU(图形处理器):专用图形计算核心,擅长并行运算,负责图像渲染、视频处理,也可用于AI算力加速(如显卡中的GPU)。
二、外设寄存器
定义
外设寄存器是硬件外设(如GPIO、UART、TIMER)与软件的交互接口,本质是一块具有固定地址的高速存储单元,用于存储“控制指令”或“硬件状态数据”,相当于硬件的“控制开关面板”。
寄存器(外设):是指能够操作硬件的,具有固定地址的内存空间
作用逻辑
软件通过“读写寄存器”实现对硬件的控制:
- 写寄存器:配置外设工作模式(如设置GPIO为输出模式、控制LED电平);
- 读寄存器:获取外设实时状态(如读取按键是否按下、TIMER计数是否完成)。
适用架构
在x86、ARM、MIPS、8051等主流嵌入式/计算机架构中均存在,是跨平台硬件控制的核心机制。
三、GPIO(通用输入输出端口)
定义
GPIO是单片机/MCU上的通用引脚接口,可通过软件灵活配置工作模式,是嵌入式开发中最基础、最常用的外设接口。
工作模式与应用
- 输出模式:控制外部设备,如驱动LED亮灭、继电器吸合;
- 输入模式:读取外部信号,如检测按键是否按下、传感器输出的电平信号。
典型应用场景
LED实验、按键检测实验、传感器数据采集(如温湿度传感器)等,均依赖GPIO实现硬件交互。
四、LED实验(基于C8051单片机)
实验关键信息
- 硬件逻辑:LED采用“高电平灭、低电平亮”(文档1明确提及);
- 控制端口:使用C8051的P2端口(代码中通过操作P2寄存器实现LED控制);
- 核心功能:实现LED全亮、全灭及“跑马灯”效果(从0~7引脚循环点亮,再从6~0引脚循环点亮)。
用到的寄存器
LED实验的核心是通过GPIO端口寄存器控制电平,不同平台寄存器存在差异:
平台 | 核心寄存器 | 作用 |
---|---|---|
C8051单片机 | P2端口寄存器 | 直接控制P2引脚电平,如P2=0 (全亮)、P2=0xff (全灭) |
STM32 | GPIO模式寄存器(MODER) | 设置GPIO引脚为“输出模式”,确保可控制LED电平 |
STM32 | GPIO输出数据寄存器(ODR) | 直接控制引脚输出高/低电平,是LED状态控制的关键 |
STM32 | GPIO上拉/下拉寄存器(PUPDR) | 可选配置,防止引脚电平浮动,避免LED误亮 |
完整实验代码
主函数代码(main.c)
#include <reg52.h>
#include "led.h" // 引入LED控制函数头文件
int main(void)
{
int i;
led_all_off(); // 初始化:LED全灭(P2=0xff)
while(1) // 死循环,持续执行跑马灯逻辑
{
// 跑马灯:从引脚0~7依次点亮
for(i = 0; i < 8; ++i)
{
led_on(~(1 << i)); // 控制单个LED点亮(~(1<<i)确保对应引脚为低电平)
delay(30000); // 延时,保持LED点亮状态
}
// 跑马灯:从引脚6~0依次点亮(跳过引脚7)
for(i = 6; i > 0; --i)
{
led_on(~(1 << i));
delay(30000);
}
}
}
LED控制函数实现(led.c)
#include "led.h"
#include <reg52.h> // C8051寄存器定义头文件
// LED全亮:P2端口置0(所有引脚低电平)
void led_all_on(void)
{
P2 = 0;
}
// LED全灭:P2端口置0xff(所有引脚高电平)
void led_all_off(void)
{
P2 = 0xff;
}
// 单个LED点亮:n为P2端口的控制值(低电平对应LED亮)
void led_on (unsigned int n)
{
P2 = n;
}
LED控制函数声明(led.h)
#ifndef __LED_H_
#define __LED_H_
// 函数声明:供外部文件调用
extern void led_all_on(void); // LED全亮
extern void led_all_off(void); // LED全灭
extern void led_on (unsigned int n); // 单个LED点亮
#endif
#include <reg52.h>
#include "digiter.h"
#include "delay.h"
void bit_select(int n)
{
P1 &= ~(0x0f << 0);
P1 |= (1 << n);
}
void segmment_select(int n) // 0 ~ 9
{
unsigned char t[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
P0 = t[n];
delay(300); // 保证二极管导通
P0 = 0;
delay(300); // 消影
}
void show_number(int n) // 0 ~ 9999
{
int t = 0;
if(n == 0)
{
bit_select(0);
segmment_select(0);
}
if(n > 9999)
{
return;
}
while(n)
{
bit_select(t++);
segmment_select(n % 10);
n /= 10;
}
}
延迟函数实现
// 延时函数:通过循环实现简单延时
void delay(unsigned int n)
{
while (n--);
}
五、数码管相关
数码管段码表(0~9)
用于控制数码管显示数字,段码为十六进制值,对应数码管的“段点亮逻辑”:
// 数组t[0]~t[9]分别对应显示数字0~9
unsigned char t[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
数码管显示代码片段
数码管控制函数声明(led.c)(需注意不能加delay,避免影响显示刷新):
#include <reg52.h>
#include "digiter.h"
#include "delay.h"
void bit_select(int n)
{
P1 &= ~(0x0f << 0);
P1 |= (1 << n);
}
void segmment_select(int n) // 0 ~ 9
{
unsigned char t[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
P0 = t[n];
delay(300); // 保证二极管导通
P0 = 0;
delay(300); // 消影
}
void show_number(int n) // 0 ~ 9999
{
int t = 0;
if(n == 0)
{
bit_select(0);
segmment_select(0);
}
if(n > 9999)
{
return;
}
while(n)
{
bit_select(t++);
segmment_select(n % 10);
n /= 10;
}
}