单片机基础知识 -- 大端模式 与 小端模式

一、大小端模式介绍

1. 先搞懂:为什么要有大小端?

我们知道:

  • 1 个字节 = 8 bit
  • 但计算机里的 int、long、地址 都是 多字节(比如 4 字节)

问题来了:

一个 4 字节的数,存到内存里,高字节放前面,还是低字节放前面?

两种方案 → 就是 大端 / 小端

2. 举个最经典例子

假设有一个 32位整数

复制代码
0x12345678

拆成 4 个字节(从高到低):

  • 最高字节:0x12
  • 然后:0x34
  • 然后:0x56
  • 最低字节:0x78

内存地址从小到大:0x100 0x101 0x102 0x103


① 大端模式(Big-Endian)

高字节存低地址,和人类读写习惯一样

内存:

复制代码
0x100: 0x12
0x101: 0x34
0x102: 0x56
0x103: 0x78

特点:

  • 符合人类阅读顺序
  • 网络传输、ARM 在某些模式、部分单片机常用

② 小端模式(Little-Endian)

低字节存低地址,和人类反过来

内存:

复制代码
0x100: 0x78
0x101: 0x56
0x102: 0x34
0x103: 0x12

特点:

  • x86、x86_64(电脑CPU)全是小端
  • 计算机硬件计算更方便

3. 一句话总结(超好记)

  • 大端:高位在前,和人看书一样
  • 小端:低位在前,和人反过来

4. 你做嵌入式/单片机一定会遇到的场景

  1. 串口、SPI、I2C、网络通信

    协议一般是 大端 ,但你的 MCU 可能是小端,直接发数据会发反

  2. 强制类型转换、指针强转

    比如:

c 复制代码
int a = 0x12345678;
char *p = (char*)&a;
  • 大端:*p = 0x12
  • 小端:*p = 0x78
  1. 读写Flash、寄存器、协议解析
    大小端搞错,数据一定是错的。

5. 超简口诀

高对低(地址)是大端,低对低是小端

二、大端模式实际场景

16位数0x1234赋值给32位数

内存地址 (由低到高) 大端模式下的存放内容 说明
低地址 0x00 最高字节 (MSB)
0x00
0x12 原16位数的高字节
高地址 0x34 最低字节 (LSB)

16位数0x1234赋值给4字节数组

数组索引 地址(相对) 存储的内容(字节) 说明
arr[0] 低地址 0x12 高字节(高位)
arr[1] 高地址 0x34 低字节(低位)
arr[2] 更高地址 (未知) 数组后续元素,不受影响
arr[3] 最高地址 (未知) 数组后续元素,不受影响

1、场景一

在 UM800Y 这款大端模式的 8051 芯片中,如果你把一个 16 位的数(比如 unsigned int)赋值给一个 4 字节的数组,这个 16 位数在数组中的存放规则是:高字节(高位)存放在数组的低索引字节,低字节(低位)存放在数组的高索引字节

举个例子让你更清楚地理解

假设:

  • 你有一个 16 位的数值:0x1234(这里 0x12 是高字节,0x34 是低字节)。
  • 你定义了一个 4 字节的数组:unsigned char arr[4]
  • 你将这个 16 位数赋值给数组,比如通过指针操作或共用体。

那么,在内存中的实际存放结果将是:

数组索引 地址(相对) 存储的内容(字节) 说明
arr[0] 低地址 0x12 高字节(高位)
arr[1] 高地址 0x34 低字节(低位)
arr[2] 更高地址 (未知) 数组后续元素,不受影响
arr[3] 最高地址 (未知) 数组后续元素,不受影响

如果用代码来直观感受一下

你可以通过下面的 C 代码来验证这种存放方式:

c 复制代码
#include <stdio.h>

void main() {
    // 定义一个16位的数值
    unsigned int value = 0x1234;
    
    // 定义一个4字节的数组
    unsigned char arr[4] = {0};
    
    // 将16位数值的地址强制转换为字节指针,
    // 这样就可以按字节访问value在内存中的内容
    unsigned char *p = (unsigned char *)&value;
    
    // 将value的字节内容复制到数组的前两个元素中
    arr[0] = p[0]; // 在8051大端模式下,p[0]指向高字节 0x12
    arr[1] = p[1]; // p[1]指向低字节 0x34
    
    // 如果你debug查看arr的内容,会看到:
    // arr[0] == 0x12
    // arr[1] == 0x34
}

为什么是这样?

这完全是由 UM800Y 芯片的内核架构决定的。它使用的是 1T 8051 内核,完全兼容传统 8051 的指令代码 。而标准的 8051 架构在处理多字节数据(如 16 位的地址和 int 类型)时,采用的是大端格式。

2、场景二

在 UM800Y 芯片(大端模式)中,将一个16位的数赋值给一个32位的数,关键在于区分数值转换内存存放这两个概念。

简单来说,结论是:

  1. 数值上:16位数会被完整地、原样地赋值给32位数(存放在低位)。
  2. 内存中 :这个32位数作为一个整体,在内存中的存放规则依然遵循芯片的大端模式

我们用一个例子来具体看:

假设16位数是 0x1234。当你把它赋值给一个32位的变量(比如叫 value_32)后,这个 value_32数值 就变成了 0x00001234。也就是说,它在高位补了16个0。

现在,这个值为 0x00001234 的32位数,在UM800Y的大端模式下,内存地址从低到高的存放顺序会是:

内存地址 (由低到高) 大端模式下的存放内容 说明
低地址 0x00 最高字节 (MSB)
0x00
0x12 原16位数的高字节
高地址 0x34 最低字节 (LSB)

所以,这个过程可以拆解成两步来理解:

  1. 第一步:数值赋值 (确定"是什么")

    当你写下 uint32_t value_32 = 0x1234; 这行代码时,从C语言的逻辑层面看,value_32 这个变量里的值就被确定为了 0x00001234。这个过程和你之前问的"将16位数赋值给4字节数组"里的 arr[2]arr[3] 无关,它们是不同的内存操作。

  2. 第二步:内存存放 (确定"怎么放")

    这个数值 0x00001234 在物理内存中怎么存放,就完全由UM800Y的大端模式决定了。

    • 大端模式的核心规则 :数据的高字节 (这里是 0x00)放在内存的低地址 ;数据的低字节 (这里是 0x34)放在内存的高地址
    • 因此,这个32位的数在内存中,就是按顺序存放 0x00, 0x00, 0x12, 0x34

简单来说

如果你关心的是 value_32 这个变量的值,它就是 0x00001234

如果你通过指针,以字节为单位去查看 value_32 在内存中的样子,就会看到 0x00, 0x00, 0x12, 0x34 这个顺序。

相关推荐
雾削木2 小时前
STM32 基于外部时钟源的 PWM 测量
stm32·单片机·嵌入式硬件
qq_411262422 小时前
esp的深度睡眠关机功耗很高,一般软件方面应该查哪里?
单片机·嵌入式硬件
San_a dreamer fish2 小时前
STM32开发入门(二):
stm32·单片机·嵌入式硬件
v先v关v住v获v取2 小时前
CC1031载货汽车变速器结构设计13张cad+设计说明书+三维图
科技·单片机·51单片机
冒险家KL2 小时前
STM32 ISP自动下载探索及官方STM32CubeProgrammer实现自动下载
stm32·嵌入式硬件·isp
Wave8453 小时前
智能家居安防系统
stm32·单片机·智能家居
wsoz4 小时前
Linux与单片机程序对比
单片机·mcu·嵌入式·linux操作系统
姓刘的哦4 小时前
STM32控制直流有刷电机
单片机·嵌入式硬件
悠哉悠哉愿意4 小时前
【单片机学习笔记】math库函数补充
c语言·笔记·单片机·学习