Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.68/121: Рейтинг темы: голосов - 121, средняя оценка - 4.68
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739

Как передать по modbus float

08.06.2016, 15:36. Показов 25183. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Если я хочу передать по modbus float я разбиваю его на 4 байта и формирую 2 регистра, код прикладываю:
C++
1
2
3
4
5
6
7
8
9
10
void float_to_int(float float_value, uint16_t adress)
{
    char float_bytes[sizeof(float)];
    int i;
 
    for (i = 0; i < sizeof(float); ++i)
        float_bytes[i] = *((char *)&float_value + i);
    res_table.regs[adress] = (float_bytes[3] << 8) + float_bytes[2];
    res_table.regs[adress+1] = (float_bytes[1] << 8) + float_bytes[0];
}
А как мне собрать флоат обратно из двух регистров?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.06.2016, 15:36
Ответы с готовыми решениями:

Как передать переменную float в i2s hal
есть проект под stm32f4xx float fl_sample, fr_sample; Synth_Process(&amp;fl_sample, &amp;fr_sample); while (1){ for(uint16_t i=0;...

Как переслать float по modbus?
Пытаюсь прочитать число типа float по modbus длиной в 2 байта, в ответ приходит то, что на картинке. Подскажите как эти байты привести к...

Modbus RTU (точно float)
Добрый день всем. Возможно мне помогут здесь. Перерыл очень много всего, возможно плохо рыл. Реализую небольшую ПУ для управления...

23
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
08.06.2016, 18:49
_SayHelli, один вопрос одна тема
правила п 4.4
На каждый вопрос создавайте по одной теме - это помогает избежать путаницы в ответах и облегчает поиск.
Добавлено через 4 минуты
Цитата Сообщение от _SayHelli Посмотреть сообщение
я разбиваю его на 4 байта
воспользуйся объединением
например так
C
1
2
3
4
5
union FloatChar
{
float fl;
char ch[4];
}
2
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
08.06.2016, 19:49  [ТС]
ValeryS, то есть я регистры снова бью на байты а потом складываю их в массив? а не ch[3]? ведь там 4 байта вроде как
0
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
08.06.2016, 20:41
Цитата Сообщение от _SayHelli Посмотреть сообщение
то есть я регистры снова бью на байты а потом складываю их в массив?
да
можешь сразу в объединение внести переменную типа регистр, я, к сожалению не знаю что это такое
C
1
2
3
4
5
6
union FloatChar
{
float fl;
regs rg[2]; //подправь как нужно
char ch[4];
}
Цитата Сообщение от _SayHelli Посмотреть сообщение
а не ch[3]? ведь там 4 байта вроде как
не понял вопроса
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
08.06.2016, 20:59  [ТС]
ValeryS, float - > 4 байта, ячейки массива итовые -> 2 байта. чтобы поместить туда float, я разбиваю его на 4 байта, объединяю их в инт и кладу в регистр по 2 байта.
C++
1
char ch[4];
Как я понял это и есть массив под эти 4 байта. Но разве при таком обозначении в массиве не будет содержаться 5 ячеек?
C++
1
2
3
4
5
6
union FloatChar
{
float fl;
regs rg[2]; //подправь как нужно
char ch[4];
}
одной переменной float соответствует 2 регистра массива с определенными адресами то есть мне туда засунуть две свои переменные с необходимыми адресами?
1
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
08.06.2016, 21:21
Лучший ответ Сообщение было отмечено _SayHello как решение

Решение

Цитата Сообщение от _SayHelli Посмотреть сообщение
Как я понял это и есть массив под эти 4 байта.
да
Цитата Сообщение от _SayHelli Посмотреть сообщение
Но разве при таком обозначении в массиве не будет содержаться 5 ячеек?
нет конечно при объявлении число в скобках это количество элементов, а при обращении индекс
C
1
2
char ch[4];// объявление массива на 4 элемента
ch[4]=0;// обращение к пятому элементу, коего нет
Цитата Сообщение от _SayHelli Посмотреть сообщение
одной переменной float соответствует 2 регистра массива с определенными адресами то есть мне туда засунуть две свои переменные с необходимыми адресами?
я не знаю что такое регистры, посему советовать не могу, попробуй
1
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
09.06.2016, 11:33  [ТС]
ValeryS, спасибо замутил через union заработало)
0
0 / 0 / 0
Регистрация: 18.07.2019
Сообщений: 7
18.07.2019, 15:09
напишите пожалуйста подробно, ка Вы сделали обратное преобразование в float?
У меня есть 2 регистра принятых мастером с преобразованым float в байты, как Вы указали вначале тымы.
Эти регистры в программе Ардуино(С++) называются au16data[0] и au16data[1], у них тип uint16_t
Как правильно написать это объединение для моих регистров?

C
1
2
3
4
5
6
 union FloatChar
{
float fl;
regs rg[2]; //подправь как нужно
char ch[4];
}
0
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
18.07.2019, 15:25
Цитата Сообщение от blokerun Посмотреть сообщение
напишите пожалуйста подробно, ка Вы сделали обратное преобразование в float?
в том то и прелесть объединений, что никаких преобразований не нужно
1
0 / 0 / 0
Регистрация: 18.07.2019
Сообщений: 7
18.07.2019, 15:43
помогите пожалуйста правильно записать эту конструкцию.

У меня так:
-обьявление переменных
C
1
2
3
uint16_t au16data[2];
uint8_t u8state;
float t;
*
*код программы, где принимаются данные и записываются в два регистра au16data
*
C
1
2
3
4
5
6
7
8
union 
     {
      float t;
      uint16_t  au16data[2]; 
      char ch[4];
     } FloatChar;
 
    Serial.println(t);
- в терминале выдает нулевое значение перменной t (0.00)

Что я не так сделал?
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
18.07.2019, 15:54
Я так понимаю, что после обращения к прибору по Modbus имеется результат в виде массива
C
uint_16 au16data[100];
Нужно заполнить переменную типа float. Делайте преобразование типов и присваивайте
C
1
single x=(FloatChar) au16data[0];
или сразу как-то обрабатывайте.
Единственно, уточняйте порядок байт в принятом числе. Мне доводилось для принятых двух слов обменивать порядок следования и пословно и побайтно. Это есть в документации на прибор. Например, для ОВЕН ТРМ212 после приёма числа потребуется поменять порядок с 0 1 2 3 на 3 2 1 0. Для ВКТ5 я менял только слова: с 0 1 2 3 на 2 3 0 1.
Не знаю только, как это на C показать.

Добавлено через 10 минут
Вернее,
C
1
single x=(FloatChar) (au16data[0]).t;
1
0 / 0 / 0
Регистрация: 18.07.2019
Сообщений: 7
18.07.2019, 16:08
а что делать со вторым регистром au16data[1] ?
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
18.07.2019, 16:20
Он уже учёлся в приведении типов (typecast). Элементы au16data[0] и au16data[1] занимают последовательные ячейки памяти.

Кроме union можно использовать typecast и адресную арифметику, как в примере Как сохранить float в переменной типа char?

Добавлено через 2 минуты
У вас есть эталонные корректные значения au16data и t?
Приведите их.
0
0 / 0 / 0
Регистрация: 18.07.2019
Сообщений: 7
18.07.2019, 16:29
а что такое single?
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
18.07.2019, 18:33
это float, только в других языках программирования. Только размер типа float зависит от компилятора, а single - однозначно 32 бита. Плохо знаю C/C++ и путаю ключевые слова из других языков.
Вам главное смысл уловить.

Добавлено через 50 минут
Набрал в gcc для компьютера тестовую программку. Рассмотрел четыре случая:
1. чудной с использованием union
2. принят массив с правильным расположением байт
3. принят массив с обратным расположением слов
4. принят массив с обратным расположением байт
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
 
union Convert32
{
    float fFloat;
    int32_t fInt32;
    uint32_t fUInt32;
    int16_t fInt16[2];
    uint16_t fUInt16[2];
    int8_t fInt8[4];
    uint8_t fUInt8[4];
};
 
int main()
{
    /*
    число 0xc3960000 соответствует -300,00000
    проверяем это простым приведением типа
    */
    float xFloat;
    uint32_t x32=0xc3960000;
    xFloat=((union Convert32) x32).fFloat;
    printf("x=-300=%f\n", xFloat);
 
    /*
    допустим, при приёме по Modbus неизменён порядок слов и приняты слова 0x0000,  0xc396,
    */
    uint16_t a[2]= {0x0000, 0xc396};
    xFloat=0; //для чистоты эксперимента
    xFloat=*((float *) a);
    printf("x=-300=%f\n", xFloat);
 
    /*
    допустим, при приёме по Modbus изменён порядок слов и приняты слова 0xc396, 0x0000
    */
    uint16_t b[2]= {0xc396, 0x0000};
    xFloat=0; //для чистоты эксперимента
    {
        //обменяем порядок слов
        uint16_t temp;
        temp=b[0];
        b[0]=b[1];
        b[1]=temp;
    }
    xFloat=*((float *) b);
    printf("x=-300=%f\n", xFloat);
 
    /*
    допустим, при приёме по Modbus изменён порядок байт и приняты слова 0x96c3, 0x0000
    */
    uint16_t c[2]= {0x96c3, 0x0000};
    xFloat=0; //для чистоты эксперимента
    {
        //обмениваем порядок байт
        uint8_t temp;
        temp=*((uint8_t*)c+0);
        *((uint8_t*)c+0)=*((uint8_t*)c+3);
        *((uint8_t*)c+3)=temp;
        temp=*((uint8_t*)c+1);
        *((uint8_t*)c+1)=*((uint8_t*)c+2);
        *((uint8_t*)c+2)=temp;
    }
    xFloat=*((float *) c);
    printf("x=-300=%f\n", xFloat);
 
    return 0;
}

Не по теме:

Собственно, я знаю C/C++ также, как и вы, и только что увидел и применил адресную арифметику и приведение типов typecast



Добавлено через 41 минуту
Можно заполнять переменную float по мере приёма слов
C
1
2
3
4
5
6
7
8
9
10
11
    /*
    заполнение переменной типа float по мере приёма слов
    допустим, при приёме по Modbus неизменён порядок слов и приняты слова 0x0000,  0xc396,
    */
    uint16_t receive;   //принятое слово
    xFloat=123456.789;  //какой-то мусор в результирующей переменной
    receive=0x0000;     //первый принятый байт
    *((uint16_t*)&xFloat+0)=receive;
    receive=0xc396;     //второй принятый байт
    *((uint16_t*)&xFloat+1)=receive;
    printf("x=-300=%f\n", xFloat);
0
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
18.07.2019, 20:09
ФедосеевПавел,несколько запутанные у вас знания
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
Только размер типа float зависит от компилятора, а single - однозначно 32 бита.
float это 4 байта
single знаковый число может быть и положительным и отрицательным
unsingle беззнаковый число только положительное
и это приставка для целочисленных типов
может быть (un)signed char размер один байт (un)signed int а здесь зависит от разрядности системы от 2 до 4 байт, в МК обычно 2 байта
в старадавние времена решили int опускать, зачем не знаю, и можно встречать такие записи
signed тоже что и signed int
unsigned long тоже что и insigned long int

Цитата Сообщение от blokerun Посмотреть сообщение
- в терминале выдает нулевое значение перменной t (0.00)
Что я не так сделал?
а что ты туда положил?
вот как работать с объединениями
C
1
2
3
4
5
6
7
8
9
10
11
12
typedef union _floatchar 
     {
      float t;
      uint16_t  au16data[2]; 
      char ch[4];
     } floatchar ;
 
floatchar FloatChar;
FloatChar.t=1.0; // положили значения
printf (" %f" ,FloatChar.t) //вывели в виде float 
printf (" %d  %d" ,FloatChar.au16data[0],au16data[1]) // вывели массив au16data
printf (" %d  %d %d %d" ,FloatChar.ch[0],FloatChar.ch[1],FloatChar.ch[2],FloatChar.ch[3]) // вывели массив ch
и давайте обсуждать нюансы языка в соответствующей ветке
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
18.07.2019, 20:59
Цитата Сообщение от ValeryS Посмотреть сообщение
float это 4 байта
single знаковый число может быть и положительным и отрицательным
unsingle беззнаковый число только положительное
Не буду спорить. Мои познания в C ближе к суевериям.

У промежуточного топикстартера задача несколько сложнее, чем вывести на печать число float. И ещё, у него задача прямо противоположная самому первому топикстартеру - у того была передача в устройство, а у этого приём из устройства.

Из порта ввода-вывода его программа получает два слова (по 16 бит каждое). Эти два слова ему нужно составить в переменную типа float (размеры совпадают), т.е. сделать typecast.
Примерно эту ситуацию я воспроизвёл в
C
1
2
3
4
5
6
7
8
9
10
11
    /*
    заполнение переменной типа float по мере приёма слов
    допустим, при приёме по Modbus неизменён порядок слов и приняты слова 0x0000,  0xc396,
    */
    uint16_t receive;   //принятое слово
    xFloat=123456.789;  //какой-то мусор в результирующей переменной
    receive=0x0000;     //первое принятое слово
    *((uint16_t*)&xFloat+0)=receive;
    receive=0xc396;     //второе принятое слово
    *((uint16_t*)&xFloat+1)=receive;
    printf("x=-300=%f\n", xFloat);
Может быть на этом беды топикстартера и завершаться. А может случиться, что слова из устройства передаются не в порядке младшее, а потом старшее слово, а наоборот, или даже весь порядок байт обратный. Тогда после завершения приёма (или по мере приёма) нужно переставлять байты или слова уже в составленном числе float.

Поэтому я и привёл примеры преобразования массивов слов в число float.

А также спросил об эталонных значениях принятых слов и их корректной интерпретации. Если у него реальное устройство, то интерпретацию он увидит на дисплее устройства, а значения массива просто выведет контрольной печатью. После этого, немного попереставляв байты, можно разобраться с порядком принимаемых байт.
0
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
18.07.2019, 21:16
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
У промежуточного топикстартера задача несколько сложнее, чем вывести на печать число float. И ещё, у него задача прямо противоположная самому первому топикстартеру - у того была передача в устройство, а у этого приём из устройства.
так я печать привел, так, для примера
вот введение чисел и вывод на экран (или куда) нужно float
C
1
2
3
FloatChar.au16data[0]=0;
FloatChar.au16data[1]=0;
printf (" %f" ,FloatChar.t) //вывели в виде float
ФедосеевПавел, попытаюсь тебе как ассеблершику объяснить union
как ты знаешь, в памяти компа нет float, double, и прочей ереси
есть байты, а как их интерпретировать, дело программы и программиста
в данном случае в памяти 4 байта
и FloatChar.au16data это читает эти 4 байта как массив из двух слов по 2 байта
а FloatChar.t читает как float те же 4 байта
по сути то что ты сделал руками , все это выполнит union
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
18.07.2019, 21:57
Я понимаю, что такое union - это аналог записей с вариантами из Pascal.

Плохо пользуюсь преобразованиями C, поэтому не разобрался с применением union - хотел, оставляя переменную типом float, использовать именованный тип union для побайтовой адресации. Где-то запутался, а компилятор зорко следил за размерами переменных и типов - не дал выполнить typecast массива к типу union. Наверное, нужно было объявить два типа union размерами 2 и 4 байта, и уже ими оперировать при перестановке байт и слов.

Добавлено через 4 минуты
Я ассемблерщик волею случая. Мне ближе Pascal и некоторые IEC'овские языки. Еще пару лет назад мой ассемблер ограничивался TASM'ом и десятком инструкций допотопного процессора i8086.
0
0 / 0 / 0
Регистрация: 18.07.2019
Сообщений: 7
18.07.2019, 22:23
Господа, благодарю за помощь! Я сам не программист, так, совсем немного балуюсь с микроконтроллерами Atmega.
ModBus устройства у меня не промышленные а просто соединил между собой два микроконтроллера Ардуино, пока по UART портам, у них своя есть библиотека по модбусу. Хочу понять как работает протокол. Уже могу зажигать например светодиоды на мастере при каком-либо событии на слейве. Вот хотелось теперь передать показания температуры и влажности, а они float. Завтра буду пробовать преобразование на ваших примерах.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.07.2019, 22:23
Помогаю со студенческими работами здесь

Как передать одиночное значение (int\float) в шейдер
Всё работает хорошо, пока я не добавляю аттрибут float, он просто равен 0 в двух шейдерах, при изменении в вершинном, в фрагментный...

Как из mfc передать в Qt Activex массив float или double?
Я пишу activex компонент (с использованием Qt). Как переслать массив double в qt activex компонент из моего приложения? Если делать через...

Передать дробное число по modbus
Здравствуйте. Создал два простых приложения (сервер и клиент) с помощью библиотеки EasyModbus, вот они: class Program { ...

Как передать в строке "бесконечность" в метод float.TryParse(string)?
получил тестовое задание по шарпу, нужно было ввести в метод float.TryParse такую строку, что бы на выходе получить бесконечность. код...

Передать в функцию два значения float
Здравствуйте. Например: void Func( Один аргумент. ) { } Как в этот один аргумент передать два значения float ?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru