Регистрация | Вход

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 2
  • 1
  • 2
  • »
Модератор форума: DAlexV, ivan_fd  
Приведение типов в Swordfish
AndrF Дата: Вс, 05.04.2015, 23:19  |                                                                                                                Сообщение # 1
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 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
ЯНДЕКС Дата: 05.04.2015
DAlexV Дата: Пн, 06.04.2015, 03:55  |                                                                                                                Сообщение # 2
Группа: Проверенные
Ранг:  Разобрался
Сообщений: 657
Репутация: 27   ±
Замечания:   ±
На сайте с 13.05.2008

Статус: Offline

AndrF, я конечно не фокусник что бы по 3 строчкам понять что хочется sad , но раз упоминается температура то предположу что нужно перевод к читабельному виду байт считанный из датчика температуры. 
Ну тогда наверное как то так. 
Код
' температура 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, " "))

Скажу по секрету такие фокусы smile проходят и с Word и LongWord. 
Успехов  wink


Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
AndrF Дата: Пн, 06.04.2015, 15:03  |                                                                                                                Сообщение # 3
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 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
Репутация: 27   ±
Замечания:   ±
На сайте с 13.05.2008

Статус: Offline

AndrF, прошу прощения. Горел на работе. Можно вопрос. А зачем использовать переменную Float если для чтения температуры достаточно 2 байт (Word) ?????
Когда искал примеры нашел пример на Си:
http://cxem.net/mc/mc316.php
Надеюсь он поможет.
А в остальном все верно сделано.

Успехов  wink


Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
AndrF Дата: Ср, 08.04.2015, 09:03  |                                                                                                                Сообщение # 5
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 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
Репутация: 27   ±
Замечания:   ±
На сайте с 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 схопатал горчичник  cool

при добавлении заремленой строчки 
fl = wTmp
'tStr= "t = " + FloatToStr( fl , 2) + "їC"

Успехов  wink
Прикрепления: 1406917.jpg (16.9 Kb) · Convert.rar (39.7 Kb)


Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
AndrF Дата: Ср, 08.04.2015, 12:33  |                                                                                                                Сообщение # 7
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 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
Репутация: 27   ±
Замечания:   ±
На сайте с 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
Репутация: 3   ±
Замечания:   ±
На сайте с 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
Репутация: 27   ±
Замечания:   ±
На сайте с 13.05.2008

Статус: Offline

Print( FloatToStr( fl byref float / $10 , 2))
????
Точное написание не помню.
а если работает тогда что не устраивает ????


Будьте оригинальны-не повторяйте чужих ошибок ! Рыба сдохла. Теперь STM32(TS)+C#(VS).Старею :)
AndrF Дата: Чт, 09.04.2015, 11:52  |                                                                                                                Сообщение # 11
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 03.02.2012

Статус: Offline

Цитата DAlexV ()
а если работает тогда что не устраивает ????

Собственно - см первый вопрос или тему ветки - меня всего лишь интересовало можно ли привести типы в Swordfish... То есть можно ли подсказать компилятору, чтобы он переменную Byte сразу рассматривал как ShortInt. Все же у Swordfish достаточно много недокументированного...

Добавлено (09.04.2015, 11:52)
---------------------------------------------
Кстати, возвращаясь к температуре - сейчас глянул - в Протоне подобным образом сделать не удастся - там нет типа Integer. То есть код хоть как выйдет посложнее...

ЯНДЕКС Дата: 09.04.2015
ivan_fd Дата: Пт, 10.04.2015, 09:33  |                                                                                                                Сообщение # 12
Группа: Модераторы
Ранг:  Специалист
Сообщений: 894
Репутация: 124   ±
Замечания:   ±
На сайте с 12.01.2009

Статус: Offline

Цитата AndrF ()
Кстати, возвращаясь к температуре - сейчас глянул - в Протоне подобным образом сделать не удастся - там нет типа Integer. То есть код хоть как выйдет посложнее...

Названия такого нету "Integer", но по размеру то есть. Какие сложности?
AndrF Дата: Пт, 10.04.2015, 11:59  |                                                                                                                Сообщение # 13
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 03.02.2012

Статус: Offline

Цитата ivan_fd ()
Названия такого нету "Integer", но по размеру то есть. Какие сложности?

Дело не столько в размере (аналог по размеру - Word), а в том что Integer имеет бит знака, а Word нет. Потому для вывода правильного отрицательного значения в Протоне по определению требуется больше танцев.

Разве что в Протоне можно использовать старшие байты DWord, но там делить придется на 16777216.
ivan_fd Дата: Пт, 10.04.2015, 12:56  |                                                                                                                Сообщение # 14
Группа: Модераторы
Ранг:  Специалист
Сообщений: 894
Репутация: 124   ±
Замечания:   ±
На сайте с 12.01.2009

Статус: Offline

В Протоне есть тип Sword - то есть Signed Word. Читайте мануал.
AndrF Дата: Ср, 13.05.2015, 17:22  |                                                                                                                Сообщение # 15
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 145
Репутация: 3   ±
Замечания:   ±
На сайте с 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
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск: