Пакетный протокол обмена данными между МК и ПК

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Родился
Сообщения: 13
Зарегистрирован: Чт апр 02, 2009 10:06:25

Сообщение YKolomiets »

Спасибо большое за ответ и за предложенную помощь.
Пошел вникать в CAN.
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 262
Зарегистрирован: Пт ноя 16, 2007 00:40:17
Откуда: Украина

Сообщение foxit »

Liv писал(а):Для каких задач и платформ Вас интересуют примеры? Опишите свою задачу, возможно, что-то подобное найдется.
Программирую AVR.

Задача такая.
На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
Пока объект один то все вроде понятно. А если объектов несколько. Вот тогда уместней использовать пакетный протокол. расстояние порядка 1 км.
Реклама
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

1 км - довольно много. RS-485 потянет на низких скоростях, ну или использовать проводные модемы. Что касается протокола, то Ваш случай не очень сложный, должно хватить той информации, которая есть по ссылке, которую я здесь приводил. В скором времени планирую добавить туда примеров.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Liv писал(а):А для CRC-8 это тоже выгоднее?
Прошу прощения за задержку с ответом, закрутило.
Увы, нет. По крайней мере, для 1-Wire ;-) CRC8 содержит в полиноме столько же единичек, сколько и 16-битная CRC от xmodem, но ведь сама CRC вдвое короче и при прокручивании для такого быстрого способа набор сдвигов и xor-ов становится ну слишком большим. Так навскидку, развёрнутый канонический цикл займёт меньше места и будет выполняться быстрее.

Но есть ещё один способ, занимающий промежуточное положение между каноническим циклом и табличным вычислением и по скорости, и по месту. Используется две таблицы по шестнадцать вхождений и CRC вычисляется таблично для каждого полубайта отдельно.
Если обычную таблицу для байтового алгоритма таблицу из 256 вхождений записать "квадратно", 16*16, то можно заметить, что все значения в таблице есть xor соответствующего значения по вертикали из первой строки и по горизонтали из первого столбца.
Соответсвтенно, для того же далласа, берём две таблицы, в одной из которых сдублирована первая строка, в другой — первый столбец (если я нигде не ошибся в перебивании чисел из таблички в далласовской апноте).

Код: Выделить всё

uint8_t crctable_1w_lo[] = {
	0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65
};
uint8_t crctable_1w_hi[] = {
	0, 157, 35, 190, 70, 219, 101, 248, 140, 17, 175, 50, 202, 233, 116
};
И обновление CRC для одного байта будет выглядеть так

Код: Выделить всё

uint8_t crc_1w_table_4(uint8_t crc, uint8_t data)
{
	uint8_t index = crc ^ data;
	return crctable_1w_lo[ index & 0x0F] ^ crctable_1w_hi[ index >> 4];
}
Будет оно ближе по скорости к циклу или к привычной табличке для целых байтов — зависит от архитектуры контроллера, разрядности его самого и CRC. Так навскидку для AVR при аккуратнов выписывании на асме (с выровненными на границу 16 байт полутаблицами) это будет раза в полтора быстрее, чем развёрнутый в линеечку цикл. А места займёт ощутимо меньше, чем полноразмерная таблица.

Может, когда-то разрожусь на статеечку на эту тему, а может и нет — в сети, вообще говоря, довольно много информации, а писатель статей из меня не такой хороший, как Вы.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 6334
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

foxit писал(а): На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
От каждого датчика - своя линия или на шине?
Если своя - никаких протоколов не надо, принимаются логические сигналы напрямую ( если пинов хватает ) или через мультиплексор.
Если шина и в точке размещения датчика не ставить МК -- ес-сно, никакой протокол не поможет, один замкнутый блокирует всех.
Если ставить МК на каждую точку, и решена проблема его питания ( по отдельному проводу или с разделением питание-сигнал ) опять же никакой протокол не нужен :
хост посылает слейву адрес, и дивайс на этом адресе отвечает одним битом Вкл/Откл.
Или еще проще: хост посылает стартовый маркер, у каждого дивайса есть его временной интервал, во время которого он отвечает опять же одним битом.
В общем, IMHO, по воробьям лучше из рогатки ( если позволит ОЗЖ ). а из установки "Град" - это не комильфо. Я так думаю.

Перечитал вопрос и уточняю: датчики сводятся к одному МК и уж от него - в комп?
Тогда о каком пакетном режиме может идти речь - ПК обменивается с МК по схеме "точка-точка", длина фиксированная - 3 байта. Я бы повторил эти 3 байта 3 раза и потом мажоритарно выбрал корректное значение, не усложняя. Проверено, надежно работает, причем не в информационной системе, а в АСУТП.
Последний раз редактировалось Jack_A Сб ноя 06, 2010 11:54:26, всего редактировалось 1 раз.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

avreal писал(а):если я нигде не ошибся в перебивании чисел из таблички в далласовской апноте
Стоп, что-то я так с чистого листа нахомутал при переносе кода от какого-то из 16-битных алгоритмов. Из таблички в апноте переписал вроде бы правильно, но при прогоне в тестовой программе не всегда сходится. Может, конечно, не сходится в самой тестовой программке, но это уже посмотрю позже, сейчас опять бегу дальше.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6334
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

foxit писал(а): На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
От каждого датчика - своя линия или на шине?
Если своя - никаких протоколов не надо, принимаются логические сигналы напрямую ( если пинов хватает ) или через мультиплексор.
Если шина и в точке размещения датчика не ставить МК -- ес-сно, никакой протокол не поможет, один замкнутый блокирует всех.
Если ставить МК на каждую точку, и решена проблема его питания ( по отдельному проводу или с разделением питание-сигнал ) опять же никакой протокол не нужен :
хост посылает слейву адрес, и дивайс на этом адресе отвечает одним битом Вкл/Откл.
Или еще проще: хост посылает стартовый маркер, у каждого дивайса есть его временной интервал, во время которого он отвечает опять же одним битом.
В общем, IMHO, по воробьям лучше из рогатки ( если позволит ОЗЖ ). а из установки "Град" - это не комильфо. Я так думаю.


Перечитал вопрос и уточняю: датчики сводятся к одному МК и уж от него - в комп?
Тогда о каком пакетном режиме может идти речь - ПК обменивается с МК по схеме "точка-точка", длина фиксированная - 3 байта. Я бы повторил эти 3 байта 3 раза и потом мажоритарно выбрал корректное значение, не усложняя. Проверено, надежно работает, причем не в информационной системе, а в АСУТП.

PS Саша, давно хотел спросить : а кто такой метелик? :-)
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

avreal писал(а):Но есть ещё один способ, занимающий промежуточное положение между каноническим циклом и табличным вычислением и по скорости, и по месту.
Да, с полутаблицами вычислять тоже можно, где-то встречал такую реализацию. Но я все же думаю сделать в исходнике 2 варианта, один из которых можно будет выбирать на этапе компиляции: обычное вычисление с циклом (нужно меньше всего памяти, используется в случаях, когда скорость не важна) и табличный (максимальная скорость, а 256 байт памяти программ сейчас действительно не такая уж проблема). Что касается CRC-16, то используется она только на плохих каналах связи, а там скорость не нужна.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

avreal писал(а):Из таблички в апноте переписал вроде бы правильно
Ага, щас ™
Тупо пропустил один байт, правильно так:

Код: Выделить всё

const uint8_t crctable_1w_hi[] = {
	0, 157, 35, 190, 70, 219, 101, 248, 140, 17, 175, 50, 202, 87, 233, 116
};
Liv писал(а):обычное вычисление с циклом и табличный
Ну для CRC8, пожалуй, да. А 16-битная CRC на 8-битнике указанным выше методом из комбинаций сдвигов места занимает практически как цикл, а по времени почти как табличный. Специфика побайтового беганья к памяти за 16-битными значениями.
Jack_A писал(а):PS Саша, давно хотел спросить : а кто такой метелик? :-)
Привет, Евгений!
Бабочка.
Эта фраза мне несколько лет назад приснилась. Именно фраза, а не картина, мне иногда снятся тексты.
Причём снилась нахально несколько дней подряд.
Дочка потом говорила, что ночью в меня вселился дух Мацуо Басьо :-)
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 262
Зарегистрирован: Пт ноя 16, 2007 00:40:17
Откуда: Украина

Сообщение foxit »

Jack_A писал(а):
foxit писал(а): На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
От каждого датчика - своя линия или на шине?
Если своя - никаких протоколов не надо, принимаются логические сигналы напрямую ( если пинов хватает ) или через мультиплексор.
Если шина и в точке размещения датчика не ставить МК -- ес-сно, никакой протокол не поможет, один замкнутый блокирует всех.
Если ставить МК на каждую точку, и решена проблема его питания ( по отдельному проводу или с разделением питание-сигнал ) опять же никакой протокол не нужен :
хост посылает слейву адрес, и дивайс на этом адресе отвечает одним битом Вкл/Откл.
Или еще проще: хост посылает стартовый маркер, у каждого дивайса есть его временной интервал, во время которого он отвечает опять же одним битом.
В общем, IMHO, по воробьям лучше из рогатки ( если позволит ОЗЖ ). а из установки "Град" - это не комильфо. Я так думаю.

Перечитал вопрос и уточняю: датчики сводятся к одному МК и уж от него - в комп?
Тогда о каком пакетном режиме может идти речь - ПК обменивается с МК по схеме "точка-точка", длина фиксированная - 3 байта. Я бы повторил эти 3 байта 3 раза и потом мажоритарно выбрал корректное значение, не усложняя. Проверено, надежно работает, причем не в информационной системе, а в АСУТП.
от каждого датчика своя линия.
на простых задачах легче изучить в данном случае протокол, а потоп уже внедрять.
Друг Кота
Аватара пользователя
Сообщения: 6334
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

foxit писал(а): от каждого датчика своя линия.
на простых задачах легче изучить в данном случае протокол, а потоп уже внедрять.
Не надо меня так обильно цитировать, загордюсь :-)
Если так, то для приема с датчиков никакого протокола не надо - достаточно соманды in
А передать от МК в порт... Как вариант - то, что я выше описал, преимущество - относительно большая помехоустойчивость. Маловероятно, что побьются 2 или все 3 копии одного байта.
Если передавать со станартным подходом - заголовок пакета - данные - контрольная сумма - ответ; если побился хотя бы один бит, то перезапрос, потери времени.
Но стандартные протоколы, согласен, изучать и пробовать надо, может пригодиться при подключении промышленного прибора, ему уже не прикажешь, он передает, как обучен.
Родился
Сообщения: 1
Зарегистрирован: Чт апр 01, 2010 19:15:36

Сообщение grisha109 »

Доброго времени суток!
Недавно столкнулся с задачей обмена информацией в системе из трех МК AVR ATmega644, в которой два МК должны передавать данные в третий по UART. Для этих целей решил взять за основу протокол WAKE с сайта http://digit-el.com/files/open/wake/wake.html . поскольку пишу в среде CodeVisionAVR, то пришлось переделывать исходный код для IAR под CV.
Поскольку я новичок :) возникло несколько глупых вопросов :) :
Все имеющиеся библиотеки (файлы с .h) я подключил к своему проекту в CV, из С файлов все функции и объявления переменных скопировал в свой проект и подправил под CV. Далее пытаюсь осуществить обмен данными между двумя МК в среде Proteus но ничего не выходит.
В основном цикле обоих микроконтроллеров программы делаю следующее (полный код программы в прикрепленном файле):

Port_Init();
while (1)
{
Tx_Dat[0]=1;
Tx_Dat[1]=2;
Tx_Dat[2]=3;
t1=Rx_Dat[0];
t2=Rx_Dat[1];
t3=Rx_Dat[2];
sprintf(lcd_buffer,"RECEVING");
lcd_clear();
lcd_puts(lcd_buffer);
FloatToLCD(t1,0);
delay_ms(300);
FloatToLCD(t2,1);
delay_ms(300);
FloatToLCD(t3,2);
}
Большая просьба по возможности объяснить каким образом использовать данный протокол применительно к обмену данными между МК
Вложения
wake.rar
(5.09 КБ) 321 скачивание
MyWake.rar
(142.71 КБ) 320 скачиваний
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Готовые примеры есть только для обмена между МК и компьютером. В случае обмена между двумя МК для мастера придется писать функции обмена самостоятельно. Они, конечно, будут не сильно отличаться, но все-таки будут другими. То, что Вы написали в основном цикле, неработоспособно. Нужно заполнить все поля пакета, передать его, затем дождаться приема пакета, анализируя Command, и только затем читать буфер приема.
Контактная информация:
Мявтор!
Аватара пользователя
Сообщения: 384
Зарегистрирован: Ср май 17, 2006 18:39:01
Откуда: Москва

Сообщение Pavel V. »

А я подсмотрел вот такое интересное решение для формирования исходящего пакета (на С++).

Использовать примерно следующим образом:

Код: Выделить всё

void SendInputsState(void) {
	Message message(&uart0);
	message.Send(Commands::CMD_DI_ALL);
	message.Send(0x02);
	uint16_t inputsState = inputs.GetState();
	message.Send(inputsState >> 8);
	message.Send(inputsState);
}
Прием пакета:

Код: Выделить всё

	/*!
	 * @brief Обработчик прерывания по приему
	 */
	virtual void RxHandler(void) {
		uint8_t ch = GetChar();
		if(ch == UartBase<RX, TX>::m_StartOfMessage) {
			UartBase<RX, TX>::m_RxBuffer.flush();
			return;
		} else if(ch == UartBase<RX, TX>::m_EndOfMessage) {
			g_Uart0MessageReceive.Signal();
			return;
		} else if(ch == UartBase<RX, TX>::m_Escape) {
			UartBase<RX, TX>::m_IsEscape = true;
			return;
		}
		if(UartBase<RX, TX>::m_RxBuffer.get_free_size() > 0) {
			if(UartBase<RX, TX>::m_IsEscape) {
				UartBase<RX, TX>::m_RxBuffer.push(ch ^ 0x20);
				UartBase<RX, TX>::m_IsEscape = false;
			} else {
				UartBase<RX, TX>::m_RxBuffer.push(ch);
			}
		}
	}
Обработка пакета вынесена из прерывания и происходит по событию g_Uart0MessageReceive:

Код: Выделить всё

	void Process(uint8_t command, uint8_t length) {
		uint8_t message[128];
		message[0] = command;
		message[1] = length;
		uint16_t crc = 0;
		uint16_t crcRcv = 0;
		bool result = true;
		if(length > 0) {
			result = uart0.Read(&message[2], length);
		}
		if(!result) {
			return;
		}
		crc = Crc::Crc16Block(message, length + 2);
		if(uart0.ReadCrc(crcRcv)) {
			if(crc == crcRcv) {
				Invoke(message);
			}
		}
	}
Удачи!
Вложения
Crc.h
(2.97 КБ) 314 скачиваний
Message.h
(4.33 КБ) 351 скачивание
Контактная информация:
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Я тоже переделал функции работы с WAKE:

Возможно, что-то там сыро, еще мало тестировал.
Вложения
Soft_PC.zip
WAKE со стороны PC
(9.39 КБ) 391 скачивание
Soft_AVR.zip
WAKE со стороны AVR
(10.77 КБ) 434 скачивания
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 262
Зарегистрирован: Пт ноя 16, 2007 00:40:17
Откуда: Украина

Сообщение foxit »

Liv писал(а):Я тоже переделал функции работы с WAKE:

Возможно, что-то там сыро, еще мало тестировал.
а можно примерчик простенький?
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Так там же всё есть. Wake.c - это реализация протокола, а Port.c - пример его использования.
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Леонид Иванович, а отчего Вы именно такой CRC8 используете? Отчего не взять какой-нибудь из "стандартных", типа Dallass 1-wire?
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

А у меня и есть Dallas.
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

А отчего CRC_INIT = 0xde? У Далласа, как я понимаю, 0.
Ответить

Вернуться в «Периферия»