共计 1170 个字符,预计需要花费 3 分钟才能阅读完成。
为什么需要 20 位编码?
在嵌入式开发中,ADC 信号采集是一个常见需求。以温度传感器为例,8 位编码只能提供 256 个离散值,对应 0.5℃的分辨率;16 位编码虽然提升到 65536 个值,但在高精度场合(如医疗设备)仍显不足。20 位编码器可提供 1,048,576 个量化等级,分辨率达到 0.0001℃,满足精密测量需求。

核心原理
二进制权重与量化误差
20 位编码的核心是二进制权重分配,其量化误差公式为:
E_q = V_ref / (2^20 - 1)
其中 V_ref 为参考电压。例如当 V_ref=5V 时,理论最小分辨率为 4.77μV。
代码实现
SPI 接口配置(STM32F4 系列)
// SPI1 初始化(时钟极性 CPOL=1, 相位 CPHA=1)void SPI1_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // 使能 SPI1 时钟
SPI1->CR1 = SPI_CR1_CPOL | SPI_CR1_CPHA // 模式 3
| SPI_CR1_BR_2 // 波特率 =f_pclk/64
| SPI_CR1_MSTR; // 主机模式
SPI1->CR1 |= SPI_CR1_SPE; // 使能 SPI
}
使用 union 处理高低位
typedef union {
uint32_t full_data;
struct {
uint16_t low_word;
uint16_t high_word;
} parts;
} EncoderData;
// 读取 20 位数据(有效位在 bit19-bit0)EncoderData read_encoder(void) {
EncoderData data;
data.parts.high_word = SPI1->DR & 0x0FFF; // 取高 12 位
data.parts.low_word = SPI1->DR & 0xFFFF; // 取低 16 位
return data;
}
硬件设计要点
- 电源滤波 :
- 在 ADC 参考电压引脚添加 10μF 钽电容 +100nF 陶瓷电容
-
模拟电源与数字电源间使用磁珠隔离
-
SPI 布线 :
- 时钟线长度不超过 15cm
- 使用双绞线或屏蔽线传输
测试方法
示波器捕获时序
- 连接 CH1 到 SPI_CLK,CH2 到 SPI_MISO
- 设置触发模式为 CLK 下降沿
- 测量 CS 下降沿到第一个时钟沿的延迟(应 >100ns)
避坑指南
-
电源噪声 :
当 LSB 位频繁跳变时,检查电源纹波是否超过 10mVpp -
端序问题 :
ARM 架构默认小端序,与网络传输的大端序需转换:uint32_t swap_endian(uint32_t x) {return ((x >> 24) & 0xff) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x << 24) & 0xff000000); }
思考题延伸
过采样技术可通过 4^n 倍采样提升 n 位有效分辨率。例如:
– 4 倍采样→+ 1 位
– 16 倍采样→+ 2 位
实际应用中,需要权衡采样速度与分辨率提升的收益。
正文完
发表至: 未分类
近一天内
