Страница 1 из 1
Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 03:21:17
7seg
Уважаемые товарищи , сижу уже второй вечер и не могу найти решение поставленной себе задачи. Мб кто подскажет ?
Есть несколько устройств которые опрашивается по uart'ом, ну вот собрал я все данные и спокойно могу оперировать эти данными в приделах так называемого контролера мастера.
Но далее я бы хотел передать все эти данные по TWI шине вот тут у меня и получается каша в голове. (
Как правильно передать данные (32 байта), чтобы на втором мк их было удобно рассортировать.
Изначально предполагал использовать разновидность FIFO буфера , а именно кольцевой, т.к в него удобно записать полученные данные по uart , а далее побайтно передать через TWI, не боясь что случиться потеря данных или переполнения буфера.
Но вот и загвоздка пока я собираю байтики через uart , я знаю что это за данные, а вот когда они переданы все буфером по TWI появляется проблема с классификацией данных.
Хотелось услышать советы от более опытных котов , как все же правильно организовать данную передачу ?
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 04:02:58
akl
Присваивайте каждому каналу индивидуальный адрес и передавайте. Благо IIC это позволяет.
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 04:16:02
7seg
@akl , пока я склоняюсь на самом деле тоже к этому методу т.к этот метод по крайне мере уже использовал для написания драйвера монохромного lcd индикатора. Но и у адресации есть минус, увеличение объема передаваемой информации. М.б кто еще какие методы знает ?)
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 05:38:13
Z_h_e
7seg писал(а):Но и у адресации есть минус, увеличение объема передаваемой информации.
А как I2C без адресации использовать? Можно конечно в поле адреса данными забить....
7seg писал(а): М.б кто еще какие методы знает ?)
Все данные, от всех МК передаете в одном пакете (пакетах) в определенной последовательности за определенное время. Начала пакета определяется паузой на линии не менее х времени.
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 06:06:52
7seg
@Z_h_e, Т.е вы предлагаете повторит структуру разделения пакетов по принципу как это сделано в ModBus RTU, Правильно ли я вас понял ?
Просто если не много уточнить используемую мной иерархию в целом : То у меня используется сенсорная панель , которая является в моей системе Мастером (протокол ModBus), далее я собираю данные этой панелью с небольших блоков на которых реализован самописанный слейв ModBus'a , Дальше передаю все собранные данные так сказать на конвертер(мост ModBus-TWI).
И что то мне подсказывает что МК который принимает такой объем информации для последующей передачи через TWI просто не осилит еще и обработку отдельного таймера для разделения пакетов паузами. (хотя я могу ошибаться , уж очень мало времени я знаком с программированием микроконтроллеров.)
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 06:25:13
Z_h_e
Ну можно выделить еще одну линию под стробы для синхронизации. Например после спада или фронта начало пакета данных.
Добавлено after 36 seconds:
Можно отправлять уникальный служебный пакет - начало данных.
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 06:39:15
7seg
@Z_h_e , мне если можно так выразится идея с отправкой служебного пакета (который будет гласить, о начале или завершении передачи данных ) . Только у меня возникает вопрос ? Как исключить случай когда полезные данные(которые мы пересылаем) будут равны служебному пакету.(думаю я не первый задался этим вопросом, но нечего толкового нагуглить не смог по данной тематике.)
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 07:01:51
Z_h_e
7seg писал(а):Как исключить случай когда полезные данные(которые мы пересылаем) будут равны служебному пакету.
Вариантов то кучу можно придумать. Например длина стартового имеет уникальную фиксированную длину и отличается от длины полезных данных.
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 07:17:10
7seg
В ближайшее время как буду у пк, попробую воплотить это в код,Вроде каши стало меньше после общения на форуме.
Re: Фильтрация данных при передаче.
Добавлено: Ср фев 20, 2019 10:03:15
GoldenAndy
[uquote="Z_h_e",url="/forum/viewtopic.php?p=3573995#p3573995"]
7seg писал(а):Как исключить случай когда полезные данные(которые мы пересылаем) будут равны служебному пакету.
Вариантов то кучу можно придумать. Например длина стартового имеет уникальную фиксированную длину и отличается от длины полезных данных.[/uquote]
Почитайте про протокол Wake - там есть спец.символы, а если полезный символ совпадает со спец.символом - он экранируется.
Re: Фильтрация данных при передаче.
Добавлено: Пт фев 22, 2019 04:33:44
7seg
Наконец то появилось время чтобы продолжить разбираться с передачей данных )
@goldenandy еще раз спасибо за направление в сторону протокола Wake.Технология Байт-Стаффинга замечательная вещь, надеюсь сегодня уже реализую облегченный протокол на основании Wake.
Есть один вопрос по поводу корректности копирования данных , мб кто подскажет можно ли так делать ?
Есть структура
Код: Выделить всё
struct Data
{
volatile uint8_t InState[5]; //Дискретные входа
volatile uint8_t OutState[4]; //Дискретные выхода
volatile uint16_t InputRegisters[5]; //Выходные 16-Битные данные.
volatile uint16_t HoldingRegisters[5]; //Входные 16-Битные данные.
}DataBus;
Есть массив:
Код: Выделить всё
uint8_t BuffTransmitTWI[sizeof(DataBus)+1]={0}; //Размер 29 байт + 1 байт.
И написал функцию копирования :
Код: Выделить всё
void WriteDataBuf()
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
memcpy((BuffTransmitTWI+1),&DataBus,(sizeof(DataBus)));
}
}
На первый взгляд вроде все компактно\красиво , а главное работает.
BuffTransmitTWI+1 т.к первая ячейка буфера (BuffTransmitTWI[0]) используется для адресации.
Но вот могут ли быть какие либо подводные камни ? у данного метода.
P.S всегда с опаской использую memcp, а функции memcpy_s вроде бы нет в avr gcc.
Re: Фильтрация данных при передаче.
Добавлено: Пт фев 22, 2019 10:00:20
BOB51
Ежли уж сильно хочется и максимальную достоверность данных и энное количество и разноскоростные МК при условии фонового обмена...
Да все равно три линии использовать...
Тогда есть смысл в использовании протокола с побитовой синхронизацией как вот в этом проекте
https://radiokot.ru/forum/viewtopic.php ... 1#p3472041
там как раз два комплекта - базовый на MCS-51 и собственно исполнительный блок на аттини2313.
Единственный гвоздь - проект под ассемблером.

Re: Фильтрация данных при передаче.
Добавлено: Пт фев 22, 2019 10:14:02
7seg
[uquote="BOB51",url="/forum/viewtopic.php?p=3575545#p3575545"]Единственный гвоздь - проект под ассемблером.

[/uquote]
К сожалению ASM так и не смог осилить , уж очень он привязан к железу. И код получается на нем не читабельный(по крайне мере для меня).

Re: Фильтрация данных при передаче.
Добавлено: Пт фев 22, 2019 12:06:26
BOB51
Для утилиток весьма неплохой комментарий выполнен - переведи в Си и используй.
Всего-то "ногодрыг"
Вытянул непосредственно тиньки касающееся:
Спойлер
Код: Выделить всё
;
; trbspi_sb1.txt
;
; файл протокола приемопередатчика проекта UPGM
; для блока подчиненной периферии(PAVR)
; /slave board/
;
;
;----------------------------------------------
;
; .equ bus_dtr = 0 ; шина данных/запроса доступа
; локализация в PORTA PAVR
; по reset вход с внешней подтяжкой к +5 вольт
; при запросе выход с активным уровнем 0
; при обмене соответственно или вход или выход
; с данными в прямом коде
; .equ bus_clc = 1 ; тактовый строб обмена данными
; локализация в PORTA PAVR
; по reset/cold init вход с внешней подтяжкой к +5 вольт
; при обмене соответственно вход(прием) или выход(передача)
; активный уровень 0
; .equ bus_qt = 0 ; шина квитирования
; локализация в PORTD PAVR
; по reset/cold init вход с внешней подтяжкой к +5 вольт
; активный уровень 0
; вход для передатчика, выход для приемника
;
;----------------------------------------------
;
; .def data_t = r11 ; регистр (урезан) данные данных trbspi_sb
;
;----------------------------------------------
;
; данные флаги размещены в регистре РСФ GPIOR0
; или по псевдониму доступа через ОЗУ (GPIOR0+0x20)
;
; .equ data_key = 0 ; (GPIOR0) флаг типа данные/команда
; data_key=0 - байт с данными
; data_key=1 - байт с командой
;
;
;
;----------------------------------------------
;
; тактовая частота системного генератора 8МГц
;
;----------------------------------------------
;
; настройки портов относительно PSPI
;
; исходно по reset
; DDRA=00000000
; PORTA=00000000
; входы с Z-состоянием
; DDRB=00000000
; POTTB=00000000
; входы с Z-состоянием
; DDRD=00000000
; POTTD=00000000
; входы с Z-состоянием
; В init проводим отключение подтягивающих резисторов
; MCUCR.PUD=1
; и устанавливаем PORTD.ptr_clc = 0 DDRD.ptr_clc = ВЫХОД (1)
;
;----------------------------------------------
;
; модуль передачи
;
; собственно передача data_key и байта данных
; перед вызовом программы
; данные должны быть загружены в
; data_t (r11)
; и установлен в соответствие флаг data_key
;(data_key=0 - байт с данными
; data_key=0 - байт с командой)
;
;
pspi_txd:
push tmp0 ; служебный буфер-времянка
push tmp1 ; счетчик бит
push tmp2 ; счетчик таймера интервалов
cbi DDRA,bus_dtr
cbi DDRA,bus_clc
cbi DDRD,bus_qt ; предварительно настроено
; bus_dtr=bus_clc=bus_qt=ВХОД (через внешнюю
; подтяжку = 1)
cbi PORTA,bus_dtr ; подготовлено к выдаче bus_dtr=0
; вывод bus_dtr=1
cbi PORTA,bus_clc ; подготовлено к выдаче bus_clc=0
; вывод bus_clc=1
cbi PORTD,bus_qt ; подготовлено к выдаче bus_qt=0
; вывод bus_qt=1
tx_on:
ldi tmp1,8 ; счетчик бит загружен
in tmp0,GPIOR0 ; читаем флаг data_key
rcall strob ; бит типа данных передан
data_tx:
mov tmp0,data_t
rcall strob ; бит данных передан
lsr tmp0 ; постсдвиг значения данных
mov data_t,tmp0 ; используется вывод данных из tmp0.0
dec tmp1
brne data_tx
tx_off:
pop tmp2
pop tmp1
pop tmp0
ret
;----------------------------------------------------------
strob:
sbrs tmp0,0
sbi DDRA,bus_dtr ; if tmp0,0=0 --> вывод bus_dtr=0
sbrc tmp0,0
cbi DDRA,bus_dtr ; if tmp0,0=1 --> вывод bus_dtr=1
; вывод в соответствии нулевого бита из tmp0,0
; на PORTA,bus_dtr
rcall time ; задержка установки данных
sbi DDRA,bus_clc ; активируем запрос синхронизации
; ранее в PORTA.bus_clc установлен 0
rcall time ; задержка установки данных
tx_tp0:
sbic PIND,bus_qt
rjmp tx_tp0 ; ожидание ответа приемника (bus_qt=0)
cbi DDRA,bus_clc ; деактивируем запрос синхронизации
; bus_clc=ВХОД
; единица на bus_clc формируется за счет внешнего
; подтягивающего резистора
cbi DDRA,bus_dtr ; вывод bus_dtr=1
; разворот шины данных на ВХОД
rcall time ; задержка установки данных
tx_tp1:
sbis PIND,bus_qt
rjmp tx_tp1 ; ожидание ответа приемника (bus_qt=1)
rcall time ; задержка установки данных
ret
;----------------------------------------------------------
time:
ldi tmp2,10 ; интервал ~40uS период = 0,00004*5= ~0,0002 бита/секунду
ttime:
nop ;
dec tmp2
brne ttime
ret
;----------------------------------------------------------
;
;
;----------------------------------------------
;
; модуль приема
;
; не имеет защиты от превышения ожидания длительности строба
; сопровождения исходя из предположения, что обмен между модулями
; является основной частью программы в промежутках между исполнением
; команд
; т.е. допускается полный останов обмена
;
; при выходе
;
; в data_t принятые данные в прямом коде
; флаг GPIOR0.data_key=1 принята команда
; флаг GPIOR0.data_key=0 приняты данные
;
;
pspi_rxd:
push tmp0 ; буфер обмена
push tmp1 ; счетчик бит
push tmp2 ; счетчик таймера интервалов
cbi DDRA,bus_dtr
cbi DDRA,bus_clc
cbi DDRD,bus_qt ; предварительно настроено на
; шины bus_dtr=bus_clc=bus_qt=ВХОД, bus_dtr=bus_clc=bus_qt1=1
cbi PORTA,bus_dtr ; подготовлено к выдаче bus_dtr=0
; вывод bus_dtr=1
cbi PORTA,bus_clc ; подготовлено к выдаче bus_clc=0
; вывод bus_clc=1
cbi PORTD,bus_qt ; подготовлено к выдаче bus_qt=0
; вывод bus_qt=1
rx_on:
rcall strobinp ; флаг типа данных получен
sbrs tmp0,7
cbi GPIOR0,data_key
sbrc tmp0,7
sbi GPIOR0,data_key ; флаг типа данных размещен
ldi tmp1,8 ; загрузить счетчик бит
data_rx:
rcall strobinp ; текущий бит данных получен
dec tmp1
brne data_rx
mov data_t,tmp0 ; данные переданы в data_t
pop tmp2
pop tmp1
pop tmp0
ret
;-------------------------------------------------------------
strobinp:
sbic PINA,bus_clc ; простой в ожидании PORTA.bus_clc=0
; ***!!! выполняется БЕЗ ОГРАНИЧЕНИЯ НА ВРЕМЯ ОЖИДАНИЯ !!!***
rjmp strobinp
rcall time ; задержка установки данных
sbis PINA,bus_dtr
clc
sbic PINA,bus_dtr
sec
ror tmp0 ; заносим значение текущего PINA.bus_dtr в старший бит tmp0
sbi DDRD,bus_qt ; актвировать строб квитирования
; bus_qt=ВЫХОД с предварительно заданным
; (cbi PORTD,bus_qt) значением =0
rcall time ; задержка установки данных
rx_tp1:
sbis PINA,bus_clc ; простой в ожидании PORTA.bus_clc=1
; ***!!! выполняется БЕЗ ОГРАНИЧЕНИЯ НА ВРЕМЯ ОЖИДАНИЯ !!!***
rjmp rx_tp1
cbi DDRD,bus_qt ; деактвировать строб квитирования
; bus_qt=ВХОД, единица устанавливается за счет внешнего
; подтягивающего резистора
rcall time ; задержка установки данных
ret
;
;----------------------------------------------
;
собственно переделывается под любой иной МК с использованием соответствующего набора команд в оном применяемого.
А обработчик принятых данных на собственное усмотрение.

И там же в проекте "просто словами" записан алгоритм (брался за основу при разработке):
для передатчика
Спойлер
;
; общие положения по приемопередатчику внутренней шины обмена
; команд/данных
передача идет младшими битами вперед
данные пересылаются в прямом коде
перед каждым байтом следует бит ключа типа данных
data_key = 0 идет пересылка данных
data_key = 1 идет пересылка команды
размер пакета определяется по контексту команды
применяется последовательная пересылка с
побитовым квитированием (подобно ранее применяемому
в старых конструкциях) но с сокращенным временем ожидания
стабилизации состояния шины данных (короткий соединительный шлейф)
используется три двунаправленных шины
bus_dtr - данные (передача или прием)
bus_clc - строб сопровождения, генерируется передатчиком
bus_qt - строб квитирования, генерируется приемником
тип шин -
ВХОД с Z-состоянием и внешним подтягивающим резистором
для приемника
и
ВЫХОД с ОК (монтажное ИЛИ) и внешним подтягивающим резистором
для передатчика
статус "активный выход в состоянии 1" НЕ ДОПУСКАЕТСЯ!
передатчиком или приемником может являться как ведущий,
так и подчиненный МК в зависимости от контекста выполняемой задачи
данный протокол может объединять только два МК или МК и ПК
через LPT порт
интервал ожидания не имеет ограничений по времени, но может быть
дополнен защитой от зависания в 10-30 секунд
первым передается data_key, затем 8 бит данных
строб сопровождения имеет активный уровень равный 0
начало передачи
установить bus_dtr=bus_clc=bus_qt=1
bus_qt=ВХОД
bus_trd=bus_clc=ВЫХОД
подготовка флагов, буфер-регистров
/загрузка начального значения в счетчики интервалов/
START
выдать на bus_dtr текущий бит данных
дать задержку в 5uS
установить bus_clc = 0
дать задержку в 5uS
ожидание bus_qt = 0
по обнаружении bus_qt = 0
дать задержку в 5uS
установить bus_clc = 1
дать задержку в 5uS
ожидание bus_qt = 1
по обнаружении bus_qt = 1
дать задержку в 5uS
выполнить операции по продолжению обработки данных
перейти в точку START
либо завершить обработчик передатчика
флаги
data_key "флаг ключа типа данных"
/"ошибка отсутствия корреспондента"/
регистры
буфер данных в 2 байта
счетчик интервала длительности импульсов
счетчик бит
/счетчик превышения времени ответа об исполнении/
Согласно протокола переходим в режим приема квитанции об исполнении команды
от исполнительного модуля.
и для приемника
Спойлер
;
; общие положения по приемопередатчику внутренней шины обмена
; команд/данных
прием идет младшими битами вперед
данные пересылаются в прямом коде
перед каждым байтом следует бит ключа типа данных
data_key = 0 идет пересылка данных
data_key = 1 идет пересылка команды
размер пакета определяется по контексту команды
применяется последовательная пересылка с
побитовым квитированием (подобно ранее применяемому
в старых конструкциях) но с сокращенным временем ожидания
стабилизации состояния шины данных (короткий соединительный шлейф)
используется три двунаправленных шины
bus_dtr - данные (передача или прием)
bus_clc - строб сопровождения, генерируется передатчиком
bus_qt - строб квитирования, генерируется приемником
тип шин -
ВХОД с Z-состоянием и внешним подтягивающим резистором
для приемника
и
ВЫХОД с ОК (монтажное ИЛИ) и внешним подтягивающим резистором
для передатчика
статус "активный выход в состоянии 1" НЕ ДОПУСКАЕТСЯ!
передатчиком или приемником может являться как ведущий,
так и подчиненный МК в зависимости от контекста выполняемой задачи
данный протокол может объединять только два МК или МК и ПК
через LPT порт
интервал ожидания не имеет ограничений по времени, но может быть
дополнен защитой от зависания в 10-30 секунд
начало приема
установить bus_dtr=bus_clc=bus_qt=1
bus_qt=ВХОД
bus_trd=bus_clc=ВХОД
подготовка флагов, буфер-регистров
/загрузка начального значения в счетчики интервалов/
START
Дежурное ожидание запроса передатчика
bus_clc=0
по получении bus_clc=0
дать задержку в 5uS
считать текущие данные с линии bus_dtr
установить bus_qt=ВЫХОД
установить bus_qt=0
выполнить обработку размещения бита
согласно счетчика бит
если счетчик бит не исчерпан
установить bus_qt=1
дать задержку в 5uS
ожидание bus_clc=1
по получении bus_clc=1
дать задержку в 5uS
повтор приема текущего бита от START
если счетчик бит исчерпан
установить bus_qt=1
bus_qt=ВХОД
дать задержку в 5uS
ожидание bus_clc=1
по получении bus_clc=1
дать задержку в 5uS
перейти к программе обработки полученных данных
синхронизация окончания обработки текущих данных для передатчика
выражается в отсутствии ответа квитирования на строб первого
бита следующей посылки на время внутренних операций приемника
(обработка полученных данных и связанных с ними подпрограмм)
это чтоб легче под иной набор команд/ЯВУ переводить.

Re: Фильтрация данных при передаче.
Добавлено: Пт фев 22, 2019 16:12:27
7seg
@BOB51 , возможно попробую . Мне надо все равно глобальную оптимизацию проводить. Не хватает 20 MHz для TWI+ModBus. Уже поздно, завтра покопаюсь еще пока выходные )
А так было бы очень интересно услышать мнение уважаемых котов по поводу memcpy(). Как я понимаю , это самый быстрый способ от копировать 29 байт (Хотя могу и ошибаться. Эхх как я не люблю считать все таки такты. где мои 12 ядер по 3.5 GHz XD)
Добавлено after 27 minutes 58 seconds:
Чуть не забыл)) Уважаемые коты всех с праздником )
Re: Фильтрация данных при передаче.
Добавлено: Пт фев 22, 2019 17:42:06
GoldenAndy
7seg писал(а):мнение уважаемых котов по поводу memcpy()
Если области не пересекаются (а у вас они не пересекаются), то юзайте.
Только внимательно смотрите, размер копируемых данных у memcpy - задается всегда в байтах.
И сразу встречный вопрос.
Зачем вообще копировать ???
Добавьте в свою структуру еще одну unsigned char переменную в конце, положите в нее 0х00, а передатчику скармливайте не буффер, адрес вашей структуры... и пусть данные улетают прямо из структуры....