Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Преобразование кода 24 битного ацп к виду напряжения
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
messenger
Преобразую код 24 битного ацп к виду напряжения. Т.к. переменная 32 битная сделал вот так.

cod_acp=0;

T3= (acp_MSB & 0b10000000)>>7; //выделим знак то есть Z0000000
if (T3==1)
{
cod_acp=0b00000000000000000000000011111111;
}

cod_acp = (cod_acp<<8) ^ acp_MSB ; // 00000000 00000000 Z00000000 хххххххх
cod_acp = (cod_acp<<8) ^ acp_Mid_Byte; // и так далее
cod_acp = (cod_acp<<8) ^ acp_LSB;

znachenie_acp=((cod_acp*5.0)/8388607.0)/64.0;//переводим в напряжение

подскажите,есть более быстрый способ? что бы не тратить машинное время.
Первое что пришло в голову
znachenie_acp=cod_acp*0.00000000931322685637794;
может есть варианты как еще выделить знак?
мне нужно минимальное вермя преобразования
mcheb
Цитата(messenger @ Dec 31 2015, 18:32) *
Преобразую код 24 битного ацп к виду напряжения.

А можно поинтересоваться,зачем это преобразование? Ну и попутно ещё всякие вопросы.
Alex11
Лучше сделайте union из 4 байтов и 32-битного слова, а дальше примерно так:
if(acp_MSB < 0) cod_acp.b3 = 0xff;
else cod_acp.b3 = 0;
cod_acp.b2 = acp_MSB;
cod_acp.b1 = acp_Mid;
cod_acp.b0 = acp.LSB;
znachenie_acp=cod_acp.w*...
здесь посчитайте руками на что нужно умножить один раз, хотя, может быть, оптимизатор и так отработает.
messenger
я в codevision пишу.
Поясните что есть "union" и как сделать что бы писать побайтно в переменную как здесь cod_acp.b2 = acp_MSB;
M_Andrey
Цитата(Alex11 @ Dec 31 2015, 21:41) *
if(acp_MSB < 0) cod_acp.b3 = 0xff;
else cod_acp.b3 = 0;


Здесь acp_MSB - байт, он беззнаковый и компилятор об этом предупредит.


Надо примерно так:

Код
</p><p>union    long2uch
{
    struct
        {
    struct    {    unsigned char l,ml,mh,h;    }    byte;
    signed long sl;
    }
} acp;

acp.byte.l  = 0;
acp.byte.ml = acp_LSB;
acp.byte.mh = acp_Mid_Byte;
acp.byte.h  = acp_MSB;

double znachenie_acp = acp.sl*(5.0/(2147483648*64));</p><p>


_pv
надо убрать плавающую запятую совсем и сделать просто
adcVolt = (adcCode * 149) >> 4;
результат получится в десятках наноВольт с точностью до 0.007%.

Цитата
Надо примерно так:
double znachenie_acp = acp.sl*(5.0/(2147483648*64));

вот так как раз не надо (особенно учитывая что это codevision), потому что (2147483648*64) хоть и стоит рядом с 5.0, думаю вполне может оказаться что будет сначала посчитано как int (который у АВР кстати вообще 16 битный, хотя опять же, как там у codevision - не уверен) а только потом преобразовано в double.
messenger
Цитата(_pv @ Jan 1 2016, 18:43) *
надо убрать плавающую запятую совсем и сделать просто
adcVolt = (adcCode * 149) >> 4;
результат получится в десятках наноВольт с точностью до 0.007%.


поясните пожалуйста для начинающих, не могу въехать
M_Andrey
Цитата(messenger @ Jan 1 2016, 20:21) *
поясните пожалуйста для начинающих, не могу въехать

Вопрос в том что вы хотите получить. Вам действительно нужна точность 24 бита?
Dog Pawlowa
Цитата(messenger @ Jan 1 2016, 20:21) *
поясните пожалуйста для начинающих, не могу въехать

Не сочтите мои слова как неуважение к новичкам, но учить язык программирования по ответам на форуме - неправильный, трудоемкий путь.
В любой книжке по С написано, что такое union, вы хотите тут подобрать людей, чтобы Вам книжки вслух читали?
_pv
Цитата(messenger @ Jan 1 2016, 23:21) *
поясните пожалуйста для начинающих, не могу въехать

ну величина 1 LSB ацп это 5.0В/(2^23)/64 = 9.31322574615479 нановольт (кстати, двойку не потеряли на знаковости? то есть весь входной диапазон АЦП +-5В=10В или 5В?)
а число 149/16 == это 9.3125 (отличается от 9.31322574615479 лишь на 0.007%), то есть умножив код на 149 целочисленно (32 разряда не переполнятся) и поделив на 16, (сдвинув на 4), получится целочисленный результат, но в нановольтах.

про десяток нановольт в прошлом сообщении - это я по запятой в калькуляторе промазал, в 10 раз
messenger
Очень интересный способ! И память можно здорово сэекономить.
Только я не пойму, раз мы говорим о целочисленном результате, то пллучается просто "9" а не 9.3125, и тогда погрешность 3.5%
И если вся шкала 8388608 (2^23), то для 16 битной переменной это переполенение, а если брать 32 битную, то какой в этом смысл?
_pv
Цитата(messenger @ Jan 2 2016, 13:30) *
Только я не пойму, раз мы говорим о целочисленном результате, то пллучается просто "9" а не 9.3125, и тогда погрешность 3.5%

если число например 1000000 умножить на 149, а потом поделить на 16, сколько получится, в целых числах?
messenger
9312500
_pv
Цитата(messenger @ Jan 2 2016, 16:09) *
9312500

то есть, таким образом, используя целочисленное умножение/деление, число умножили на 9.3125, а не на 9.

messenger
Что то я смысл не пойму. Беззнаковый int от 0 до 65535. Т.е мы уже вышли за пределы и нужна переменная типа long, которая по размеру такая же как и float.
Dog Pawlowa
Цитата(messenger @ Jan 2 2016, 22:39) *
Что то я смысл не пойму.

Вы забыли, про что спрашивали?
Напоминаю:
Цитата(messenger @ Dec 31 2015, 17:32) *
подскажите,есть более быстрый способ? что бы не тратить машинное время.
sigmaN
возможно это поможет понять предыдущие советы https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%...%82%D0%BE%D0%B9

http://x86asm.net/articles/fixed-point-ari...tic-and-tricks/
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.