Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
Sergey1985
2 / 2 / 0
Регистрация: 16.09.2014
Сообщений: 38
Завершенные тесты: 1
1

Передача 4-х байтного значения по RS-232

20.06.2015, 08:22. Просмотров 1561. Ответов 21
Метки нет (Все метки)

Доброго времени суток товарищи программеры.
Вопрос по работе с rs232. Работаю в AVR Studio4. Необходимо асинхронно (используется только 2 проводка) передать 4-х байтную переменную. Как это можно реализовать если сам протокол работает максимум с 9-ти битными значениями.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.06.2015, 08:22
Ответы с готовыми решениями:

Передача данных с PIC16 по RS-232
Добрый день! Требуется передать результат вычислений по RS-232C (о приеме...

Умножение 2-байтного числа на 1-байтное (МК51)
Необходимо реализовать умножение двубайтного числа на однобайтное в...

Передача значения напряжения на ПК через V-USB
Добрый день! Я только начинаю программировать микроконтроллеры на си. Мне...

RS-232. Передача и прием данных
Подскажите пожалуйста. не опытному программисту в чем может быть проблема с...

Передача команд SCPI по RS-232
Привет всем есть такая задачка нужно написать программу на (MFC)c++ для...

21
raxp
10186 / 6569 / 492
Регистрация: 28.12.2010
Сообщений: 21,166
Записей в блоге: 1
20.06.2015, 15:52 2
...передавать побайтно, UART так и работает.
...9-ти битный режим ни к чему.
0
paskal
450 / 299 / 28
Регистрация: 15.08.2011
Сообщений: 920
20.06.2015, 21:13 3
9 битный режим может пригодится чтоб определить начало пакета
0
Sergey1985
2 / 2 / 0
Регистрация: 16.09.2014
Сообщений: 38
Завершенные тесты: 1
20.06.2015, 22:20  [ТС] 4
Так хорошо передавать по байтно. Только не понятен механизм приема данных Как понять что данный байт яв-ся именно ,к примеру, первыми 8-ми битами данных а не последними.
0
raxp
10186 / 6569 / 492
Регистрация: 28.12.2010
Сообщений: 21,166
Записей в блоге: 1
21.06.2015, 07:34 5
Лучший ответ Сообщение было отмечено raxp как решение

Решение

Напомнить формат UART? Или сами найдете. Таки, чтобы видно было, что начало пакета (фрейма UART) легко определить по стартовому биту после состояния IDLE.

Вот, если пакеты непрерывно шлются друг за другом, то может появиться необходимость идентифицировать один пакет от другого в случае разной информации в них, т.е. определить начало кодограммы из 4-х фреймов в случае TC. Вот в этом случае 9-ти битный режим и пригодится. Однако напомню, что при использовании 9-битного режима поимеем проблемы при необходимости стыковки устройства с компьютером (даже если устройство и не будет эксплуатироваться с компьютером, то возможно появится необходимость отладки или возможности его стыковки с ним).

9-ти битный легко обойти вводом битов идентификации (двух достаточно) в 8-ми битное поле данных. Да, конечно мы жертвуем частью информации и если данные в каждом байте занимают полностью всю разрядную сетку, то придется разбить данные еще и ввести дополнительный пакет (сами пакеты по 11 бит: стартовый ноль, 8 бит данных, стоповая единица, IDLE высокого уровня) в кодограмму.
0
Ethereal
Нарушитель
4522 / 1816 / 235
Регистрация: 17.02.2013
Сообщений: 2,711
22.06.2015, 13:19 6
Цитата Сообщение от Sergey1985 Посмотреть сообщение
Как понять что данный байт яв-ся именно ,к примеру, первыми 8-ми битами данных а не последними.
Тот байт, который ты пошлешь первым будет принят первым. Тот, который пошлешь последним будет принят последним.

Добавлено через 1 минуту
Сам для себя реши - я буду передавать байты в порядке от младшего к старшему. Или наоборот.
0
olegjan
11 / 11 / 1
Регистрация: 14.07.2014
Сообщений: 185
25.06.2015, 08:48 7
Sergey1985,
на стороне МК:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void my_put(unsigned long int _byte){
    
  while(!(UCSR0A & (1 << UDRE0)));
  UDR0 = _byte&0xFF;
  
  while(!(UCSR0A & (1 << UDRE0)));
  UDR0 = (_byte&0xFF00) >> 8;
    
  while(!(UCSR0A & (1 << UDRE0)));
  UDR0 = (_byte&0xFF0000) >> 16;
  
  while(!(UCSR0A & (1 << UDRE0)));
  UDR0 = (_byte&0xFF000000) >> 24;
}
со стороны хоста (например в Qt) поймать такую переменную можно так:
C++ (Qt)
1
2
3
4
5
6
#include <QtEndian>
..
..
    QByteArray byte;
    byte = port->readAll();
    quint32 q = qFromLittleEndian<quint32>((const uchar*)byte.constData());
qFromLittleEndian - определяет порядок байтов переменнной
0
Sergey1985
2 / 2 / 0
Регистрация: 16.09.2014
Сообщений: 38
Завершенные тесты: 1
25.06.2015, 08:56  [ТС] 8
О круто! Вот только я с Qt вообще никак.
А как эта запись будет выглядеть на С++Builder6
0
olegjan
11 / 11 / 1
Регистрация: 14.07.2014
Сообщений: 185
25.06.2015, 10:12 9
Sergey1985, ну я с С++Builder6 также как ты с Qt)
0
Sergey1985
2 / 2 / 0
Регистрация: 16.09.2014
Сообщений: 38
Завершенные тесты: 1
25.06.2015, 10:19  [ТС] 10
Понятно) Ну тогда сам приму. Вот только вопрос:
Прием нужно осуществлять как массив из 4-х байт или можно просто 32-х разрядную переменную сразу считывать. Прерывание 4 раза при приеме будет или только 1 раз?
0
olegjan
11 / 11 / 1
Регистрация: 14.07.2014
Сообщений: 185
25.06.2015, 10:27 11
Sergey1985, нужно принимать поочерёдно 4 байта, ибо компорт за раз умеет принять только 8 бит,
потом собирать эти 4 в одну 4-х байтовую переменную, только не забыть её сделать такого же размера, как та которую отправил из МК.
1
Voland_
1663 / 1009 / 96
Регистрация: 04.01.2010
Сообщений: 3,365
25.06.2015, 21:03 12
Лучший ответ Сообщение было отмечено raxp как решение

Решение

Цитата Сообщение от olegjan Посмотреть сообщение
нужно принимать поочерёдно 4 байта, ибо компорт за раз умеет принять только 8 бит,
дезинформируете, сударь.
ОСь буферизирует принятые данные в буфер до 4кб по умолчанию, если не ошибаюсь. А в обработчике COM-порта есть два типа прерываний - OnRxChar, который вызовется для каждого принятого байта (в вашем случае) данных, а есть OnRxData, когда прерывание вызовется один-два раза, для всего принятого буфера, либо его части, что заметно ускоряет обработку данных во многих случаях.

ЗЫ: почитайте в MSDN на предмет приема байт из COM-порта. Там же не все так сложно, вроде бы с примерами есть, на любом интересуемом языке.
1
Sergey1985
2 / 2 / 0
Регистрация: 16.09.2014
Сообщений: 38
Завершенные тесты: 1
26.06.2015, 10:23  [ТС] 13
В MSDN речь идет о программировании под Windows. Здесь как таковых вопросов нет. Вопрос возник как определить(передать)(принять) 32 разрядную переменную на AVR Т.е. как определить какой из принятых байт первый а какой последний. Но вроде разобрались правда еще не пробовал. Сделаю отпишусь возможно появятся еще вопросы по этой теме к гуру электронного мира
0
raxp
10186 / 6569 / 492
Регистрация: 28.12.2010
Сообщений: 21,166
Записей в блоге: 1
26.06.2015, 10:38 14
определить(передать)(принять) 32 разрядную переменную на AVR
складывается впечатление, что вы не читаете, что написано в посту #2 и 4.

UART работает побайтно, формируете массив и шлете из МК побайтно. Надо идентифицировать при приеме (не имеет никакого значения где, то ли в ПК, то ли в камне), читаем пост #4.
1
paskal
450 / 299 / 28
Регистрация: 15.08.2011
Сообщений: 920
28.06.2015, 15:26 15
Цитата Сообщение от Ethereal Посмотреть сообщение
Тот байт, который ты пошлешь первым будет принят первым. Тот, который пошлешь последним будет принят последним.
Представьте что первый байт случайно потерялся при приеме. Тогда первым будет принят второй байт. Sergey1985 правильный вопрос задал между прочим. Как вы отличите один байт от другого?
0
Ethereal
Нарушитель
4522 / 1816 / 235
Регистрация: 17.02.2013
Сообщений: 2,711
28.06.2015, 23:55 16
Цитата Сообщение от paskal Посмотреть сообщение
Представьте что первый байт случайно потерялся при приеме.
Тогда хоть на голову встань, а данные потеряны.

Если ситуация с потерей байт возможна, то надо целый протокол рисовать.
С заголовком и контрольной суммой у посылки. С подтверждением приема посылки и повтором посылки если подтверждения не было.

Добавлено через 3 минуты
Можно за основу взять протокол обмена между программатором и программируемым МК.
Заголовок, длина данных, данные, контрольная сумма. Ответ ACK, если все принято нормально или NAK в противном случае. Если NAK, то посылка повторяется. Если нет ответа, то после паузы повторяется. Если сделано X попыток и ACK не получен, то делается вывод об отсутствии связи.
0
paskal
450 / 299 / 28
Регистрация: 15.08.2011
Сообщений: 920
29.06.2015, 00:30 17
Цитата Сообщение от Ethereal Посмотреть сообщение
Тогда хоть на голову встань, а данные потеряны.
Заметьте, речь о том что после такого сбоя теряются все последующие данные. Т.е. предложенная схема фактически неработоспособна. Протокол с заголовком и контрольной суммой не обязателен. Но возможность синхронизации - необходима.
Замечено, что уже при включении питания проскакивает от 1 до нескольких байт мусора. Так что ваша схема может не работать сразу после включения даже без потерь в канале.
0
Voland_
1663 / 1009 / 96
Регистрация: 04.01.2010
Сообщений: 3,365
29.06.2015, 11:12 18
...на самом деле методов валидации (определения достоверности блока данных) намного больше, чем принцип "заголовок - данные - чексумма". Можно использовать все знания о передаваемых данных, тогда можно вполне (для синхронизации) обойтись другими проверками.

Например, если вы передаете тип float (4 байта) или double (8 байт), то принятые значения очень сильно будут разниться по сравнению с оригиналом, при потере байта и особенно, при смещенном приеме. Поэтому, достоверным (и/или синхронизированным) можно считать значения, подходящие под достоверный диапазон принимаемых значений.
Скажем, принимаете вы значение температуры в формате float. При проверке принятых 4х байт проверяете - является ли число в пределах измерения (скажем, >=-273 и <1500) и если не является, то выкидываете первый принятый байт из буфера и ожидаете следующий, пока число не войдет в диапазон.

Конечно, такая "защита" намного менее эффективна по сравнению с заголовком+чексумма. Но она настолько же и более проста.

а еще сплошь и рядом используются таймауты. То есть расстояние между соседними пакетами должно составлять >NN мс, а расстояние между соседними байтами в блоке должно быть <MM мс. То есть как только контроллер или комп видят, что принят пакет с разрывом, либо пакет не содержит должное количество байт - весь пакет отбрасывается в утиль.
0
ValeryS
Модератор
7316 / 5559 / 704
Регистрация: 14.02.2011
Сообщений: 18,853
29.06.2015, 11:28 19
могу предложить еще один вариант, ТС к нему шел
первая посылка 9 бит в 0 в байте или 0 или номер посылки
4 байта данных 9 бит в 1
считываем до тех пор пока не придет посылка с 9 байтом равным 0
выставляем флаг, выставляем размер пакета 4
считываем данные
если установлен флаг и 9 бит 1 то это данные
укладываем их
вычитаем из длинны пакета 1
если длина пакета равна 0, то все данные приняли, флаг сбрасываем и все сначала
если 9 бит 0 но длинна пакета не 0, значит ошибка, сбрасываем флаг и все сначала
0
Sergey1985
2 / 2 / 0
Регистрация: 16.09.2014
Сообщений: 38
Завершенные тесты: 1
29.06.2015, 12:48  [ТС] 20
Вот интересно как функция WriteFile на C++ данные передает. Имеется в виду физический уровень. Ведь данные там вообще могут быть какие угодно. Но тем не менее ReadFile на другом компе все считывает без всяких потерь данных.
0
29.06.2015, 12:48
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.06.2015, 12:48

Преобразование числового значения типа Float для передачи по RS-232 (SerialPort)
Добрый день! Возникла следующая проблема: необходимо преобразовать число типа...

(К1810ВМ86) Циклический сдвиг 4-х байтного кода
Здравствуйте, столкнулся с ЭВМ УМПК-86. Было дано задание создать алгоритм, но...

Конвертировать из четырех байтного масива в десятичное число
Всем привет. Ни как не получается придумать как конвертировать четырех байтный...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru