Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.60/47: Рейтинг темы: голосов - 47, средняя оценка - 4.60
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
1

Передать float через usart 328p

02.05.2019, 17:17. Показов 9507. Ответов 46
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день!

Уже несколько несколько дней не могу решить такую задачу: Передать через usart float.
Вот код:
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
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
void USART_init(void) // Настраеваем скорость передачи данных
{
  UBRR0L = 103;
  UBRR0H = 0;
  UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
void USART_TransmitByte( unsigned char data )
{
  while ( !( UCSR0A & (1<<UDRE0)) );
  UDR0 = data;
}
void USART_TransmitText(char* data)
{
   while (*data != 0)
   {
      while ( !( UCSR0A & (1<<UDRE0)) );
      UDR0 = *data;
      data++;
   }
}
void float_write(float f)
{
  float a = f;
  char* ptr;
  ptr = (char*) &a;
  for (int i = 0; i < 4; i++)  // Побайтово передаем
  {
     char simvol = *(ptr++);
     USART_TransmitByte(simvol);
  }
}
int main (void)
{
   sei();
   USART_init();
   float_write(78.6);
   //char a = 1 + '0';
   //USART_TransmitByte(a);
   
}
Вот вывод: 33⸮B

Что я сделал не так?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.05.2019, 17:17
Ответы с готовыми решениями:

atmega 328p USART
Доброго времени суток и панигите люди добрые :) Общие оговорки: я любознателен, но не знаком с ...

Как вывести float число через USART?
Проблема следующая, считываю данные с АЦП, запихиваю в переменную например tempadc в ней могут...

Как передать данные через usart
Целый день мучался как передать данные на комп., толком ничего не вышло, вот код #include...

Передача сообщения через UART для Atmega 328P
Добрый день. Сам я новичок в этом деле. Сделал устройство бегущей строки на Atmega328P по этой...

46
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
03.05.2019, 21:24  [ТС] 21
Author24 — интернет-сервис помощи студентам
tatarva87, можете скинуть инфу где описывается как и что там мк преобразует и делает с float, а то 8 16 цифр это уже 16 байт, я окончательно запутался.

Добавлено через 5 минут
Можете скинуть инфу о том как хранится float в памяти avr, а то я уже запутался. Один говорит float в МК преобразуется в 16 битное число, в интернете пишут то что float хранится как 4 байта. Моя задача разобраться со всем этим и передать float собственными силами без всяких высокоуровневых функций. И эту статью, которую сейчас скинули я уже читал.
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
03.05.2019, 21:44 22
Число float занимает 4 байта или 32 бита. Тот код, что тебе приводили - это распаковка при помощи функции sprintf числа float в символьный вид из 16 цифр. Но если ты не хочешь использовать библиотечную функцию, то забудь про этот пример. Повторяю число float занимает 4 байта или 32 бита.
1
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
03.05.2019, 21:47  [ТС] 23
А если так?
C
1
2
3
4
5
6
7
8
9
10
11
12
void float_write(float f)
{
  uint32_t number = f;
  uint8_t byte_out;
  uint32_t*pointer_float = &number;
  for (int start = 0; start < 4; start++)
  {
    byte_out = *pointer_float;
    pointer_float++;
    USART_TransmitByte(byte_out);
  }
}
Добавлено через 14 секунд
C
1
2
3
4
5
6
7
8
9
10
11
12
void float_write(float f)
{
  uint32_t number = f;
  uint8_t byte_out;
  uint32_t*pointer_float = &number;
  for (int start = 0; start < 4; start++)
  {
    byte_out = *pointer_float;
    pointer_float++;
    USART_TransmitByte(byte_out);
  }
}
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
03.05.2019, 22:00 24
Опять же, повторяю: это не годится. То что ты выводишь непосредственно из переменной float побайтно в порте будет отображаться абракадаброй. Тебе нужно реализовать собственную функцию аналогичную printf, в которой нужно произвести распаковку числа float в поразрядное представление и каждый разряд выводить в порт, преобразуя эту разрядную цифру в символьное представление из таблицы ASCII и не забыть про точку.
Например, если при распаковке float ты получишь цифры 12.456, то тебе нужно взять цифру 1, найти в кодовой странице её код (для единицы это будет код 49) и вывести этот код:
C
1
USART_TransmitByte( 49);
Затем берёшь цифру 2 и выводишь:
C
1
USART_TransmitByte( 50);
Затем выводишь точку:
C
1
USART_TransmitByte( 46);
И так далее.
1
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
03.05.2019, 22:13  [ТС] 25
Я понимаю то что побайтово это превращается в черте что, но я написал свой пример монитора порта и скидывал его код. Он принимает 4 байта и превращает их в последовательность 32 бит и эти биты должны будут превратиться во float

Но проблема в том, что самый первый бит из этих 32-ух, который определяет знак всегда равен 0(даже если число -54.43), значит. Значит косячит avr

Добавлено через 1 минуту
Вот 4 байта, и дальше я с ними буду работать
begin
00000000
00000000
00000000
00000010
end
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
03.05.2019, 22:35 26
Не совсем понял. Нужно распаковать или запаковать во float десятичное число?
1
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
03.05.2019, 22:42  [ТС] 27
Еще раз весь процесс.

Вообщем, программа на МК находит число float в памяти МК, которое занимает 4 байта и передает их через USART по одному. Далее моя программа на ПК принимает эти четыре байта и превращает их в последовательность 32 бит, далее 32 бита должны будут превратиться во float число.

Добавлено через 48 секунд
Вот эти биты, но они не похожи на правду
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
03.05.2019, 23:31 28
А, вот как! Я-то думал, что всё это нужно сделать средствами микроконтроллера и вывести в человеческом виде в порт.
Ну а если так, то в чём дело-то тогда? При выводе в порт тогда и должна получаться абракадабра и пусть её забирает компьютер и работает дальше. Главное порядок байт не перепутать при выводе в порт.

Добавлено через 7 минут
C
1
2
3
4
5
6
7
8
void float_write(float f)
{
 byte *uk=(byte *)&f
  for (int start = 0; start < 4; start++, uk++)
  {
     USART_TransmitByte(*uk);
  }
}
Вот только с порядком байт не помню. Может быть их надо в обратном порядке выводить. Поищи каков порядок следования байт в AVR
0
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
03.05.2019, 23:33  [ТС] 29
Просто вот эти байты, которые получает комп в бинарном виде:
00000000
00000000
00000000
00000010

не зависимо от того, отрицательное или положительное число первый бит всегда 0.
Программу на пк проверял она правильно работает это МК чудит
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
03.05.2019, 23:39 30
Попробовал функцию, что я привёл?
0
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
03.05.2019, 23:40  [ТС] 31
6.84
00010010
10000111
01011011
00000010

-6.84
00010010
10000111
01011011
00000010

Не смотря на знак биты одинаковые, а ведь один бит во float определяет знак

34.84
10010100
00111010
11010000
00000010

-34.84
10010100
00111010
11010000
00000010

Добавлено через 38 секунд
Да, только что
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
04.05.2019, 00:04 32
Да, действительно, старший бит почему-то 0.
Но у тебя и порядок бит инвертирован и порядок байт.
Например число -6.84 от старшего бита к младшему и от старшего байта к младшему должен идти вот так, то есть в обратном порядке.
11000000
11011010
11100001
01001000

Но это в принципе не особо важно, если ты сам знаешь свой порядок и правильно его интерпретируешь в программе.
А вот бит отвечающий за знак всё же почему-то нулевой.
0
4393 / 2243 / 252
Регистрация: 28.10.2011
Сообщений: 8,574
Записей в блоге: 6
04.05.2019, 00:10 33
Цитата Сообщение от Danil_2002 Посмотреть сообщение
6.84
00010010
10000111
01011011
00000010
На компе результат.
Код
01001000
11100001
11011010
01000000
Найдите отличия.

Тестовый код.
PureBasic
1
2
3
4
5
f.f=6.84
Debug RSet(Bin(PeekA(@f),   #PB_Ascii), 8, "0")
Debug RSet(Bin(PeekA(@f+1), #PB_Ascii), 8, "0")
Debug RSet(Bin(PeekA(@f+2), #PB_Ascii), 8, "0")
Debug RSet(Bin(PeekA(@f+3), #PB_Ascii), 8, "0")
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
04.05.2019, 00:18 34
Цитата Сообщение от locm Посмотреть сообщение
На компе результат.
Код
01001000
11100001
11011010
01000000
Здесь порядок байт от младшего к старшему, то есть старший байт внизу, а порядок бит от старшего к младшему, то есть старший бит в каждом байте слева, а младший - справа.
0
4393 / 2243 / 252
Регистрация: 28.10.2011
Сообщений: 8,574
Записей в блоге: 6
04.05.2019, 00:25 35
И я о том же. Это общепринятый порядок записи двоичных чисел когда старший байт слева, а младший справа.
0
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
04.05.2019, 00:28  [ТС] 36
Да какая разница как они расположены(так просто было проще вывести их в консоль), обрабатываться они будут уже в нормальном виде

Добавлено через 21 секунду
Проблема в другом
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
04.05.2019, 00:39 37
Цитата Сообщение от Danil_2002 Посмотреть сообщение
Проблема в другом
Попробовал у себя на ардуинке число -6.84, выводит нормально, со знаком.

Может у тебя в функции показывающей биты ошибка?
0
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
04.05.2019, 00:57  [ТС] 38
Нет, ее проверял отдельно.
Вот она:

Добавлено через 9 секунд
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int* bin_number(char* buf)
{
    int bin[32]; // Двоичное представление числа float
    int a = 0;
    printf("begin");
    printf("\n");
    for(int start = 0; start < 4; start++)
    {
        char simvol = *(buf); // Извлекаем байт
        buf++;
        //char simvol = (char)5;
        for (int st = 0; st < 8; st++)
        {
            bin[a] = (simvol >> st) & 1;
            printf("%d", bin[a]);
            a++;
        }
        printf("\n");
    }
    printf("end");
    printf("\n");
}
Добавлено через 1 минуту
Мне кажется что именно с отправкой байтой на avr(в самой программе), может не до чет какой-то.
0
11 / 10 / 3
Регистрация: 30.04.2019
Сообщений: 60
04.05.2019, 00:59 39
Попробуй мою
C
1
2
3
4
5
6
7
8
9
10
11
void func2(float k){
  byte *r=(byte *)&k;
  for(int i=3;i>=0;i--){
    for(int j=7;j>=0;j--){
      if(*(r+i) & (1<<j)){USART_TransmitByte(49);}
      else {USART_TransmitByte(48);}
    }
    USART_TransmitByte(10);
    
  }
}
Выводит "битовое поле" побайтно, от старшего к младшему. Бит знака слева вверху.

Вот её вывод чисел -6.84 и 6.84 у меня:
11000000
11011010
11100001
01001000


01000000
11011010
11100001
01001000
Как видишь знак в старшем разряде отображается
0
35 / 25 / 10
Регистрация: 16.02.2018
Сообщений: 152
04.05.2019, 11:47  [ТС] 40
А программу, которая принимает биты ты сам писал? Можешь кинуть? А то проблема со старшем битом решена, а вот остальные биты все одинаковые, какое число бы я не кидал. Значит моя программа тупит. Хотя я ее проверял. Скармливал обычные числа и проверял правильно ли она выводит их в бинарном виде.

И вот мой вывод 6.84:

00001100
10001100
00001100
00000010
0
04.05.2019, 11:47
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.05.2019, 11:47
Помогаю со студенческими работами здесь

Приём данных с usart через dma в память периферии и вывод обратно на usart (для проверки)
Подскажите, как сделать так, чтобы при отправке через usart в переменную и обратно вывести по...

Не Получается Передать Байт С Выхода Usart
Всем привет! Я новичок в разработке кода для STM32! Но очень хочу освоить это направление! Купил...

Как передать по modbus float
Если я хочу передать по modbus float я разбиваю его на 4 байта и формирую 2 регистра, код...

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

Прошивка stm32f105 через USART
Здравствуйте. Сделал boottooder, который по MODBUS записывает в программный флэш прошивку, а затем...

Программирование STM43F407VG через USART
Приветствую Всех с Новым 2015 годом и Рождеством ! Исследую STM43F407VG на базе...

xmega: usart - какой глубины буфер в USART?
Взялся тут &quot;запилить&quot; на xmego32a4 мультиплексор двух rs232 в один rs485. Все как бы получилось и...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru