ADC0读取结果右移2位的作用及必要性咨询
关于ADC读取时右移2位的疑问
我已经解决了部分问题,但还有疑问需要澄清:使用以下ADC初始化与读取代码时,未添加(ADC0.RES >> 2)时得到十进制值4092,添加2位右移后得到1024。我不清楚其中原理,想了解该右移操作是否必要,以及为何仅在右移2位后得到该结果,请予以解释。
uint16_t adc_value=0; void ADC0_init(void) { /* Disable digital input buffer */ PORTA.PIN6CTRL &= ~PORT_ISC_gm; PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable pull-up resistor */ PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm; ADC0.CTRLB = VREF_ADC0REFEN_bm ; VREF.CTRLA = VREF_ADC0REFSEL_4V34_gc; ADC0.CTRLC |= ADC_PRESC_DIV4_gc /* CLK_PER divided by 4 */ | ADC_REFSEL_INTREF_gc; /* Internal reference */ ADC0.CTRLA |= ADC_ENABLE_bm /* ADC Enable: enabled */ | ADC_RESSEL_10BIT_gc; /* 10-bit mode */ /* Select ADC channel */ ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc; } uint16_t ADC0_read(void) { /* Start ADC conversion */ ADC0.COMMAND = ADC_STCONV_bm; /* Wait until ADC conversion done */ while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) ) { ; } /* Clear the interrupt flag by writing 1: */ ADC0.INTFLAGS = ADC_RESRDY_bm; return (ADC0.RES >> 2); }
解答
1. 右移操作的本质:ADC结果的对齐规则
你在初始化时配置了10位ADC分辨率(ADC_RESSEL_10BIT_gc),但这款MCU的ADC0.RES是16位寄存器。为了统一不同分辨率的存储格式,ADC会把10位的转换结果左对齐存储在寄存器的高位区域——具体到你的情况,10位有效数据被放在了ADC0.RES的bits 11~2位置,低2位补0。
比如你读到的4092,二进制是111111111100,其实就是10位满量程值(1023)左移2位后的结果(1023 × 4 = 4092)。
2. 右移2位的作用:还原真实的10位数值
右移2位操作ADC0.RES >> 2,就是把左对齐的有效数据移回寄存器的低10位,消除高位填充的偏移,得到符合10位分辨率范围的真实值(0~1023)。你得到的1024应该是近似值(实际满量程是1023,可能是测量误差或输入接近参考电压导致的微小偏差)。
3. 右移操作是否必要
这取决于你的使用场景:
- 如果你需要计算绝对电压值(比如根据参考电压换算输入电压),必须添加右移,否则数值会被放大4倍,导致计算结果完全错误。
- 如果你只需要比较ADC结果的相对大小(比如判断输入是否超过阈值),可以不用右移,但这不符合常规开发习惯,且会降低数值范围的可读性。
简言之,右移是为了将ADC的左对齐结果转换为开发者习惯的右对齐格式,确保数值对应真实的分辨率范围。
内容的提问来源于stack exchange,提问作者user21170594
相关产品推荐
相关产品推荐

