Пошел вникать в CAN.
Пакетный протокол обмена данными между МК и ПК
- Сообщения: 13
- Зарегистрирован: Чт апр 02, 2009 10:06:25
Спасибо большое за ответ и за предложенную помощь.
Пошел вникать в CAN.
Пошел вникать в CAN.
- Реклама
Программирую AVR.Liv писал(а):Для каких задач и платформ Вас интересуют примеры? Опишите свою задачу, возможно, что-то подобное найдется.
Задача такая.
На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
Пока объект один то все вроде понятно. А если объектов несколько. Вот тогда уместней использовать пакетный протокол. расстояние порядка 1 км.
1 км - довольно много. RS-485 потянет на низких скоростях, ну или использовать проводные модемы. Что касается протокола, то Ваш случай не очень сложный, должно хватить той информации, которая есть по ссылке, которую я здесь приводил. В скором времени планирую добавить туда примеров.
Прошу прощения за задержку с ответом, закрутило.Liv писал(а):А для CRC-8 это тоже выгоднее?
Увы, нет. По крайней мере, для 1-Wire
Но есть ещё один способ, занимающий промежуточное положение между каноническим циклом и табличным вычислением и по скорости, и по месту. Используется две таблицы по шестнадцать вхождений и 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
};Код: Выделить всё
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];
}Может, когда-то разрожусь на статеечку на эту тему, а может и нет — в сети, вообще говоря, довольно много информации, а писатель статей из меня не такой хороший, как Вы.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
От каждого датчика - своя линия или на шине?foxit писал(а): На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
Если своя - никаких протоколов не надо, принимаются логические сигналы напрямую ( если пинов хватает ) или через мультиплексор.
Если шина и в точке размещения датчика не ставить МК -- ес-сно, никакой протокол не поможет, один замкнутый блокирует всех.
Если ставить МК на каждую точку, и решена проблема его питания ( по отдельному проводу или с разделением питание-сигнал ) опять же никакой протокол не нужен :
хост посылает слейву адрес, и дивайс на этом адресе отвечает одним битом Вкл/Откл.
Или еще проще: хост посылает стартовый маркер, у каждого дивайса есть его временной интервал, во время которого он отвечает опять же одним битом.
В общем, IMHO, по воробьям лучше из рогатки ( если позволит ОЗЖ ). а из установки "Град" - это не комильфо. Я так думаю.
Перечитал вопрос и уточняю: датчики сводятся к одному МК и уж от него - в комп?
Тогда о каком пакетном режиме может идти речь - ПК обменивается с МК по схеме "точка-точка", длина фиксированная - 3 байта. Я бы повторил эти 3 байта 3 раза и потом мажоритарно выбрал корректное значение, не усложняя. Проверено, надежно работает, причем не в информационной системе, а в АСУТП.
Последний раз редактировалось Jack_A Сб ноя 06, 2010 11:54:26, всего редактировалось 1 раз.
- Реклама
Стоп, что-то я так с чистого листа нахомутал при переносе кода от какого-то из 16-битных алгоритмов. Из таблички в апноте переписал вроде бы правильно, но при прогоне в тестовой программе не всегда сходится. Может, конечно, не сходится в самой тестовой программке, но это уже посмотрю позже, сейчас опять бегу дальше.avreal писал(а):если я нигде не ошибся в перебивании чисел из таблички в далласовской апноте
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
От каждого датчика - своя линия или на шине?foxit писал(а): На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
Если своя - никаких протоколов не надо, принимаются логические сигналы напрямую ( если пинов хватает ) или через мультиплексор.
Если шина и в точке размещения датчика не ставить МК -- ес-сно, никакой протокол не поможет, один замкнутый блокирует всех.
Если ставить МК на каждую точку, и решена проблема его питания ( по отдельному проводу или с разделением питание-сигнал ) опять же никакой протокол не нужен :
хост посылает слейву адрес, и дивайс на этом адресе отвечает одним битом Вкл/Откл.
Или еще проще: хост посылает стартовый маркер, у каждого дивайса есть его временной интервал, во время которого он отвечает опять же одним битом.
В общем, IMHO, по воробьям лучше из рогатки ( если позволит ОЗЖ ). а из установки "Град" - это не комильфо. Я так думаю.
Перечитал вопрос и уточняю: датчики сводятся к одному МК и уж от него - в комп?
Тогда о каком пакетном режиме может идти речь - ПК обменивается с МК по схеме "точка-точка", длина фиксированная - 3 байта. Я бы повторил эти 3 байта 3 раза и потом мажоритарно выбрал корректное значение, не усложняя. Проверено, надежно работает, причем не в информационной системе, а в АСУТП.
PS Саша, давно хотел спросить : а кто такой метелик?
Да, с полутаблицами вычислять тоже можно, где-то встречал такую реализацию. Но я все же думаю сделать в исходнике 2 варианта, один из которых можно будет выбирать на этапе компиляции: обычное вычисление с циклом (нужно меньше всего памяти, используется в случаях, когда скорость не важна) и табличный (максимальная скорость, а 256 байт памяти программ сейчас действительно не такая уж проблема). Что касается CRC-16, то используется она только на плохих каналах связи, а там скорость не нужна.avreal писал(а):Но есть ещё один способ, занимающий промежуточное положение между каноническим циклом и табличным вычислением и по скорости, и по месту.
Ага, щас ™avreal писал(а):Из таблички в апноте переписал вроде бы правильно
Тупо пропустил один байт, правильно так:
Код: Выделить всё
const uint8_t crctable_1w_hi[] = {
0, 157, 35, 190, 70, 219, 101, 248, 140, 17, 175, 50, 202, 87, 233, 116
};Ну для CRC8, пожалуй, да. А 16-битная CRC на 8-битнике указанным выше методом из комбинаций сдвигов места занимает практически как цикл, а по времени почти как табличный. Специфика побайтового беганья к памяти за 16-битными значениями.Liv писал(а):обычное вычисление с циклом и табличный
Привет, Евгений!Jack_A писал(а):PS Саша, давно хотел спросить : а кто такой метелик?
Бабочка.
Эта фраза мне несколько лет назад приснилась. Именно фраза, а не картина, мне иногда снятся тексты.
Причём снилась нахально несколько дней подряд.
Дочка потом говорила, что ночью в меня вселился дух Мацуо Басьо
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
от каждого датчика своя линия.Jack_A писал(а):От каждого датчика - своя линия или на шине?foxit писал(а): На объекте 20 датчиков(нормально замкнутых кнопок). МК опрашивает датчики и по УАРТ пересылает на центральный пульт.
Если своя - никаких протоколов не надо, принимаются логические сигналы напрямую ( если пинов хватает ) или через мультиплексор.
Если шина и в точке размещения датчика не ставить МК -- ес-сно, никакой протокол не поможет, один замкнутый блокирует всех.
Если ставить МК на каждую точку, и решена проблема его питания ( по отдельному проводу или с разделением питание-сигнал ) опять же никакой протокол не нужен :
хост посылает слейву адрес, и дивайс на этом адресе отвечает одним битом Вкл/Откл.
Или еще проще: хост посылает стартовый маркер, у каждого дивайса есть его временной интервал, во время которого он отвечает опять же одним битом.
В общем, IMHO, по воробьям лучше из рогатки ( если позволит ОЗЖ ). а из установки "Град" - это не комильфо. Я так думаю.
Перечитал вопрос и уточняю: датчики сводятся к одному МК и уж от него - в комп?
Тогда о каком пакетном режиме может идти речь - ПК обменивается с МК по схеме "точка-точка", длина фиксированная - 3 байта. Я бы повторил эти 3 байта 3 раза и потом мажоритарно выбрал корректное значение, не усложняя. Проверено, надежно работает, причем не в информационной системе, а в АСУТП.
на простых задачах легче изучить в данном случае протокол, а потоп уже внедрять.
Не надо меня так обильно цитировать, загордюсьfoxit писал(а): от каждого датчика своя линия.
на простых задачах легче изучить в данном случае протокол, а потоп уже внедрять.
Если так, то для приема с датчиков никакого протокола не надо - достаточно соманды in
А передать от МК в порт... Как вариант - то, что я выше описал, преимущество - относительно большая помехоустойчивость. Маловероятно, что побьются 2 или все 3 копии одного байта.
Если передавать со станартным подходом - заголовок пакета - данные - контрольная сумма - ответ; если побился хотя бы один бит, то перезапрос, потери времени.
Но стандартные протоколы, согласен, изучать и пробовать надо, может пригодиться при подключении промышленного прибора, ему уже не прикажешь, он передает, как обучен.
- Сообщения: 1
- Зарегистрирован: Чт апр 01, 2010 19:15:36
Доброго времени суток!
Недавно столкнулся с задачей обмена информацией в системе из трех МК 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);
}
Большая просьба по возможности объяснить каким образом использовать данный протокол применительно к обмену данными между МК
Недавно столкнулся с задачей обмена информацией в системе из трех МК 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 скачиваний
Готовые примеры есть только для обмена между МК и компьютером. В случае обмена между двумя МК для мастера придется писать функции обмена самостоятельно. Они, конечно, будут не сильно отличаться, но все-таки будут другими. То, что Вы написали в основном цикле, неработоспособно. Нужно заполнить все поля пакета, передать его, затем дождаться приема пакета, анализируя Command, и только затем читать буфер приема.
А я подсмотрел вот такое интересное решение для формирования исходящего пакета (на С++).
Использовать примерно следующим образом:
Прием пакета:
Обработка пакета вынесена из прерывания и происходит по событию g_Uart0MessageReceive:
Удачи!
Использовать примерно следующим образом:
Код: Выделить всё
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);
}
}
}
Код: Выделить всё
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);
}
}
}
Я тоже переделал функции работы с WAKE:
Возможно, что-то там сыро, еще мало тестировал.
Возможно, что-то там сыро, еще мало тестировал.
- Вложения
-
- Soft_PC.zip
- WAKE со стороны PC
- (9.39 КБ) 391 скачивание
-
- Soft_AVR.zip
- WAKE со стороны AVR
- (10.77 КБ) 434 скачивания
а можно примерчик простенький?Liv писал(а):Я тоже переделал функции работы с WAKE:
Возможно, что-то там сыро, еще мало тестировал.
Так там же всё есть. Wake.c - это реализация протокола, а Port.c - пример его использования.
- Сообщения: 1430
- Зарегистрирован: Вт июн 07, 2011 08:03:18
Леонид Иванович, а отчего Вы именно такой CRC8 используете? Отчего не взять какой-нибудь из "стандартных", типа Dallass 1-wire?
А у меня и есть Dallas.
- Сообщения: 1430
- Зарегистрирован: Вт июн 07, 2011 08:03:18
А отчего CRC_INIT = 0xde? У Далласа, как я понимаю, 0.


