来自代码内 binary/hex 的无法解释的转换
Unexplained Conversion from a binary/hex within code
我正在使用来自 Waveshare 网站的代码(与安装在 RPi3 上的 ADDA Waveshare 板一起使用):http://www.waveshare.com/wiki/File:High-Precision-AD-DA-Board-Code.7z
*********************************************************************************************************
* name: main
* function:
* parameter: NULL
* The return value: NULL
*********************************************************************************************************
*/
int main()
{
uint8_t id;
int32_t adc[8];
int32_t volt[8];
uint8_t i;
uint8_t ch_num;
int32_t iTemp;
uint8_t buf[3];
if (!bcm2835_init())
return 1;
bcm2835_spi_begin();
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST ); // The default
bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); // The default
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_1024); // The default
bcm2835_gpio_fsel(SPICS, BCM2835_GPIO_FSEL_OUTP);//
bcm2835_gpio_write(SPICS, HIGH);
bcm2835_gpio_fsel(DRDY, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_set_pud(DRDY, BCM2835_GPIO_PUD_UP);
//ADS1256_WriteReg(REG_MUX,0x01);
//ADS1256_WriteReg(REG_ADCON,0x20);
// ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
id = ADS1256_ReadChipID();
printf("\r\n");
printf("ID=\r\n");
if (id != 3)
{
printf("Error, ASD1256 Chip ID = 0x%d\r\n", (int)id);
}
else
{
printf("Ok, ASD1256 Chip ID = 0x%d\r\n", (int)id);
}
ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
ADS1256_StartScan(0);
ch_num = 8;
//if (ADS1256_Scan() == 0)
//{
//continue;
//}
while(1)
{
while((ADS1256_Scan() == 0));
for (i = 0; i < ch_num; i++)
{
adc[i] = ADS1256_GetAdc(i);
volt[i] = (adc[i] * 100) / 167;
}
for (i = 0; i < ch_num; i++)
{
buf[0] = ((uint32_t)adc[i] >> 16) & 0xFF;
buf[1] = ((uint32_t)adc[i] >> 8) & 0xFF;
buf[2] = ((uint32_t)adc[i] >> 0) & 0xFF;
printf("%d=%02X%02X%02X, %8ld", (int)i, (int)buf[0],
(int)buf[1], (int)buf[2], (long)adc[i]);
iTemp = volt[i]; /* uV */
if (iTemp < 0)
{
iTemp = -iTemp;
printf(" (-%ld.%03ld %03ld V) \r\n", iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000);
}
else
{
printf(" ( %ld.%03ld %03ld V) \r\n", iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000);
}
}
printf("[%dA", (int)ch_num);
bsp_DelayUS(100000);
}
bcm2835_spi_end();
bcm2835_close();
return 0;
}
请帮我弄清楚这段代码在 main() 中的作用:
for (i = 0; i < ch_num; i++)
{
adc[i] = ADS1256_GetAdc(i);
volt[i] = (adc[i] * 100) / 167;
}
常数(100和167)没有解释。他们在这个 'calibration' 中到底想做什么,这些常量取决于什么?
具体看这段代码(这似乎是实际问题
for (i = 0; i < ch_num; i++)
{
adc[i] = ADS1256_GetAdc(i);
volt[i] = (adc[i] * 100) / 167;
}
它读取多个 ADC 通道(0 到 ch_num-1),然后将每个 ADC 值粗略转换为 167 的百分比。
考虑我们通常进行百分比计算的方式为 (a/b)*100。换句话说,算出 a 是 b 的分数,然后乘以 100。但是对于整数数学,对于所有 < b 的值,初始除法将产生零,并且乘法不会影响它。
所以我们将(a/b)*100改写为(a*100)/b。现在除法发生在乘法之后,您将得到非零结果。
更具体地考虑这个例子
(100/167) * 100 应该变成 0.59 * 100 = 59%。但是使用整数数学你会得到 (100/167) * 100 = (0) * 100 = 0%。重写后你有 (100*100)/167 = (10000)/167 = 59.
这是整数数学的标准技巧。
学习阅读数据表是嵌入式编程的一项重要技能。
该芯片上的 ADC returns 一个 24 位有符号值。 datasheet 表示
The ADS1255/6 full-scale input voltage equals ±2VREF/PGA.
满刻度为 0x7FFFFF 或 8388607。
我相信 VRef 是 2.5V,代码使用 ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
将 PGA 设置为 1
因此 adc[i]
值 1 表示 1/0x7FFFFF
(2*2.5/1) 伏特或 0.596 微伏特。我们可以通过乘以 5000000 / 8388607 将原始读数转换为微伏。乘以一个很大的数字会溢出 32 位整数,所以让我们减少。
5000000 / 8388607 ~= 500/839 ~= 100/167
.
(乘以250/419可能精度会高一点而不会溢出)
我正在使用来自 Waveshare 网站的代码(与安装在 RPi3 上的 ADDA Waveshare 板一起使用):http://www.waveshare.com/wiki/File:High-Precision-AD-DA-Board-Code.7z
*********************************************************************************************************
* name: main
* function:
* parameter: NULL
* The return value: NULL
*********************************************************************************************************
*/
int main()
{
uint8_t id;
int32_t adc[8];
int32_t volt[8];
uint8_t i;
uint8_t ch_num;
int32_t iTemp;
uint8_t buf[3];
if (!bcm2835_init())
return 1;
bcm2835_spi_begin();
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST ); // The default
bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); // The default
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_1024); // The default
bcm2835_gpio_fsel(SPICS, BCM2835_GPIO_FSEL_OUTP);//
bcm2835_gpio_write(SPICS, HIGH);
bcm2835_gpio_fsel(DRDY, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_set_pud(DRDY, BCM2835_GPIO_PUD_UP);
//ADS1256_WriteReg(REG_MUX,0x01);
//ADS1256_WriteReg(REG_ADCON,0x20);
// ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
id = ADS1256_ReadChipID();
printf("\r\n");
printf("ID=\r\n");
if (id != 3)
{
printf("Error, ASD1256 Chip ID = 0x%d\r\n", (int)id);
}
else
{
printf("Ok, ASD1256 Chip ID = 0x%d\r\n", (int)id);
}
ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
ADS1256_StartScan(0);
ch_num = 8;
//if (ADS1256_Scan() == 0)
//{
//continue;
//}
while(1)
{
while((ADS1256_Scan() == 0));
for (i = 0; i < ch_num; i++)
{
adc[i] = ADS1256_GetAdc(i);
volt[i] = (adc[i] * 100) / 167;
}
for (i = 0; i < ch_num; i++)
{
buf[0] = ((uint32_t)adc[i] >> 16) & 0xFF;
buf[1] = ((uint32_t)adc[i] >> 8) & 0xFF;
buf[2] = ((uint32_t)adc[i] >> 0) & 0xFF;
printf("%d=%02X%02X%02X, %8ld", (int)i, (int)buf[0],
(int)buf[1], (int)buf[2], (long)adc[i]);
iTemp = volt[i]; /* uV */
if (iTemp < 0)
{
iTemp = -iTemp;
printf(" (-%ld.%03ld %03ld V) \r\n", iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000);
}
else
{
printf(" ( %ld.%03ld %03ld V) \r\n", iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000);
}
}
printf("[%dA", (int)ch_num);
bsp_DelayUS(100000);
}
bcm2835_spi_end();
bcm2835_close();
return 0;
}
请帮我弄清楚这段代码在 main() 中的作用:
for (i = 0; i < ch_num; i++)
{
adc[i] = ADS1256_GetAdc(i);
volt[i] = (adc[i] * 100) / 167;
}
常数(100和167)没有解释。他们在这个 'calibration' 中到底想做什么,这些常量取决于什么?
具体看这段代码(这似乎是实际问题
for (i = 0; i < ch_num; i++)
{
adc[i] = ADS1256_GetAdc(i);
volt[i] = (adc[i] * 100) / 167;
}
它读取多个 ADC 通道(0 到 ch_num-1),然后将每个 ADC 值粗略转换为 167 的百分比。
考虑我们通常进行百分比计算的方式为 (a/b)*100。换句话说,算出 a 是 b 的分数,然后乘以 100。但是对于整数数学,对于所有 < b 的值,初始除法将产生零,并且乘法不会影响它。
所以我们将(a/b)*100改写为(a*100)/b。现在除法发生在乘法之后,您将得到非零结果。
更具体地考虑这个例子
(100/167) * 100 应该变成 0.59 * 100 = 59%。但是使用整数数学你会得到 (100/167) * 100 = (0) * 100 = 0%。重写后你有 (100*100)/167 = (10000)/167 = 59.
这是整数数学的标准技巧。
学习阅读数据表是嵌入式编程的一项重要技能。
该芯片上的 ADC returns 一个 24 位有符号值。 datasheet 表示
The ADS1255/6 full-scale input voltage equals ±2VREF/PGA.
满刻度为 0x7FFFFF 或 8388607。
我相信 VRef 是 2.5V,代码使用 ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
因此 adc[i]
值 1 表示 1/0x7FFFFF
(2*2.5/1) 伏特或 0.596 微伏特。我们可以通过乘以 5000000 / 8388607 将原始读数转换为微伏。乘以一个很大的数字会溢出 32 位整数,所以让我们减少。
5000000 / 8388607 ~= 500/839 ~= 100/167
.
(乘以250/419可能精度会高一点而不会溢出)