Как правильно сделать приведение типов в Си?

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 10
Зарегистрирован: Пт май 01, 2020 13:49:39

Сообщение lonelywalker »

Здравствуйте.
Делаю на микроконтроллере AVR частотомер.
Как правильно привести тип результата, для отображения на экране или передаче через UART.
У меня выходят вообще неправильные результаты именно из-за преобразования.
Например 234 или 000000. А должно быть 1024 с желательно с дробной частью (или без), хотя бы какого то результата.
По ниже приведенной формуле не работает. Получаются нули, а должно получиться 10004,03085khz
или хотя бы 10004 или 100040308

mesurImp = 10171;
baseImp = 16267043;
unsigned long result = (16000000UL*(unsigned long)mesurImp)/baseImp;


Как получить правильный результат ?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

Ну, наверное, следует просто на калькуляторе проверить разрядность произведения и тут же обнаружить, что она равна 40. То есть 32-разрядный тип тут никак не подходит. Нужен 64-разрядный.
Реклама
Родился
Сообщения: 10
Зарегистрирован: Пт май 01, 2020 13:49:39

Сообщение lonelywalker »

Спасибо. А как проверить разрядность на калькуляторе ?
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="lonelywalker",url="/forum/viewtopic.php?p=3891559#p3891559"]А как проверить разрядность на калькуляторе ?[/uquote]
А как ты с такими знаниями частотомер делаешь? В простейшем случае достаточно проверить помешается ли результат умножения в 32 бита, т.е. не превышает ли он 2^32.
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

[uquote="lonelywalker",url="/forum/viewtopic.php?p=3891559#p3891559"]Спасибо. А как проверить разрядность на калькуляторе ?[/uquote]
Ну вообще нужен логарифм по основанию 2. Но в калькуляторе виндовом проще перевести в двоичный или шеснадцатиричный вид, да увидеть кол-во разрядов.

Добавлено after 11 minutes 46 seconds:
с желательно с дробной частью

Код: Выделить всё

double result = (16000000.0*mesurImp)/baseImp;
(или без)

Код: Выделить всё

uint16_t result = ((uint64_t)16000000*mesurImp)/baseImp;
Реклама
Родился
Сообщения: 10
Зарегистрирован: Пт май 01, 2020 13:49:39

Сообщение lonelywalker »

Поставил разные типы переменных.
Пробовал по разному выводить в usart.

Вот так выводит в usart, но обрезает дробную часть

Код: Выделить всё

unsigned long  result = (double)(16000000UL*(float)mesurImp)/(float)baseImp;
USART_sendString(buff,16);
Так выводит только знак вопроса "?"

Код: Выделить всё

double result = (16000000UL*(double)mesurImp)/(double)baseImp;
USART_sendString(buff,16);
Хотя в codeblocks пробовал все работает, а в AVR GCC нет.
и unsigned long long то же самое

Код: Выделить всё

unsigned long long result = (unsigned long  long)(16000000UL*(float)mesurImp)/(float)baseImp;
sprintf(buff, "%16llu",freq2);
Реклама
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Ваша функция USART_sendString просто не умеет выводить float/double. А в codeblocks вы используете стандартный printf. Если что, в avr-gcc он тоже есть.
Родился
Сообщения: 10
Зарегистрирован: Пт май 01, 2020 13:49:39

Сообщение lonelywalker »

Нашел решение.
Для Atmel studio надо было изменить настройки компилятора.
поставить галочку vprintf library(-Wl,-u,vfprintf).
И установить флаг -lprintf_flt
Подробнее здесь
https://startingelectronics.org/article ... -studio-7/
Нашел транзистор. Понюхал.
Сообщения: 156
Зарегистрирован: Вс сен 06, 2020 16:06:10

Сообщение iddqd »

[uquote="lonelywalker",url="/forum/viewtopic.php?p=3891559#p3891559"]Спасибо. А как проверить разрядность на калькуляторе ?[/uquote] Даже и без калькулятора: 16 миллионов - примерно 24 бита (2:24 = 16777216, ака 16 мегабайтов). Значит остается не более 8 битов сверху на умножение, т.е. порядка 256. Если взять больше - тогда это уже не 32 бита.
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="lonelywalker",url="/forum/viewtopic.php?p=3891654#p3891654"]и unsigned long long то же самое

Код: Выделить всё

unsigned long long result = (unsigned long  long)(16000000UL*(float)mesurImp)/(float)baseImp;
sprintf(buff, "%16llu",freq2);
[/uquote]
Зачем вам флоат, особенно если вы его все равно приводите к целому и дробной части вам не видать как своих ушей? Если делаете в 64 разрядах, то флоат без нужды. Только лишние вычислительные затраты на перевод во флоат и обратно. Для дробной части нужно использовать фикспойнт (fixed-point). То есть домножить числитель на дробное смещение (скажем, для получения трех знаков после запятой в децимальном формате на 1000).
Ответить

Вернуться в «AVR»