Чтение состояния порта в переменную
- Войдите на сайт для отправки комментариев
Втр, 02/07/2019 - 22:29
byte P0 = (1 << 0); byte P1 = (1 << 1); byte P2 = (1 << 2); byte P3 = (1 << 3); byte P4 = (1 << 4); byte P5 = (1 << 5); byte P6 = (1 << 6); byte P7 = (1 << 7); #define D2_INPUT (DDRD &= ~P2) #define D3_INPUT (DDRD &= ~P3) #define D4_INPUT (DDRD &= ~P4) #define D5_INPUT (DDRD &= ~P5) #define D6_INPUT (DDRD &= ~P6) #define D7_INPUT (DDRD &= ~P7) #define D8_INPUT (DDRB &= ~P0) #define D9_INPUT (DDRB &= ~P1) #define READ (PIND & P2)+(PIND & P3)+(PIND & P4)+(PIND & P5)+(PIND & P6)+(PIND & P7)+(PINB & P0)+(PINB & P1) void setup() { D2_INPUT; D3_INPUT; D4_INPUT; D5_INPUT; D6_INPUT; D7_INPUT; D8_INPUT; D9_INPUT; Serial.begin(19200); Serial.println("Start"); } void loop() { Serial.println(READ); delay(1000); }
Мне нужно отправить с одной ардуины на другую состояние, к примеру, 8 пинов ардуино.
Если 2 и 9 пины HIGH,остальные LOW, то получаю число 6
Как на второй ардуине мне расшифровать число 6 в формат 100000001
Т.е. упаковывали Вы по портам, а распаковать надо в номера ардуиновсикх пинов, так что ли? Или я недопонял?
Ну да, хотелось бы отправлять не
а что-то короче,в hEX это 101
Не знаю, Вы как-то сложно придумали. У Вас что за контроллер? 328? Там же можно спокойно прочитать в 4 байта все пины, сколько есть и отправить эти 4 байта. Или другой контроллер?
328, как это сделать?
Только мне не все пины нужны, а определенные.
Сейчас мне убегать надо, если у Вас не получится, скажите, я завтра могу расписать на пример. Но идея такая. Определяете структуру s из 4 байтов. В эти байты пихаете PINA, PINB, PINC и PIND. ОТправляете эти 4 байта (Serial.write(&s, sizeof(s));
на стороне приёмника принимаете эти 4 байта и имеете все пины.
И пофиг, что не все нужны - передавайте все. Оно ж всего 4 байта, делов-то. Зато никаких распаковок - что передали, то и приняли.
Попробуйте, если будет затык, скажите и заходите завтра к обеду, я постараюсь пример сделать.
Irinka, теоретически Вам нужны битовые операции и сдвиги.
Но в данном конкретном случае даже сдвиги, похоже, не нужны:
Если вперемешку пины будут в байте, то через 8-битный union с битовыми полями под состояние пина попонятнее, по-моему.
Спасибо. Попробую разобраться.
А если мне в порт нужно отправить запись:
Serial.println("1234,100100011");
Так же будет неправильно*?
Можно же зашифровать' все что после запятой, а на другой ардуинке расшифровать.
На второй ардуинке нужен формат 1001...
Что такое 1234?
До запятой будет четырехзначное число, адрес устройства которому передаю, после запятой текст сообщения в формате 1000100...
В Ващем примере, Вы передаёте 11 байтов. Я же Вам предлагаю, передавать пять (ну, если с контрольной суммой, то шесть) и никакого разбора на стороне приёмника. Сделайте, Вам понравится. Ну, или скажите, я пример напишу.
Если не сложно, попрошу у Вас пример
CRC можно посчитать XOR-ом всех байтов или посложнее чего найти типа MAXIM Dallas CRC8 (из библиотеки Dallas Temperature). ptrPacket чисто для удобства объявлен.
XOR наверное пошустрее будет
когда надо быстро и не заморачиваться, я делаю XOR со сдвигом. Но, заслушаем ЕвгенияП, нам есть чему у него поучица. :)
Это всё красиво, конечно, но слишком сложно для ТС, КМК. ЕвгенийП предлагает значительно проще.) Типа,
А на приёмной стороне уже выделяем нужные биты через маски.
А когда задышит, тогда уже можно будет добавлять - КС, маркер начала и т.п.
Так, ну поехали.
Ваш адрес (четырёхзначное число) помещается в двухбайтовый unsigned. А портов у 328-ой всего три (B, C и D). Поэтому мы будем передавать РОВНО ПЯТЬ байтов. В них поместится адрес и все порты.
Сначала напишем структуру для передачи. Она будет жить в файле «Packet.h». Это файл нужно будет включать И в передатчик, И в приёмник. Лучше включать один и тот же файл (сделать его «библиотекой»), чтобы избегнуть недоразумений, когда в одном месте поменяла, а в другом забыла.
Вот он файл «Packet.h»
Здесь Вам может оказаться незнакомым приём с использованием Printable (строка №4) и функция printTo (строки №№ 15-22). Не пугайтесь. Это для того, чтобы готовую структуру можно было просто пихать в print / println и система знала как её печатать. Подробно я описывал это технику в отдельной теме.
Функция fillUp нужна, чтобы собрать значения реальных портов в нашу структуру. Это нужно делать перед отправкой структуры другой ардуине.
А так всё понятно? Размер структуры – 5 байтов, можете проверить это, напечатав её sizeof.
Теперь скетч мастера - передатчика. Он просто раз в полсекунды заполняет структуру текущими значениями портов, печатает её в сериал для контроля и отправляет её приёмнику через SoftSerial. Заодно, он инвертирует 13-ый пин, чтобы хоть что-то менялось. На приёмнике мы будем значение этого пина печатать.
Вот текст мастера.
Приёмник просто ждёт пока структура придёт полностью, а когда придёт – печатает её и заодно печатает значение 13-го пина (как пример для Вас как к пинам добираться). Вот он.
Теперь Вы можете всё это запустить, наблюдать за печатью и попробовать менять на мастере состяния пинов (замыкайте их то на землю, то на питание) - увидите, как их состояния будут правильно передаваться.
------------------------------------------------------
------------------------------------------------------
Для этого в структуру добавим функцию getCRC, которая считает контрольную сумму. Также добавим поле crc и функция setCRC. Последнюю нужно вызывать непосредственно перед отправкой структуры. Она посчитает контрольную сумму и запишет её в поле crc. На приёмнике же нужно посчитать контрольную сумму полученного пакета (функцией getCRC) и сравнить её с полученным полем crc. Если сравнилось нормально, значит с высокой вероятностью ошибок не было.
Вот тексты.
«Packet.h»
Передатчик
Приёмник
В передатчике я добавил порчу пакета (уже после расчёта crc) на каждой десятой посылке, чтобы убедиться, что приёмник адекватно реагирует на ошибку. Можете запустить и убедиться, что всё работает нормально.
Ну, вроде так, если я нигде ничего не ляпнул. Если что, спрашивайте.
Green, это у меня-то сложный пример? ))
Евгений Петрович, а восстановление по CRC? Для полного Иринкиного щастья )))
Green, это у меня-то сложный пример? ))
Нет, теперь точно не сложный.))
а восстановление по CRC? Для полного Иринкиного щастья )))
Без поллитры? Нее ...
Будет чем вечером заняться. Буду изучать. Большое огромное спасибо за оказываемую помощь.
Green, это у меня-то сложный пример? ))
А у меня-то чего сложного? принтабле что-ли? Так это не про решаемую задачу а про удобство отладочной печати. А по задаче - структура и write c readBytes, где там сложности-то?
Работает. Теперь буду разбираться в коде
Если что, спрашивайте.
Начала разбираться:
почему rerurn здесь, а не перед закрывающей скобкой?
Потому, что он относится ко всему, что ниже. Строки №№32-37 это по сути одна строка (return .....;). Просто разнёс на разные строки, чтобы не писать такую длинную. Посмотрите где точка с запятой - одна в самом конце.
Тёмный лес - это стандартная процедура подсчёта 8-битной CRC. Я её не сам придумал, она есть в любом учебнике и, кажется, даже в википедии (сейчас проверю) ....
А мне жутко интересно узнать, но стыдно спросить.... Но спрошу (если что - к нужным букварям отправьте или скажите - тебе ещё рано :-) )
вот эта сокращённая запись:
crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
можно ее расшифровать, так сказать?
Потому, что он относится ко всему, что ниже. Строки №№32-37 это по сути одна строка (return .....;). Просто разнёс на разные строки, чтобы не писать такую длинную. Посмотрите где точка с запятой - одна в самом конце.
Поняла.
пишу...сейчас кое-что првоерю и отпишусь дальше. Почему-то в протеусе не работает проект
crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
можно ее расшифровать, так сказать?
Тернарная условная операция
Почему-то в протеусе не работает проект
Это известный косяк модели в протеусе. Сделайте там не ардуины, а просто ATmega382P - заработает.
В википедии на нашёл, но не суть - это одна из стандартных процедур (есть и другие), я её просто использую готовую.
Вот момент который не понимаю:
В слейве получаю:
получаю в мастере строку 1234108338, но в этой строке не 38 байт же
Я совсем не поняла, с мастера я отправляю всю эту строку
address=1234; pinB=1; pinC=0; pinD=83; crc=38
или только значение переменных 1234; 1 0 83 38
как слейв понимает что 1234 это адрес, 1 это pinB...как просиходит этот "парсинг"?
address=1234; pinB=1; pinC=0; pinD=83; crc=38
address=1234; pinB=1; pinC=0; pinD=83; crc=38
Понятно, что раз 38 значит 38 и должно быть)
Понятно, что раз 38 значит 38 и должно быть)
Правильный подход к пониманию.
Если мастер послал CRC пакета = 38, то и слейв при проверочном расчёте (тем же способом) CRC на основании данных в пакете должен получить 38. Если вышло что-то другое - пакет битый.
Я совсем не поняла, с мастера я отправляю всю эту строку
address=1234; pinB=1; pinC=0; pinD=83; crc=38
или только значение переменных 1234; 1 0 83 38
А Вы ещё мой пример гляньте - он про то же самое, но несколько проще (хотя ЕвгенийП так не считает, конечно).
Если вышло что-то другое - пакет битый.
и если это настоящий crc то запускается процедура воостановления битой информации, а если не удалось, то пакет отбрасывается и отправляется запрос на переотправку битого пакета...
Объясниете, не понимаю:
На слейве:
В каком месте в переменную ports.text произошло присвоение отправленного текста?
В sSerial.readBytes().
В struct у нас как данные хранятся? Последовательно сложенными в линеечку, одна за другой: address | pinB | pinC | pinD | ...
Т.е. фактически - массив байтов, из которых две ячейки отданы address, по одной pinX и т.д.
write() этот массив выплёскивает в сторону слейва, слейв принимает и складывает в такой же массив на своей стороне, на который можно смотреть через шаблон структуры. Как в советском "Шерлоке Холмсе" показано - накладывают на страницу книги черный лист с дырками и читают тайное слово.
Ну, как в каком, Эта переменная - часть структуры, Вы ей на мастере что-то присвоили? А структура передаётеся полностью! Вот она и передалась, как часть структуры.
Только, если Вы хотите добавлять поля в структуру, дробавляйте их ДО crc, а не после. crc должна быть последним полем в структуре. После неё никаких полей, иначе может сломаться подсчёт crc.
А структура передаётеся полностью!
Так понятнее. Спасибо.
__attribute__ ((packed));
Что значит эта строчка?
Хочу убрать отладочную печать. Где я накосячила?
__attribute__ ((packed));
Что значит эта строчка?
При опциях IDE "из коробки" - ничего, но она страхует от неприятностей, если опции компилятора поменяются. Она требует, чтобы каждый элемент структуры занимал минимально-достаточное место в памяти. А бывает, что каждый элемент занимает целое количество int'ов (или даже long'ов) - это от опций зависит. Но прямое указание в программе имеет более высокий приорите, чем опции. Потому, лучше указать и не думать какие там опции выставлены.
Хочу убрать отладочную печать. Где я накосячила?
Вроде, нигде. Только в print пихать уже нильзя. А что, ругается? Что за ругань?
Точно, на это и ругался //Serial.println(ports);
Спасибо
Irinka, а вот залетел к вам (в вашу сеть) один лишний байт из вне и что? Всё, накрылась ваша богодельня? Где начало, где конец, где данные, где КС...?