Qm.n型数据和16bit以内的任意转换

这段代码包含两个转换函数:intGetIs()用于检查指定位置的位是否为1,getQMN()则将16位数值转换为浮点数,然后进一步转换为16进制。转换过程中涉及位移、位运算以及正负数的处理。
int  GetIs(ushort val,int n)
		{
			if (((val >> n) & 1) == 0) return 0;
			else return 1;
		}

//最大支持 16bit 转 浮点数
float GetQMN(int m, int n,ushort val1)
	{
			ushort val;
			if ((val1 & (1<<(m+n-1))) == 0)//如果最高位是0表示正数
			{
				val =val1;
			}
			else//负数
			{
				val = (ushort)( (~val1) + 1);
			}

			//负数 才用补码计算
			float tmp = 0;
			for (int i = 0; i < n; i++)//n=8
			{
				tmp += (float)(GetIs(val, i) * Math.Pow(2, i-n));
			}
			for (int i = 0; i < m; i++)//n=8
			{
				tmp += (float)(GetIs(val, n+i) * Math.Pow(2, i));
			}
			if ((val1 & (1 << (m + n - 1))) == 0)//如果最高位是0表示正数
			{
			
			}
			else//负数
			{
				tmp = tmp * -1;
			}
			return tmp;
		}



		//最大支持 16bit 转 16进制数据
		ushort GetQMN(int m, int n, float tmp)
		{
			
			ushort num = 0;
			ushort num2 = 0;
			ushort bitx = 0;
			int i;
			for (i = 0; i < n; i++)
			{
				bitx = (ushort)((Math.Abs(tmp) / Math.Pow(2, i - n))); num |= (ushort)(bitx << i);
			}
			for (i = 0; i < (m - 1); i++)
			{
				bitx = (ushort)((Math.Abs(tmp) / Math.Pow(2, n + i - n))); num |= (ushort)(bitx << i + n);
			}
			if (tmp < 0) num = (ushort)(((~num)));
			num2 = 0;
			for (i = 0; i < (m + n - 1); i++)
			{
				num2 |= (ushort)(num & (1 << i));
			}
			num2 += 1;
			if (tmp < 0) num2 |= (ushort)(1 << (m + n - 1));
			return num2;
		}

### 16位精度AD转换器的选择与特性 AD(模数转换器)的精度通常由其位数决定。16位AD意味着其输出范围可以划分为 $2^{16} = 65536$ 个不同的数字值。这种高分辨率使得16位AD适用于高精度测量场景,如工业控制、精密仪器、音频处理传感器信号采集等领域。 在实际应用中,16位AD的输入范围决定了其每个数字步长(LSB)对应的电压值。例如,如果AD的参考电压为3.3V,则其LSB为: $$ \text{LSB} = \frac{3.3}{65536} \approx 50.35 \, \mu V $$ 这意味着16位AD能够检测到非常微小的电压变化,适合用于高精度模拟信号采集。相比之下,12位AD的LSB为: $$ \text{LSB}_{12} = \frac{3.3}{4096} \approx 805.66 \, \mu V $$ 因此,16位AD的分辨率比12位AD高出一个数量级,适用于对精度要求更高的系统。 ### 16位AD的典应用场景 16位AD广泛应用于需要高精度测量的系统中,例如: - **精密传感器测量**:如压力传感器、温度传感器等,其输出信号通常较小,需要高分辨率的AD进行精确量化。 - **音频信号采集**:在音频设备中,16位AD能够提供足够高的动态范围,确保音频信号不失真[^3]。 - **工业控制与监测**:在自动化系统中,用于采集模拟量信号(如电压、电流、温度等),实现高精度控制。 - **医疗设备**:如心电图机、血糖仪等,要求AD具有高线性度低噪声特性。 ### 16位AD的实现方式 与12位ADC不同,16位ADC通常采用更复杂的转换架构,如: - **Σ-Δ(Sigma-Delta)结构**:通过过采样噪声整形技术实现高分辨率,适合低速、高精度应用。 - **逐次逼近(SAR)结构**:适用于中高速度、中高精度场合,具有低功耗、高集成度等优点。 - **流水线结构**:适用于高速采样场景,如视频信号处理、通信系统等。 对于嵌入式系统而言,一些常见的16位ADC芯片包括: - **TI ADS1115**:I²C接口,内置PGA(可编程增益放大器),适合低速、高精度测量。 - **Analog Devices AD7793**:适用于精密称重、温度测量等工业应用,具有低噪声、高稳定性特点。 - **Microchip MCP3424**:集成PGAI²C接口,支持4通道输入,适合多路信号采集系统。 ### 数据对齐与处理 在16位ADC中,数据寄存器通常为16位宽,因此不存在像12位ADC那样的对齐问题。在12位ADC中,数据可以左对齐或右对齐,左对齐会将12位数据左移4位,使得高8位可以直接提取,但会损失低4位的精度。16位ADC则直接使用完整的16数据寄存器,无需移位操作,能够保留完整的分辨率[^1]。 在嵌入式开发中,读取16位ADC数据时,通常需要进行字节交换(Endian转换),尤其是在使用I²C或SPI接口的外部ADC芯片时。例如,在使用ADS1115时,数据寄存器的高字节低字节顺序可能与MCU的内存顺序不同,需进行处理: ```c int16_t read_adc_value(uint8_t high_byte, uint8_t low_byte) { int16_t adc_value = (int16_t)((high_byte << 8) | low_byte); return adc_value; } ``` 该函数将高位字节低位字节合并为一个16位有符号整数,适用于带有符号输出的ADC芯片。 ### 选择16位AD的考量因素 在选择16位AD时,应综合考虑以下因素: - **采样率(SPS)**:Σ-ΔADC通常采样率较低,而SARADC可以支持更高的采样频率。 - **输入通道数量**:是否需要多通道同步采样,或使用多路复用器实现单ADC多通道采集。 - **接口类**:如I²C、SPI、UART等,影响与主控芯片的通信方式。 - **参考电压精度**:内部参考电压的稳定性直接影响ADC的绝对精度。 - **功耗与封装**:适用于电池供电设备或空间受限的应用场景。 ### 示例:ADS1115配置代码(I²C) 以下是一个使用I²C接口配置ADS1115的示例代码片段: ```c #include <Wire.h> #define ADS1115_ADDRESS 0x48 #define CONFIG_REG 0x01 #define CONVERSION_REG 0x00 void setup() { Wire.begin(); // 配置为单次转换模式,增益1x,数据速率128SPS Wire.beginTransmission(ADS1115_ADDRESS); Wire.write(CONFIG_REG); Wire.write(0xC3); // OS位设为1,单次转换 Wire.write(0x83); // 增益1x,128SPS Wire.endTransmission(); } int16_t read_adc() { Wire.beginTransmission(ADS1115_ADDRESS); Wire.write(CONVERSION_REG); Wire.endTransmission(); Wire.requestFrom(ADS1115_ADDRESS, 2); uint8_t high = Wire.read(); uint8_t low = Wire.read(); return (high << 8) | low; } ``` 该代码配置ADS1115为单次转换模式,并读取16位ADC值,适用于低功耗、高精度测量场景。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值