Страница 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.
Единственный гвоздь - проект под ассемблером.
8)

Re: Фильтрация данных при передаче.

Добавлено: Пт фев 22, 2019 10:14:02
7seg
[uquote="BOB51",url="/forum/viewtopic.php?p=3575545#p3575545"]Единственный гвоздь - проект под ассемблером.
8)[/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
;
;----------------------------------------------
;
собственно переделывается под любой иной МК с использованием соответствующего набора команд в оном применяемого.
А обработчик принятых данных на собственное усмотрение.
:wink:
И там же в проекте "просто словами" записан алгоритм (брался за основу при разработке):
для передатчика
Спойлер;
; общие положения по приемопередатчику внутренней шины обмена
; команд/данных
передача идет младшими битами вперед
данные пересылаются в прямом коде
перед каждым байтом следует бит ключа типа данных
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
перейти к программе обработки полученных данных

синхронизация окончания обработки текущих данных для передатчика
выражается в отсутствии ответа квитирования на строб первого
бита следующей посылки на время внутренних операций приемника
(обработка полученных данных и связанных с ними подпрограмм)
это чтоб легче под иной набор команд/ЯВУ переводить.
:beer:

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, а передатчику скармливайте не буффер, адрес вашей структуры... и пусть данные улетают прямо из структуры....