二、数制与编码:从进制转换到机器码的硬件基石
在数字电路与计算机系统设计中,数制与编码是理解一切硬件行为的基础语言。无论是CPU内部的算术逻辑单元(ALU)执行加法运算,还是存储器中保存的指令与数据,亦或是传感器采集到的模拟信号经ADC转换后的数字量,最终都以二进制比特流的形式存在。本章将系统讲解二进制、八进制、十进制、十六进制之间的转换方法,深入剖析原码、反码、补码的数学本质与硬件实现逻辑,并介绍BCD码、格雷码等工程中广泛应用的编码方案。掌握这些内容,是后续学习组合逻辑电路、时序逻辑电路以及微处理器接口设计的必要前提。
2.1 数制转换:从二进制到十六进制的工程速算
2.1.1 核心原理:位置计数法与权值
任何R进制数均可表示为各位数字与其权值乘积之和。对于二进制(R=2),权值为2的幂次;十六进制(R=16)权值为16的幂次。硬件工程师之所以偏爱十六进制,是因为一位十六进制数恰好对应四位二进制数,可以极大缩短长二进制数的书写长度。例如32位地址总线用二进制表示需要32个字符,而用十六进制仅需8个字符。
2.1.2 转换方法与操作流程
- 二进制转十六进制:以小数点为界,整数部分向左、小数部分向右,每4位一组,不足4位补0,每组用对应的十六进制字符(0-9, A-F)替换。
- 十六进制转二进制:将每位十六进制数展开为4位二进制数,去掉整数部分最高位和小数部分最低位的多余0。
- 十进制转二进制:整数部分采用“除2取余,逆序排列”;小数部分采用“乘2取整,顺序排列”。
- 二进制转十进制:按权展开求和,例如
1011.01₂ = 1×2³ + 0×2² + 1×2¹ + 1×2⁰ + 0×2⁻¹ + 1×2⁻² = 11.25₁₀。
1010 1101₂ = 0xAD。
2.1.3 案例拆解:配置I2C设备地址
假设某传感器I2C从机地址由7位硬件引脚决定,引脚电平组合为 A2=1, A1=0, A0=1,加上固定的基地址 0x40(7位),则完整地址计算如下:
基地址: 100 0000 (0x40)
引脚位: 1 0 1
拼接: 100 0000 1 0 1 → 7位地址 = 1000 0010 1? 实际为 1000 0010 1 取前7位: 1000 0010 1 → 0x41? 重新计算:
7位地址 = 100 0000 (基) + (A2<<2 | A1<<1 | A0) = 0x40 + (1<<2 | 0<<1 | 1) = 0x40 + 5 = 0x45
写地址 = 0x45 << 1 = 0x8A, 读地址 = 0x8B
通过十六进制运算,工程师可以快速确定读写地址,避免逐位二进制转换的繁琐。
2.1.4 常见误区与总结
0.1₁₀ = 0.0001100110011...₂,在浮点表示中会引入舍入误差。
| 进制 | 基数 | 数码范围 | 后缀 | 典型应用 |
|---|---|---|---|---|
| 二进制 | 2 | 0,1 | B | 数字电路内部信号 |
| 八进制 | 8 | 0-7 | O/Q | 早期UNIX文件权限 |
| 十进制 | 10 | 0-9 | D | 人机交互显示 |
| 十六进制 | 16 | 0-9, A-F | H/0x | 地址、寄存器、机器码 |
2.2 原码、反码与补码:有符号数的硬件实现
2.2.1 核心原理:符号的数字化表示
计算机硬件只能存储0和1,因此必须约定符号位的编码方式。原码是最直观的表示:最高位为符号位(0正1负),其余位为数值值。但原码存在两个问题:一是“正0”(0000)与“负0”(1000)表示冲突;二是加减法运算需要判断符号位,硬件电路复杂。反码通过将负数的数值位按位取反解决减法问题,但仍有双0问题。补码则彻底解决了这些问题:正数的补码等于原码,负数的补码等于反码加1。
2.2.2 补码的数学本质与运算规则
对于n位二进制补码,其数值范围是 -2ⁿ⁻¹ ~ 2ⁿ⁻¹-1。补码的模运算特性使得减法可以转化为加法:A - B = A + (-B的补码)。例如8位系统中计算 5 - 3:
5的补码: 0000 0101
-3的补码: 1111 1101 (3=0000 0011 → 取反1111 1100 → +1 → 1111 1101)
相加: 0000 0101 + 1111 1101 = 1 0000 0010 → 丢弃进位 → 0000 0010 = 2 ✓
硬件ALU只需一个加法器即可完成加减法,大幅简化电路设计。溢出判断可通过最高位进位与次高位进位的异或实现。
2.2.3 案例拆解:8位ADC采样值的符号处理
某温度传感器使用8位ADC,输出格式为二进制补码,满量程对应 -40℃ ~ +125℃。当ADC输出 0x80(即 1000 0000)时,其十进制值为 -128,对应最低温度 -40℃;输出 0x7F(0111 1111)时,值为 +127,对应 +125℃。实际温度计算公式为:
温度 = (ADC值 / 128) × 165 - 40
例如 ADC = 0x00 (0) → 温度 = 0 × 165/128 - 40 = -40℃
ADC = 0x40 (64) → 温度 = 64 × 165/128 - 40 = 82.5 - 40 = 42.5℃
工程师在固件中需先将读取的原始字节强制转换为 int8_t 类型,再进行上述线性换算,否则无符号数会导致负温度计算错误。
2.2.4 常见误区与总结
0x80(-128)扩展为16位应为 0xFF80,而非 0x0080。在C语言中,若将 char 赋值给 int,编译器会自动进行符号扩展。
| 编码方式 | +5表示 | -5表示 | 0的表示 | 运算复杂度 |
|---|---|---|---|---|
| 原码 | 0000 0101 | 1000 0101 | 0000 0000 / 1000 0000 | 需判断符号,复杂 |
| 反码 | 0000 0101 | 1111 1010 | 0000 0000 / 1111 1111 | 减法可转加法,仍有双0 |
| 补码 | 0000 0101 | 1111 1011 | 0000 0000 | 加减统一,硬件简单 |
2.3 BCD码与格雷码:面向显示与抗干扰的编码
2.3.1 BCD码:二进制编码的十进制数
BCD(Binary-Coded Decimal)码用4位二进制数表示1位十进制数,最常用的是8421 BCD码。例如十进制数 39 的BCD码为 0011 1001。BCD码的优点是便于人类阅读和十进制运算,常用于数码管显示、计算器、RTC时钟芯片等场景。但BCD码的存储效率低于纯二进制(4位BCD最大表示9,而4位二进制最大表示15),且运算时需要额外的十进制调整指令(如DAA)。
2.3.2 格雷码:相邻码仅一位变化的循环码
格雷码(Gray Code)的核心特征是任意两个相邻码字之间只有1位二进制位不同。这一特性使其在机械编码器、旋转位置传感器、异步FIFO指针、状态机设计中具有显著优势——当信号在相邻状态间切换时,不会出现多位同时跳变导致的毛刺或竞争冒险。4位格雷码序列为:0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000。
2.3.3 案例拆解:旋转编码器的位置检测
工业伺服电机常使用增量式光电编码器,码盘上刻有格雷码图案。假设码盘有12位格雷码,对应360°机械角度。当电机旋转时,光电传感器输出格雷码信号,FPGA或MCU需将格雷码转换为二进制位置值:
// 格雷码转二进制 (C语言实现)
uint16_t gray_to_binary(uint16_t gray) {
uint16_t bin = gray;
while (gray >>= 1) {
bin ^= gray;
}
return bin;
}
// 示例: 格雷码 0b1011 → 二进制 0b1101 → 十进制 13
由于格雷码相邻位置仅1位变化,即使码盘在边界处抖动,也不会出现类似二进制码从0111到1000时多位同时变化导致的瞬间错误读数。该设计显著提高了位置反馈的可靠性。
2.3.4 常见误区与总结
0x99 作为BCD码表示十进制数99,而作为十六进制数表示十进制数153。在RTC芯片(如DS1302)中,寄存器默认使用BCD格式存储时间,读取后需进行 dec = (bcd & 0x0F) + ((bcd >> 4) * 10) 转换。
| 编码类型 | 位数 | 表示范围 | 核心优势 | 典型应用 |
|---|---|---|---|---|
| 8421 BCD | 4位/十进制位 | 0-9 | 十进制直观,便于显示 | 数码管、RTC、计算器 |
| 格雷码 | n位 | 0 ~ 2ⁿ-1 | 相邻码仅1位变化,抗干扰 | 编码器、FIFO指针、状态机 |
| ASCII码 | 7位/8位 | 0-127/255 | 字符标准化 | UART通信、键盘输入 |
| 奇偶校验码 | 数据位+1校验位 | 取决于数据位 | 单比特检错 | UART、存储器校验 |
2.4 编码在硬件设计中的综合应用与工程复盘
2.4.1 数据链路中的编码选择策略
在实际硬件系统中,不同编码各司其职:CPU内部数据总线使用二进制补码进行算术运算;外部存储器地址使用十六进制表示便于调试;人机交互接口(如数码管)使用BCD码;高速串行通信(如PCIe、USB)使用8b/10b编码保证DC平衡;传感器位置反馈使用格雷码消除毛刺。工程师在设计方案时,应根据信号传输距离、实时性要求、抗干扰需求、调试便利性等因素综合选择编码方式。
2.4.2 案例复盘:混合信号采集板卡的编码设计
背景与约束:某工业数据采集板卡需同时处理8路模拟输入(16位ADC)、4路旋转编码器反馈、以及通过UART与上位机通信。板卡工作环境存在较强电磁干扰,且要求位置数据实时性高。
设计决策过程:
- ADC数据:采用二进制补码输出,MCU直接读取16位有符号数,通过查表法进行线性标定,避免浮点运算耗时。
- 编码器接口:选用12位格雷码输出型编码器,硬件电路使用异或门阵列将格雷码转换为二进制,转换延迟小于20ns,满足1MHz更新率要求。
- UART通信:数据帧采用ASCII码传输十六进制字符串,便于上位机解析和日志记录;每帧附加奇偶校验位,检测传输错误。
- 数码管显示:本地面板使用BCD码驱动4位LED数码管,显示当前温度值,MCU通过查表将二进制温度值转换为BCD码。
结果与复盘:该方案在实验室测试中,编码器在3000rpm转速下未出现位置跳变;UART通信在施加2kV ESD干扰时,误码率低于10⁻⁶。复盘经验:格雷码的抗干扰优势在长线传输中尤为明显;BCD码虽然浪费存储空间,但省去了显示驱动芯片的二进制转十进制逻辑,降低了BOM成本。
数制与编码是连接数学抽象与硬件实现的桥梁。从简单的进制转换到复杂的补码运算,再到面向特定场景的编码方案,每一个知识点都直接关系到硬件系统的正确性、可靠性与可维护性。建议读者在后续学习存储器接口、通信协议和嵌入式系统时,有意识地识别其中使用的编码方式,并思考设计者为何做出如此选择,这将极大提升硬件设计能力。