Страница 1 из 1
Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 20:04:05
FUZZY_
имеется прерывание приема передачи которое ложит принятые байты в буфер Uchar bufrd[255];
обычно байты приходят по 2-3 число пришедших байт в Uchar btr; данные идут нерерывно с интервалом 20 mc
пакет данных начинается с кодов в диапазоне {0x80...0x8A }, { 0xC0...0xCA } декодирование пакета, его длина б контрольная сумма однозначно определена спецификацией интерфейса
перед пакетом может быть от 0 до 10 байт - которое относится к маршрутизации пакета данных и для меня интереса не представляет
(величина размера случайная)
0 - пакет данных идет без маршрутизации
typedef unsigned char Uchar;
Uchar bufrd[255];
Uchar btr;
Вопрос как правильно соблюсти условиядля максимального быстродействия приема начала пакета данных ?
Помогите советом
Re: Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 21:00:20
Saadov
Советую прочитать статью "Спецификация протокола WAKE"
http://caxapa.ru/lib/wake/В статье подробно все описано, даны исходники С,ASM, код для ПК и много всего.
Возможно натолкнет вас на мысль.
Re: Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 21:10:06
FUZZY_
Не подходит , там фиксированая преамбула а у меня плавает 0т 0 до 10 бaйт
C2 17 24 34 34 cs = 0 бaйт маршрутизации
00 80 17 24 40 Nx cs = 1 бaйт маршрутизации
55 56 57 58 8a 81 17 24 81 cs = 5 бaйт маршрутизации
и много много других комбинаций с преамбулой от 0 до 10 бaйт
Re: Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 21:29:20
Saadov
Я после работы туго соображаю. Но преамбула показывает код операции, например, а у вас преамбулу еще надо поймать. Как то это не понятно.
C2 17 24 34 34 cs = 0 bit маршрутизации
00 80 17 24 40 Nx cs = 1 bit маршрутизации
55 56 57 58 8a 81 17 24 81 cs = 5 bit маршрутизации
и много много других комбинаций с преамбулой от 0 до 10 bit
бит или байт??
Re: Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 22:02:01
FUZZY_
Байт конечно, bit - это ошибочно
Re: Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 22:43:37
Saadov
Отведите еще один байт под идентификацию, чтобы приняв его устройство сразу знало, что это начало пакета и/или сколько будет по длине преамбула. Я ведь не зря привел вам ссылку на протокол, так как там есть информация по вашему вопросу.
{Идентификатор...Преамбула}{Данные}{CRC}
Например, старший нибл кол-во байт в преамбуле, младший, что делать устройству, ну или наоборот.
Re: Определение начала пакета данных ?
Добавлено: Вт авг 10, 2010 22:46:59
Pooher
А что мешает в начало пакета добавить, скажем, 2 байта которые будут однозначно определять условие?
Re: Определение начала пакета данных ?
Добавлено: Чт авг 12, 2010 19:47:06
FUZZY_
данные отсылает устройство на работу я повлиять никак не могу
Моя задача принять данные и расшифровать предаваемую команду
55 56 57 58 8a - это надо отсечь
81 17 24 81 cs - это надо принять cs- это контрольная сумма посылки которая принимается
f0 - это надо отсечь
81 17 24 81 cs - это надо принять
00 - это надо отсечь
81 17 24 81 cs - это надо принять
пример передачи одной и тойже команды команды (81 17 24 81 cs)
Re: Определение начала пакета данных ?
Добавлено: Вт авг 17, 2010 08:18:23
Kavka
пакет данных начинается с кодов в диапазоне {0x80...0x8A }, { 0xC0...0xCA }
55 56 57 58 8a - это надо отсечь
81 17 24 81 cs - это надо принять cs- это контрольная сумма посылки которая принимается
его длина б контрольная сумма однозначно определена спецификацией интерфейса
Чёт у вас неточности в примерах и вопросе.
Возникает логичный вопрос - а внутри пакета возможны те коды с которых вы указали возможное начало пакета?
Если нет, то это тоже упрощает задачу.
А вообще, вижу два варианта.
1) Принимать поток вы начинаете с известного места - с паузы между пакетами.
Тогда у вас будет простейший конечный автомат (он же state machine по буржуйски) ждущий пока не попадётся байт начала пакета, т.е. пропускающий маршрутную информацию.
Дальше всё просто.
2) Принимать поток вы начинаете с произвольного места.
Тогда надо хранить последние 6 байт и по поступлению каждого нового байта проверять условие по контрольной сумме, начальному байту и структуре пакета данных. При выполнении условий вы получаете пакет данных.
Re: Определение начала пакета данных ?
Добавлено: Вт авг 17, 2010 08:46:28
Pavel V.
Выкладывай нормальное описание протокола, придумаем что-нибудь

Наверняка к этой железяке есть мануал.
Re: Определение начала пакета данных ?
Добавлено: Вт авг 17, 2010 22:22:55
FUZZY_
Pavel V. писал(а):Выкладывай нормальное описание протокола, придумаем что-нибудь

Наверняка к этой железяке есть мануал.
Вот логи протокола
Вот перевод с китайского
Link слоя:
Формат блока:
Запрос:
Fmt TargetAdr + + + SourceAdr Сид + Data + CS
Fmt: 1BYTE, 0x80 плюс длина значения Com и ComInfo
TargetAdr / SourceAdr: адреса назначения / адрес источника 1BYTE
Sid: 1BYTE идентификатор команды
Данные: 0 байт или больше байт команду информации
CS: число байт 1BYTE контрольной накапливаются, и проверить
Ответ:
Fmt TargetAdr + + + SourceAdr Сид + Data + CS
Sid: 1BYTE команды, ЭКЮ ответить, когда байт содержание оборудования просил команду ID + OX40
Уровень приложений:
Чтение информации о версии:
Версии информацию для ответа на ключевые слова F6 после первого кадра первого байта старший бит равен 0, если ситуация: 0F 01 F6 +31 4A ... ... 03
Версии информацию для ответа на ключевые слова F6 после первого кадра первого байта старший бит ситуации, нынешнего положения, прочитав предыдущую версию информация, затем будут сделаны 03 XX 00 03 читать дополнительные значения, пока Совет Первый кадр из ключевых слов, первый байт после самого высокого уровня от 0 до.
Система ввести команду:
82 28 f1 10 89 34
Читает информацию о версии:
82 28 f1 1a 9B 50
Ссылка для поддержания:
82 28 f1 3E d8
С код работает приблизительно 50 на 40 10 - не фильтрует вообще
if(!begin){
//----------
if((bufrd[0]==0)&(btr==1)) return;
else {
p=bufrd; ip=btr;
for(cnt=0; cnt<btr; cnt++) {
if ( (unsigned int )p[0] < 0x80 ) {p++; ip--; }
//----------
else {
if( (unsigned int )p[0] > 0x8A ) {
//----------
if( ( (unsigned int )p[0] >= 0xC0 )||((unsigned int )p[0] <= 0xCF)) {
/* oт C0 до CF начало посылки */
memcpy(Pwork,bufrd,btr);
Pwork+=btr; cb+=btr;
begin=true; // return;
}
else {p++; ip--; }
//----------
}
else {
/*от 80 до 8A начало посылки*/
memcpy(Pwork,bufrd,btr);
Pwork+=btr; cb+=btr;
begin=true;
}
}
};
if( (p!=bufrd)&&(ip>0)) {
if((work[0]&0xc0==0xc0)|| (work[0]&0xc0==0x80)){
memcpy(Pwork,p,ip);
Pwork+=ip; cb+=ip;
begin=true; }
};
// Sleep(15);
} //else
} //end begin
else {
memcpy(Pwork,bufrd,btr);
Pwork+=btr; cb+=btr;
if(cb>4){
switch(work[0]){
case 0x80:
case 0xC0: len= (work[3] +5); break;
default: len=(work[0]&0x3F) +4; break; //определение всей длины пакета
};
/* тут и есть штопор если cb==len то все ок но если cb>len потеря синхронизации и крах декодирования */
if(cb>=len) { Analiz(); ToInit(); // расшифровка команды
}
if (cb>15) ToInit(); // Это выход из зависания
};
}
}
Re: Определение начала пакета данных ?
Добавлено: Чт авг 19, 2010 19:32:35
Pe3ucTop
В вашем случае очень хорошая ситуация для сокращения кода

8x и Cx - отличаются одним битом

т.е. делаем операцию OR ( | 0x40 ) , и получаем диапазон Cx .. для которого делаем две проверки... >=C0 <=CA... ну или бинарными действиями, не суть..
Вопрос зачем у вас преобразование (unsigned int )p[] ?? мне кажется тогда уж правилнее к (unsigned char )p[] , если это не обходимо..
И не очень понял - вы хотите работать уже с буфером или на прямую с принимаемыми данными ??
И правильно ли я понял - вы не можете постоянно следить за принимаемыми данными, т.е. программа отлучается на обработку памяти ..
Просто из вашего сообщения показалось что прерывание для того что-бы копировать теже данные одним пакетом в 256 , хотя правильнее наверно по одмому при приёме, или уже по размеру пакета..
А прерыватся наверное лучше после приёма пакета

или 10-ти пакетов, смотря на как долго надо прерыватся..
Да и программа у вас выдрана кусками, многое не понятно: первая половина понятна, вторая прям белиберда какая-то, не фватает коментариев

Re: Определение начала пакета данных ?
Добавлено: Чт авг 19, 2010 20:15:11
asteroid7
FUZZY_, одного сравнения
Код: Выделить всё
if ( ( ( b >= 0x80 ) && ( b <= 0x8A ) ) || ( ( b >= 0xC0 ) && ( b <= 0xCA ) ) ) { ...
недостаточно. Кстати, в приведённом вашем коде такого условия нет.
Полином контрольной суммы известен? Контрольная сумма чего? нужных шести байт или всех принятых?
По подсчитанному КС надо дополнительно проверять пакет.
Re: Определение начала пакета данных ?
Добавлено: Вт авг 24, 2010 09:28:53
FUZZY_
Вот как должно обрабатываться сообщение:
Пришли данные: 55 56 57 AA F0 82 C0 F0 18 00 4A
Код 55 56 57 AA F0 - должен отброситься
код должен приняться 82 C0 F0 18 00 4A,
где 82 - заголовок, по заголовку мы узнаем количество байт которые нужно принять,
LEN=(количество байт команды) (0x82 - 0x80) +(2 байта адреса ) +( 1 байт контрольной суммы) = 2 +2 +1 =5 ( после 82 мы дожна принять еще 5 байт)
* при количестве байт команды больше 63 имеем вид
[ 80 ] [2 байта внутреней адресации ] [1 байт - количество байт команды] [ n байт команды (оговореных выше)] [1 байт контрольной суммы]
LEN = 2+1+1+n;
С0 F0 - внутрення адресация
18 00 - 2 байта команды
4A - контрольная сумма (usigned char) CS= 82 + C0 + F0 + 18 + 00
аналогично и с кодом С0
Re: Определение начала пакета данных ?
Добавлено: Вт авг 24, 2010 09:55:28
FUZZY_
Вот правленный код
if (!begin) {
if((bufrd[0]==0)&(btr==1)) return; //если пришел 1 байт и он = 0
cb=0;
for(cnt=0; cnt<btr; cnt++) {
if ( ( b >= 0x80 ) && ( b <= 0x8A ) ) { //диапазон 0x80 - 0x8A
memcpy(Pwork,bufrd + cnt ,btr -cnt );
Pwork+=btr-cnt; // указатель на хвост буфера
cb+=btr-cnt;
begin=true;
return ;
}
else{
if ( ( b >= 0xC0 ) && ( b <= 0xCA ) ) { // диапазон С0 - СA
memcpy(Pwork,bufrd + cnt ,btr -cnt );
Pwork+=btr-cnt; // указатель на хвост буфера
cb+=btr-cnt;
begin=true;
return ;
}
else{ //все значения которые не вошли в диапазаны 0x80 - 0x8A , С0 - СA
cb+=0;
begin=false;
}; /* конец проверки диапазана С0 - СA * /
} ; /* конец проверки диапазана 0x80 - 0x8A * /
}
} /* end begin */
else {
memcpy(Pwork,bufrd,btr);
Pwork+=btr;
if(cb>4){
switch(work[0]){
case 0x80:
case 0xC0: len= (work[3] +5); break;
default: len=(work[0]&0x3F) +4; break; //определение всей длины пакета
}
if(cb==len) {
Analiz(); ToInit(); // расшифровка команды
}
if (cb>15) ToInit(); // Это выход из зависания
}
else return;
Re: Определение начала пакета данных ?
Добавлено: Ср авг 25, 2010 16:18:08
Pe3ucTop
Опять неточности:
здесь размер до 10 байт.
//диапазон 0x80 - 0x8A
здесь уже упоминается 63

,
где 82 - заголовок, по заголовку мы узнаем количество байт которые нужно принять,
LEN=(количество байт команды) (0x82 - 0x80) +(2 байта адреса ) +( 1 байт контрольной суммы) = 2 +2 +1 =5 ( после 82 мы дожна принять еще 5 байт)
* при количестве байт команды больше 63 имеем вид
А здесь уже 63 в коде присутствуют ( 0x3F ), хотя зачем если диапазон в том же коде ограничен маской 0x0F ...
default: len=(work[0]&0x3F) +4; break; //определение всей длины пакета
Получается - диапозоны :
0x80 - 0xBF
0xC0 - 0xFF
И опять таки - определяющим остаётся один бит для диапазонов , и один бит для определения нужного диапазона, а остальные - размер..
0b1Dss ssss , где - первая еденица, сравнение принадлежнсоть к диапазонам, D - определяет диапазон , ss ssss - определяет размер - 0...63 ..
Сравнений - излишки !!
Код возможно выложу позже, а ведь так лень за когото переделывать

Ошибки в алгоритме (по куску кода, что дан):
- в буфере может быть только чать пакета , и вы только с ней будете оперировать
- приём может начатся с середины пакета, если вклинится в приём, и в данных пакета будет байты Ваших заголовков..
- что-то мне подсказывает, что если пакет больше 15 , он вообще не будет обрабатыватся

- не ясно - каких размеров у вас буферы ??
- не ясно - каким образом сбрасывается буфер или сдвигается по кругу и т.п.
- некоторые переменные - не понятны : (b , cb , work[])
Re: Определение начала пакета данных ?
Добавлено: Ср авг 25, 2010 22:23:09
FUZZY_
* при количестве байт команды больше 63 имеем вид
[ 80 ] [2 байта внутреней адресации ] [1 байт - количество байт команды] [ n байт команды (оговореных выше)] [1 байт контрольной суммы]
LEN = 2+1+1+n;
Это общий стандарт протокола ( ответ на запрос) , в моем случае я никогда не буду принимать пакет больше 15 , так как обрабатываю только
запросы.
#define BUFSIZE 255
Uchar work[BUFSIZE]; //буфер обрабатываемой команды тут лежит только нужные нам байты
cb - количество байт принимаемой команды
btr -количество байт в приемном буфере на момент когда мы к нему обращаемся ( после его чтения он заполнтся с 0 позиции)
Uchar bufrd[BUFSIZE]; // приемный буфер
Pwork=work; // в самом начале или после обработки команды
Например
код должен приняться 82 C0 F0 18 00 4A,
Расположение в буфере
work[0]=0x82
work[1]=0xC0
work[2]=0xF0
work[3]=0x18
work[4]=0x00
work[5]=0x4A
work[6]=0
work[..]=0
work[255]=0
Re: Определение начала пакета данных ?
Добавлено: Пт авг 27, 2010 23:02:13
FUZZY_
http://www.cplusplus.com/reference/stl/deque/ Кусок рабочей программы на С++ , как перевести для МК в части с deque
unsigned int cnt;
deque <unsigned char> msg;
for(cnt=0;cnt<btr;cnt++) {
msg.push_back(bufrd[cnt]);
}
//----------
cb+=btr;
if( (msg.front()&0x80)!=0x80 ) {
for(cnt=0; cnt< msg.size(); cnt++) {
if( ((msg[cnt]>=0x80)&&(msg[cnt]<0x8A))||((msg[cnt]>=0xC0)&&(msg[cnt]<=0xCA))) {
msg.erase(msg.begin(), msg.begin()+cnt); //удалили элементы которые не соотв условию
break; //вышли из цикла
}
cb--;
}
//----------
}
for(cnt=0;cnt< msg.size(); cnt++) { work[cnt]=msg[cnt]; } //заполнили массив для обработки
//----------
msg.clear();
if(cb>4) {
Form1->StatusBar1->Panels->Items[1]->Text="Start";
//----------
switch(work[0]) { //вычисление длины обрабатываемого сообщения .. тут надо сделать так чтобы оно считало только раз ...
case 0x80:
case 0xC0: len= (work[3] +5); addlen=true; break;
default: len=(work[0]&0x3F) +4; addlen=false; break;
};
//----------
Form1->Edit22->Text=IntToStr((int)len);
//----------
if(cb==len) {
Analiz(); ToInit(); //расшифровка сообщения
Form1->StatusBar1->Panels->Items[1]->Text="Stop";
}
if (cb>15) ToInit(); // если не произошла рашифровка (нет данных в базе данных)
}
else{ Form1->StatusBar1->Panels->Items[1]->Text="Wait"; }