Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > Как состыковать типы float в контроллере и на ПК. |
Автор: Курсант 11.8.2015, 16:53 |
Всем доброго времени суток! У меня следующая проблема: я отправляю из микроконтроллера по UART данные в формате float, получаю их на ПК программой, написанной на VC++. Получаю эти 4 байта я в массив байтов, и привожу их к типу float (на самом деле использую union, ну это не принципиально). Проблема в том, что данные, которые видит ПК, не такие, какими их видит контроллер. Т.е. если для контроллера это 27,24324, то для ПК это оказывается 11,534534. Примерно так. При этом есть ещё одна программа, написанная коллегой на Java, которая также принимает 4 байта, и приводит их к типу float функцией BytesToFloat, или чем-то таким. И программа на Java видит переменные такими, какими их видит контроллер. Но Java выполняется Java-машиной, и как там реализован тип float - не ясно... Может быть кто-нибудь сталкивался с похожими проблемами, знает в какую сторону копать? Спасибо за внимание... |
Автор: xvr 11.8.2015, 17:17 |
Копать в сторону совпадения Endianess на МК и ПС, а так же в сторону формата этого самого флоата - совпадают ли они. Если да, то скорее всего это будет IEEE 754, а если не IEEE - то скорее всего не совпадут ![]() |
Автор: Курсант 11.8.2015, 21:16 |
Это я и сам понял ![]() Кстати, получается, что учитывая ядро моего контроллера (Cortex-M3, а иногда и Cortex-M0) формат флота контроллера нужно узнавать не в документации на контроллер, а в документации на компилятор? |
Автор: ФедосеевПавел 11.8.2015, 22:38 |
Не знаком с С, просто предполагаю, что float - обобщённый тип данных с плавающей запятой, для корректной работы на ПК желательно указать конкретно single или double, точнее single. А потом уточнить порядок байт. |
Автор: Курсант 12.8.2015, 11:31 | ||||
Спасибо за ответ. Я не знаком с VB, но если не ошибаюсь, в концепциях VB тип float является обобщённым, и нужно указывать точность - single или double. В языке Си для двойной точности предназначен тип double, а для единичной - float. Добавлено через 11 минут и 26 секунд Проблема так и не решилась. Поэтому начну вдаваться в детали. Вот сюда я записываю свои байты:
Соответственно, я принимаю данные в DataField.Byte1, DataField.Byte2, DataField.Byte3 и DataField.Byte4, а затем вычитываю их как DataField.AsFloat; При этом принятые значения отличаются примерно в два с половиной раза от тех, которые я отправлял. Т.е. Big-Endian - Little-Endian соответствие соблюдено (я пробовал менять байты местами, получался какой-то мусор вместо тех данных, которые я отправлял). Из всего вышеизложенного я сделал вывод, что проблема - в формате данных float, а именно в структуре мантиссы и показателя степени, знака и их сдвигов-размеров-положения. Проблема усугубляется тем, что в микроконтроллере я имею soft-float, т.е. тип float ненастоящий, программируется компилятором используя целочисленную арифметику контроллера. И как он там устроен - большой вопрос... Фактически, он устроен отличным от компьютера образом. Придётся, видимо, делать самую неприятную часть работы - брать 16-ричное значение, и пытаться получить из него отправляемое значение, воссоздавая логику компилятора по работе с float. |
Автор: Курсант 12.8.2015, 14:41 | ||
arm-gcc В ПК и в компиляторе, судя по всему, всё соответствует Проблема, похоже, в том, что я теряю некоторые биты при приёме через COM-порт. Использую я для этого класс serialPort из VisualC++. Читаю данные в строку с помощью метода serialPort->ReadLine; Проблема была в методе ReadLine объекта serialPort Судя по всему метод предназначен для вычитывания текстовых строк из COM-порта. Поэтому нетипичные для текстовых строк байты метод "коверкает". Когда я стал вычитывать байты методом ReadByte, все данные стали отображаться нормально. |