Приведение типов в Swordfish
|
|
AndrF |
Дата: Вс, 05.04.2015, 23:19 | Сообщение # 1 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Собственно как привести данные к нужному типу?
Например, строка с температурой у меня формируется следующим образом:
Код "t = " + TrimLeft( DecToStr( wTemp.Byte0, 3, " ")) + "." + TrimLeft( DecToStr( wTemp.Byte0, 2, " ")) Но вот каким образом мне указать что байт wTemp.Byte0 содержит данные в формате ShortInt?
Сейчас приходится извращаться, используя промежуточную переменную типа ShortInt:
Код Dim si As ShortInt .... si = wTemp.Byte0 "t = " + TrimLeft( DecToStr( si, 3, " ")) + "." + TrimLeft( DecToStr( wTemp.Byte0, 2, " ")) В общем, как тут сделать по правильному?
Сообщение отредактировал
AndrF - Вс, 05.04.2015, 23:20
|
|
|
|
DAlexV |
Дата: Пн, 06.04.2015, 03:55 | Сообщение # 2 |
Группа:
Проверенные
Ранг:
Разобрался
Сообщений:
657
Замечания:
±
На сайте с 13.05.2008
Статус:
Offline
|
AndrF, я конечно не фокусник что бы по 3 строчкам понять что хочется , но раз упоминается температура то предположу что нужно перевод к читабельному виду байт считанный из датчика температуры. Ну тогда наверное как то так. Код ' температура 13.4 С wtemp=134 ' челочисленное деление 'остаток от деления tStr="t = " + TrimLeft( DecToStr((wtemp / 10), 3, " ")) + "." + TrimLeft( DecToStr( wtemp mod 10, 3, " "))
' температура 1.34 С
tStr="t = " + TrimLeft( DecToStr((wtemp / 100), 3, " ")) + "." + TrimLeft( DecToStr( wtemp mod 100, 3, " ")) Скажу по секрету такие фокусы проходят и с Word и LongWord. Успехов
Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
|
|
|
|
AndrF |
Дата: Пн, 06.04.2015, 15:03 | Сообщение # 3 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата DAlexV ( ) AndrF, я конечно не фокусник что бы по 3 строчкам понять что хочется , но раз упоминается температура то предположу что нужно перевод к читабельному виду байт считанный из датчика температуры. Мне нужно объявить компилятору что в байте wTemp.Byte0 данные находятся в формате ShortInt.
Во втором своем примерчике я для этого использую промежуточную переменную, но хотелось бы обойтись без нее. А так мой код работает без проблем - байты содержат данные уже в нужном виде, только первый из них со знаком...
В общем, для чего я все затевал - сделал часики на DS3231 - вот пара функций работы с этим чипом:
Код ' Считаем дату, время и температуру из DS3231 Public Sub RTCRead(ByRef lwDate As LongWord, ByRef lwTime As LongWord, ByRef iTemp As Integer) Dim i As Byte
I2CStart I2CWriteByte ( DS3231_I2C_Address) I2CWriteByte ( $0) I2CRestart I2CWriteByte ( DS3231_I2C_Address + 1)
' Загрузим время lwTime.Byte0 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' секунды lwTime.Byte1 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' минуты lwTime.Byte2 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' часы lwTime.Byte3 = 0 ' Учтем формат времени If lwTime.Byte2.Booleans(6) Then lwTime.Byte2 = lwTime.Byte2 And $1F End If
' Загрузим дату lwDate.Byte0 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' день недели lwDate.Byte1 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' день месяца lwDate.Byte2 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' месяц lwDate.Byte3 = BcdToDec( I2CReadByte( I2C_ACKNOWLEDGE)) ' год
' Пропустим лишнее (будильники, установки) For i = 7 To $10 I2CReadByte( I2C_ACKNOWLEDGE) Next
' Загрузим температуру iTemp.Byte1 = I2CReadByte( I2C_ACKNOWLEDGE) iTemp.Byte0 = I2CReadByte( I2C_NOT_ACKNOWLEDGE)
Acknowledge( I2C_ACKNOWLEDGE) I2CStop End Sub
' Сохраним дату и время в DS3231 Public Sub RTCWrite(ByRef lwDate As LongWord, ByRef lwTime As LongWord) I2CStart I2CWriteByte ( DS3231_I2C_Address) I2CWriteByte ( $0)
' Сохраним время I2CWriteByte( lwTime.Byte0) ' секунды I2CWriteByte( lwTime.Byte1) ' минуты I2CWriteByte( lwTime.Byte2) ' часы
' Сохраним дату I2CWriteByte( lwDate.Byte0) ' день недели I2CWriteByte( lwDate.Byte1) ' день месяца I2CWriteByte( lwDate.Byte2) ' месяц I2CWriteByte( lwDate.Byte3) ' год
Acknowledge( I2C_NOT_ACKNOWLEDGE) I2CStop End Sub
А вот как на текущий момент сделал отображение температуры:
Код Dim lwDate, lwTime As LongWord, iTemp As Integer
RTCRead(lwDate, lwTime, iTemp)
' Вывод температуры. Только положительные значения - при отрицательной ' температуре возможна ошибка в дробной части! OledPrint( 57, 7, "t = " + DecToStr( iTemp / $100) + "." + DecToStr(( iTemp.Byte0 >> 6) * 25, 2) + "їC") ' Если нужен вывод отрицательной температуры с дробной частью, то, скорей всего, правильней будет: ' Dim fl As Float ' fl = iTemp ' OledPrint( 57, 6, "t = " + FloatToStr( fl / $100 , 2) + "їC") Единственное в чем до сих пор не уверен - это в дробной части при отрицательных температурах - нет 100% понятия что DS3231 выдает в LSB. Есть подозрение что для вывода отрицательных значений с дробной частью лучше использовать закомментированные строки. Проверить на практике мне затруднительно - надо помещать DS3231 в холодильник. А это влом, так как приборчик у меня будет использоваться в помещении.
Кстати, в качестве резервного питания для часов я использовал не батарейку, а ионистор на 1,5 Фарады. Две недели на нем часы выжили...
Сообщение отредактировал
AndrF - Пн, 06.04.2015, 15:09
|
|
|
|
DAlexV |
Дата: Вт, 07.04.2015, 22:26 | Сообщение # 4 |
Группа:
Проверенные
Ранг:
Разобрался
Сообщений:
657
Замечания:
±
На сайте с 13.05.2008
Статус:
Offline
|
AndrF, прошу прощения. Горел на работе. Можно вопрос. А зачем использовать переменную Float если для чтения температуры достаточно 2 байт (Word) ????? Когда искал примеры нашел пример на Си: http://cxem.net/mc/mc316.php Надеюсь он поможет. А в остальном все верно сделано.
Успехов
Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
|
|
|
|
AndrF |
Дата: Ср, 08.04.2015, 09:03 | Сообщение # 5 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата DAlexV ( ) AndrF, прошу прощения. Горел на работе. Можно вопрос. А зачем использовать переменную Float если для чтения температуры достаточно 2 байт (Word) ????? Вообще-то не Word. а Integer, так как температура может быть отрицательной. В Integer тоже два байта, но старший бит отвечает за знак. В Integer я и помещаю температуру в своем примере выше.
Цитата Когда искал примеры нашел пример на Си: Подобные примеры я видел - IMHO в них люди порют одну и ту же ошибку - забывают про знак температуры. С одной стороны это не критично, если устройство используется только в квартире, где отрицательной температуры нет по определению, с другой стороны - все же ошибка.
Два байта температуры DS3231 содержат температуру именно в формате Integer. Смотрите сами:
$0001 - это + 0.25 градуса (после деления на $100) $1111 - это - 0.25 градуса (после деления на $100)
Вариант по вашей ссылке для отрицательной температуры выведет выведет ошибочное значение - не так ли?
Мой вариант с Float (где Float используется для вывода, а не чтения) корректно отработает всегда, хотя может и потребует чуть больше тактиков контроллера, но это совсем не критично. Да и проще сам код смотрится...
Eсли не нужна дробная часть, то проще использовать Integer, но иногда интересно посмотреть относительное изменение температуры - тут дробная часть и помогает.
Сообщение отредактировал
AndrF - Ср, 08.04.2015, 09:27
|
|
|
|
DAlexV |
Дата: Ср, 08.04.2015, 10:42 | Сообщение # 6 |
Группа:
Проверенные
Ранг:
Разобрался
Сообщений:
657
Замечания:
±
На сайте с 13.05.2008
Статус:
Offline
|
Цитата AndrF ( ) Подобные примеры я видел - IMHO в них люди порют одну и ту же ошибку - забывают про знак температуры. С одной стороны это не критично, если устройство используется только в квартире, где отрицательной температуры нет по определению, с другой стороны - все же ошибка. Ну если я правильно раскурил мануал за знак температуры отвечает 7 бит регистра $11. Тогда решается так:
Код dim wTMP as word
' -25.25 гр wtmp.byte1=%10011001 wtmp.byte0=%01000000
' температуре возможна ошибка в дробной части! tStr= "t = " + DecToStr( wTmp / $100) + "." + DecToStr(( wTmp.Byte0 >> 6) * 25, 2) + "їC"
if wtmp.15=1 then tStr= "t = -" + DecToStr( wTmp.byte1 and %01111111) + "." + DecToStr(( wTmp.Byte0 >> 6) * 25, 2) + "їC" else tStr= "t = +" + DecToStr( wTmp.byte1) + "." + DecToStr(( wTmp.Byte0 >> 6) * 25, 2) + "їC" end if Что же касаемо Float то при моделировании на 1320 схопатал горчичник при добавлении заремленой строчки fl = wTmp 'tStr= "t = " + FloatToStr( fl , 2) + "їC"
Успехов
Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
|
|
|
|
AndrF |
Дата: Ср, 08.04.2015, 12:33 | Сообщение # 7 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата DAlexV ( ) Ну если я правильно раскурил мануал за знак температуры отвечает 7 бит регистра $11. Да.
Но вот ваш код ниже для отрицательных чисел работать не будет!
Прежде всего потому что отрицательные числа возвращаются [url=https://ru.wikipedia.org/wiki/Дополнительный_код_(представление_числа)]в дополнительном коде[/url].
Для понимания - можете запустить в VB6 или Access следующие строки и поиграться меняя их значения:
Код Dim i As Integer, j As Integer i = 26.25 * 256 ' Это значение возвращает DS3231 Debug.Print "i = $" & Hex(i) & " = " & CSng(i) / 256
j = -26.25 * 256 ' Это значение возвращает DS3231 Debug.Print "j = $" & Hex(j) & " = " & CSng(j) / 256
j = &HFFC0 ' Это значение возвращает DS3231 Debug.Print "j = $" & Hex(j) & " = " & CSng(j) / 256
j = &HFF00 ' Это значение возвращает DS3231 Debug.Print "j = $" & Hex(j) & " = " & CSng(j) / 256
Ну и в Swordfish работает аналогично.
Цитата DAlexV ( ) Что же касаемо Float то при моделировании на 1320 схопатал горчичник Тут сказать не могу - у меня проблем нет.
Кстати, можно посмотреть описание DS18B20 - там тоже температура выводится аналогично, только делить надо будет не на 256, а на 16.
Сообщение отредактировал
AndrF - Ср, 08.04.2015, 12:38
|
|
|
|
DAlexV |
Дата: Чт, 09.04.2015, 09:52 | Сообщение # 8 |
Группа:
Проверенные
Ранг:
Разобрался
Сообщений:
657
Замечания:
±
На сайте с 13.05.2008
Статус:
Offline
|
Цитата AndrF ( ) Прежде всего потому что отрицательные числа возвращаются [url=https://ru.wikipedia.org/wiki/Дополнительный_код_(представление_числа)]в дополнительном коде[/url]. Упс. Забыл совсем. Каюсь лет 5 не работал с датчиками темепературы. Думал наконец то привели значения к нормальному виду, а нет. тогда такой вариант: iКод f wtmp.15=1 then tStr= "t = -" + DecToStr( (Not wTmp.byte1) and %01111111) + "." + DecToStr(( (Not wTmp.Byte0) >> 6) * 25, 2) + "їC" Единственное что скорее всего будет ошибка на 0.25 градуса если верить Цитата AndrF ( ) $0001 - это + 0.25 градуса (после деления на $100) Нужно еще подумать малость. Цитата AndrF ( ) Кстати, можно посмотреть описание DS18B20 - там тоже температура выводится аналогично, только делить надо будет не на 256, а на 16. А если попробовать переработать преобразование из библы на 18B20 ???? Код то открытый.
Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
|
|
|
|
AndrF |
Дата: Чт, 09.04.2015, 10:21 | Сообщение # 9 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата DAlexV ( ) Думал наконец то привели значения к нормальному виду, К какому это? Так самый удобный вид был и есть! Данные в двух байтах в формате Integer - проще и нормальней некуда.
Цитата DAlexV ( ) Нужно еще подумать малость. Да все уже придумано - помещаем считанное Integer в Float, делим на величину сдвига и уже имеем значение температуры, которое и выводим. Все!
Код fl = ITemp ' Где iTemp число типа Integer, полученное от DS3231 Print( FloatToStr( fl / $100 , 2)) И все!
Цитата DAlexV ( ) А если попробовать переработать преобразование из библы на 18B20 ???? Код то открытый. C DS18B20 тоже решается примитивно:
Код fl = ITemp ' Где iTemp число типа Integer, полученное от DS18B20 Print( FloatToStr( fl / $10 , 2)) Ну а все навороты что делают в примерах - от банального непонимания...
P.S. Сейчас глянул пример от самого Swordfish для DS18B20 - там тоже забыли об отрицательных температурах...
Сообщение отредактировал
AndrF - Чт, 09.04.2015, 10:51
|
|
|
|
DAlexV |
Дата: Чт, 09.04.2015, 11:15 | Сообщение # 10 |
Группа:
Проверенные
Ранг:
Разобрался
Сообщений:
657
Замечания:
±
На сайте с 13.05.2008
Статус:
Offline
|
Print( FloatToStr( fl byref float / $10 , 2)) ???? Точное написание не помню. а если работает тогда что не устраивает ????
Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
|
|
|
|
AndrF |
Дата: Чт, 09.04.2015, 11:52 | Сообщение # 11 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата DAlexV ( ) а если работает тогда что не устраивает ???? Собственно - см первый вопрос или тему ветки - меня всего лишь интересовало можно ли привести типы в Swordfish... То есть можно ли подсказать компилятору, чтобы он переменную Byte сразу рассматривал как ShortInt. Все же у Swordfish достаточно много недокументированного...Добавлено (09.04.2015, 11:52) --------------------------------------------- Кстати, возвращаясь к температуре - сейчас глянул - в Протоне подобным образом сделать не удастся - там нет типа Integer. То есть код хоть как выйдет посложнее...
|
|
|
|
ivan_fd |
Дата: Пт, 10.04.2015, 09:33 | Сообщение # 12 |
Группа:
Модераторы
Ранг:
Специалист
Сообщений:
894
Замечания:
±
На сайте с 12.01.2009
Статус:
Offline
|
Цитата AndrF ( ) Кстати, возвращаясь к температуре - сейчас глянул - в Протоне подобным образом сделать не удастся - там нет типа Integer. То есть код хоть как выйдет посложнее... Названия такого нету "Integer", но по размеру то есть. Какие сложности?
|
|
|
|
AndrF |
Дата: Пт, 10.04.2015, 11:59 | Сообщение # 13 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата ivan_fd ( ) Названия такого нету "Integer", но по размеру то есть. Какие сложности? Дело не столько в размере (аналог по размеру - Word), а в том что Integer имеет бит знака, а Word нет. Потому для вывода правильного отрицательного значения в Протоне по определению требуется больше танцев.
Разве что в Протоне можно использовать старшие байты DWord, но там делить придется на 16777216.
|
|
|
|
ivan_fd |
Дата: Пт, 10.04.2015, 12:56 | Сообщение # 14 |
Группа:
Модераторы
Ранг:
Специалист
Сообщений:
894
Замечания:
±
На сайте с 12.01.2009
Статус:
Offline
|
В Протоне есть тип Sword - то есть Signed Word. Читайте мануал.
|
|
|
|
AndrF |
Дата: Ср, 13.05.2015, 17:22 | Сообщение # 15 |
Группа:
Проверенные
Ранг:
Продвинутый
Сообщений:
145
Замечания:
±
На сайте с 03.02.2012
Статус:
Offline
|
Цитата ivan_fd ( ) В Протоне есть тип Sword - то есть Signed Word. Читайте мануал. Читать мануал по протону для меня затруднительно - сам Протон я давно снес за полной ненадобностью. А здесь упоминания SWord не обнаружил. Впрочем, если такой тип есть, то уже хорошо.Добавлено (13.05.2015, 17:22) --------------------------------------------- Возвращаясь к приведению типов - все очень просто - вот пример приведения переменной iTemp к типу Float:
Код OpedPrint( FloatToStr( Float( iTemp) / $100 , 2))
Сообщение отредактировал
AndrF - Пт, 10.04.2015, 13:01
|
|
|
|