下图是Sensor 的datasheet. 按我的理解这是 24位ADC (bit0 - bit23) 其中 bit21,22,23 是符号位,bit0 到 bit20是数据位。
stm32F4 板子
官网给的sample code 里面,在表示负数的adc值 没看明白,
bit21-23 符号位有4种情况 ,
(000) 正数 并没有超出正的最大值
(111) 负数 并没有超出负数的最小值
(001)正数但超出了正的最大值
(110)负数但超出了负数的最小值
故用一个int32的变量 adc_data 来表示 adc 的值
int32_t adc_data = 0;
adc_data = (int32_t)(((SensorData[0] << 16) | (SensorData[1] << 8) | (SensorData[2] << 0))&0xFFFFFF);
uint8_t sign = 0;
sign =(uin8_t) ((adc_data & 0xE00000) >> 21); //1110 0000, 0000 0000, 0000 0000
adc_data = (adc_data & 0x1FFFFF); //0001 1111, 1111 1111, 1111 1111
switch (sign)
{
case 0: // Positive and lower than positive full-scale (within full-scale range)
{
adc_data = (adc_data & 0x1FFFFF); //0001 1111, 1111 1111, 1111 1111
break;
}
case 7: // Negative and higher than negative full-scale (within full-scale range)
{
adc_data = (adc_data & 0x1FFFFF) * (-1);// 我认为应该这样
adc_data = (adc_data | 0xFFE00000); //官网给的代码 不理解
break;
}
case 1: //Out of Positive Full scale
{
adc_data = 0x1FFFFF; //0001 1111, 1111 1111, 1111 1111
break;
}
case 6: // Out of Negative Full scale
{
adc_data = 0x1FFFFF * (-1); // 我认为应该这样
adc_data = 0xFFE00000; // 官网给的代码 不理解而且0xFFE00000 = 4,292,870,144 已经超出 int32 表示范围
break;
}
default:
{
break;
}
}// END switch
)
adc_data = (adc_data & 0x1fffff)
该回答引用于gpt与OKX安生共同编写:
这段代码是将从Sensor中读取到的24位ADC数据转换为一个32位有符号整型数据,并且将其进行了一些必要的处理以表示正负数和溢出情况。
具体来说,先将3个字节的数据(SensorData[0]、SensorData[1]、SensorData[2])按位拼接成一个24位的数据,然后再将该数据转换为32位有符号整型(int32_t)。在转换时,首先使用位与运算将数据中的高8位(即符号位)清零,然后根据符号位进行进一步的处理。
当符号位为000时,表示数据为正数并且没有超出正数的最大值,此时直接保留低21位的数据即可。
当符号位为111时,表示数据为负数并且没有超出负数的最小值,此时需要将低21位的数据取反,并且将整个数据加上0xFFE00000,以表示负数。注意,在这种情况下,低21位已经被取反,所以不能直接用乘法得到相反数。
当符号位为001时,表示数据为正数但超出了正数的最大值,此时将整个数据赋值为0x1FFFFF即可。
当符号位为110时,表示数据为负数但超出了负数的最小值,此时需要将整个数据赋值为0xFFE00000,以表示负数。注意,在这种情况下,低21位无法确定具体数值,因此将整个数据都改为0xFFE00000。
这种表示方法在STM32的官方文档中被称为“二进制补码”,常见于单片机或嵌入式系统中的数据表示。
参考GPT:这段代码的目的是将从传感器读取的 24 位 ADC 值转换为一个有符号的整数。下面对代码中的每一部分进行解释:
1 读取 ADC 值
adc_data = (int32_t)(((SensorData[0] << 16) | (SensorData[1] << 8) | (SensorData[2] << 0))&0xFFFFFF);
这一行代码将从传感器读取的 24 位 ADC 值合并为一个 32 位整数,并清除了最高 8 位,即保留了 ADC 值的最低 24 位。
2 确定 ADC 值的符号
sign =(uin8_t) ((adc_data & 0xE00000) >> 21);
这一行代码用位操作提取 ADC 值的符号位,即将 ADC 值的最高 3 位取出并右移 21 位,得到一个 0~7 之间的数字,代表 ADC 值的符号。
3 根据符号位进行转换
接下来的 switch 语句根据符号位的不同,对 ADC 值进行不同的转换。具体的转换过程如下:
符号位为 0:表示 ADC 值为正数且在正的最大值范围内,直接保留 ADC 值。
符号位为 7:表示 ADC 值为负数且在负的最小值范围内,先将 ADC 值乘以 -1 取反,然后将最高 11 位设置为 1,以得到一个有符号的 32 位整数。
符号位为 1:表示 ADC 值超出了正的最大值范围,将 ADC 值设置为最大的正值 0x1FFFFF。
符号位为 6:表示 ADC 值超出了负的最小值范围,先将 ADC 值乘以 -1 取反,然后将 ADC 值设置为最小的负值 0xFFE00000。
需要注意的是,符号位为 7 和 6 时,需要先将 ADC 值乘以 -1 取反。
在stm32F4板子上表示负数的ADC值。根据ST官方文档1,在stm32F4板子上,ADC采集到的数据是无符号的,因此需要将其转换为有符号的数据。具体来说,如果ADC采集到的数据是24位,则需要将其转换为32位有符号整数。转换方法如下:
将采集到的24位数据左移8位。
检查左移后的数据的最高位(即第31位),如果为1,则说明该数是负数。
如果该数是负数,则需要将其减去2^24。
打开windows计算器,
点击菜单切换成程序员模式
点击QWORD切换成DWORD
依次点击0,-,1,=
看HEX的值
理解清楚计算机怎么存储和表示负数的
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
后续会进一步的更新,刚刚学习STM32F4板子,有错误欢迎大家指正。
2020年9月1日 天气晴