Чтение состояния порта в переменную

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
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

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Т.е. упаковывали Вы по портам, а распаковать надо в номера ардуиновсикх пинов, так что ли? Или я недопонял?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Ну да, хотелось бы отправлять не 

Serial.println("100000001");

а что-то короче,в hEX это 101

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не знаю, Вы как-то сложно придумали. У Вас что за контроллер? 328? Там же можно спокойно прочитать в 4 байта все пины, сколько есть и отправить эти 4 байта. Или другой контроллер?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

328, как это сделать?

Только мне не все пины нужны, а определенные.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Сейчас мне убегать надо, если у Вас не получится, скажите, я завтра могу расписать на пример. Но идея такая. Определяете структуру s из 4 байтов. В эти байты пихаете PINA, PINB, PINC и PIND. ОТправляете эти 4 байта (Serial.write(&s, sizeof(s));

на стороне приёмника принимаете эти 4 байта и имеете все пины.

И пофиг, что не все нужны - передавайте все. Оно ж всего 4 байта, делов-то. Зато никаких распаковок - что передали, то и приняли.

Попробуйте, если будет затык, скажите и заходите завтра к обеду, я постараюсь пример сделать.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Irinka, теоретически Вам нужны битовые операции и сдвиги.

Но в данном конкретном случае даже сдвиги, похоже, не нужны:

result = (PIND & 0xfc) | (PINB & 3);

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Если вперемешку пины будут в байте, то через 8-битный union с битовыми полями под состояние пина попонятнее, по-моему.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Спасибо. Попробую разобраться.
А если мне в порт нужно отправить запись:

Serial.println("1234,100100011");
Так же будет неправильно*?
Можно же зашифровать' все что после запятой, а на другой ардуинке расшифровать.
На второй ардуинке нужен формат 1001...

sadman41
Offline
Зарегистрирован: 19.10.2016

Что такое 1234?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

До запятой будет четырехзначное число, адрес устройства которому передаю, после запятой текст сообщения в формате 1000100...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В Ващем примере, Вы передаёте 11 байтов. Я же Вам предлагаю, передавать пять (ну, если с контрольной суммой, то шесть) и никакого разбора на стороне приёмника. Сделайте, Вам понравится. Ну, или скажите, я пример напишу.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Если не сложно, попрошу у Вас пример

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:
А если мне в порт нужно отправить запись: Serial.println("1234,100100011");

CRC можно посчитать XOR-ом всех байтов или посложнее чего найти типа MAXIM Dallas CRC8 (из библиотеки Dallas Temperature). ptrPacket чисто для удобства объявлен.

typedef struct {
  uint8_t deviceAddr;
  uint8_t stateDoor01 : 1;
  uint8_t stateDoor02 : 1;
  uint8_t stateDoor03 : 1;
  uint8_t stateDoor04 : 1;
  uint8_t stateIgnition : 1;
  uint8_t stateLight : 1;
  uint8_t stateSound : 1;
  uint8_t stateGPS : 1;
  uint8_t CRC;
} packet_t;


void setup() {
  packet_t packet;
  uint8_t* ptrPacket = (uint8_t*) &packet;

  packet.deviceAddr = 0xF1;
  packet.stateDoor01 = digitalRead(A1);
  packet.stateDoor02 = digitalRead(A2);
...
  packet.stateIgnition = digitalRead(2);
  packet.stateGPS = digitalRead(8);
  // packet.CRC = calculateCRC(ptrPacket, sizeof(packet) - 1);
  Serial.write(ptrPacket, sizeof(packet));
  ...
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Irinka пишет:
Если не сложно, попрошу у Вас пример
Хорошо, сегодня, чуть позже - через час-два.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

XOR наверное пошустрее будет

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

когда надо быстро и не заморачиваться, я делаю XOR со сдвигом.  Но, заслушаем ЕвгенияП, нам есть чему у него поучица. :)

Green
Offline
Зарегистрирован: 01.10.2015

Это всё красиво, конечно, но слишком сложно для ТС, КМК. ЕвгенийП предлагает значительно проще.) Типа,

Serial.write(123); адрес
Serial.write(PINB);
Serial.write(PINC);
Serial.write(PIND);

А на приёмной стороне уже выделяем нужные биты через маски.
А когда задышит, тогда уже можно будет добавлять - КС, маркер начала и т.п.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, ну поехали.

Ваш адрес (четырёхзначное число) помещается в двухбайтовый unsigned. А портов у 328-ой всего три (B, C и D). Поэтому мы будем передавать РОВНО ПЯТЬ байтов. В них поместится адрес и все порты.

Сначала напишем структуру для передачи. Она будет жить в файле «Packet.h». Это файл нужно будет включать И в передатчик, И в приёмник. Лучше включать один и тот же файл (сделать его «библиотекой»), чтобы избегнуть недоразумений, когда в одном месте поменяла, а в другом забыла.

Вот он файл «Packet.h»

#ifndef	PACKET_H
#define	PACKET_H

struct AllThePorts : public Printable{
	uint16_t address;
	uint8_t	pinB, pinC, pinD;

	// Читает порты и заполняет структуру
	void fillUp(void) {
		pinB = PINB;
		pinC = PINC;
		pinD = PIND;
	}

	// Печатает структуру для отладки
	size_t printTo(Print& p) const {
		return 
			p.print("address=") + p.print(address) +
			p.print("; pinB=") + p.print(pinB, HEX) +
			p.print("; pinC=") + p.print(pinC, HEX) +
			p.print("; pinD=") + p.print(pinD, HEX);
	}
}  __attribute__ ((packed));

#endif	//	PACKET_H

Здесь Вам может оказаться незнакомым приём с использованием Printable (строка №4) и функция printTo (строки №№ 15-22). Не пугайтесь. Это для того, чтобы готовую структуру можно было просто пихать в print / println и система знала как её печатать. Подробно я описывал это технику в отдельной теме.

Функция fillUp нужна, чтобы собрать значения реальных портов в нашу структуру. Это нужно делать перед отправкой структуры другой ардуине.

А так всё понятно? Размер структуры – 5 байтов, можете проверить это, напечатав её sizeof.

Теперь скетч мастера - передатчика. Он просто раз в полсекунды заполняет структуру текущими значениями портов, печатает её в сериал для контроля и отправляет её приёмнику через SoftSerial. Заодно, он инвертирует 13-ый пин, чтобы хоть что-то менялось. На приёмнике мы будем значение этого пина печатать. 

Вот текст мастера.

#include <SoftwareSerial.h>
#include "Packet.h"

const int8_t softRX = 6;
const int8_t softTX = 7;

SoftwareSerial sSerial(softRX, softTX);

void setup(void) {
	Serial.begin(57600);
	sSerial.begin(9600);
	pinMode(LED_BUILTIN, OUTPUT);
	Serial.println("MASTER console");
	delay(100);
}

void loop(void) {
	AllThePorts ports;
	ports.address = 1234; // адрес приёмника
	ports.fillUp();
	Serial.println(ports);
	sSerial.write((char *) & ports, sizeof(ports));
	digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
	delay(500);
}

Приёмник просто ждёт пока структура придёт полностью, а когда придёт – печатает её и заодно печатает значение 13-го пина (как пример для Вас как к пинам добираться). Вот он.

#include <SoftwareSerial.h>
#include "Packet.h"

const int8_t softRX = 6;
const int8_t softTX = 7;

SoftwareSerial sSerial(softRX, softTX);

void setup(void) {
	Serial.begin(57600);
	sSerial.begin(9600);
	Serial.println("SLAVE console");
}

void loop(void) {
	if (sSerial.available() >= (int) sizeof(AllThePorts)) {
		AllThePorts ports;
		sSerial.readBytes((char *) & ports, sizeof(ports));
		Serial.println(ports);
		// 
		// Пример доступа к пинам. Пин 13 - PB5
		bool _pin13 = ports.pinB & bit(5);
		Serial.print("pin13="); 
		Serial.println(_pin13); 
	}
}

Теперь Вы можете всё это запустить, наблюдать за печатью и попробовать менять на мастере состяния пинов (замыкайте их то на землю, то на питание) - увидите, как их состояния будут правильно передаваться.

------------------------------------------------------
------------------------------------------------------

Добавим сюда контроль ошибок передачи.

Для этого в структуру добавим функцию getCRC, которая считает контрольную сумму. Также добавим поле crc и функция setCRC. Последнюю нужно вызывать непосредственно перед отправкой структуры. Она посчитает контрольную сумму и запишет её в поле crc. На приёмнике же нужно посчитать контрольную сумму полученного пакета (функцией getCRC) и сравнить её с полученным полем crc. Если сравнилось нормально, значит с высокой вероятностью ошибок не было.

Вот тексты.

«Packet.h»

#ifndef	PACKET_H
#define	PACKET_H

struct AllThePorts : public Printable{
	uint16_t address;
	uint8_t	pinB, pinC, pinD, crc;

	// Читает порты и заполняет структуру
	void fillUp(void) {
		pinB = PINB;
		pinC = PINC;
		pinD = PIND;
	}

	// Нужно вызвать перед отправкой
	void setCRC(void) { crc = getCRC(); }
	
	uint8_t getCRC(void) const {
		const uint8_t * p = reinterpret_cast<const uint8_t *>(this);
		uint8_t crc = 0xFF;
		for (uint8_t n = 0; n < sizeof(*this) - sizeof(crc); n++) {
			crc ^= *p++;
			for (uint8_t i = 0; i < 8; i++) crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
		}
		return crc;
	}

	// Печатает структуру для отладки
	size_t printTo(Print& p) const {
		return 
			p.print("address=") + p.print(address) +
			p.print("; pinB=") + p.print(pinB, HEX) +
			p.print("; pinC=") + p.print(pinC, HEX) +
			p.print("; pinD=") + p.print(pinD, HEX) +
			p.print("; crc=") + p.print(crc, HEX);
	}
}  __attribute__ ((packed));

#endif	//	PACKET_H

Передатчик

#include <SoftwareSerial.h>
#include "Packet.h"

const int8_t softRX = 6;
const int8_t softTX = 7;

SoftwareSerial sSerial(softRX, softTX);

void setup(void) {
	Serial.begin(57600);
	sSerial.begin(9600);
	Serial.println("MASTER console");
	delay(100);
}

void loop(void) {
	static long counter = 0;
	AllThePorts ports;
	ports.address = 1234; // адрес приёмника
	ports.fillUp();
	ports.setCRC();
	Serial.println(ports);
	// Кажду десятую посылку портим, чтобы проверить реакцию на ошибку
	if (++counter % 10 == 0) ports.pinB++;
	sSerial.write((char *) & ports, sizeof(ports));
	delay(500);
}

Приёмник

#include <SoftwareSerial.h>
#include "Packet.h"

const int8_t softRX = 6;
const int8_t softTX = 7;

SoftwareSerial sSerial(softRX, softTX);

void setup(void) {
	Serial.begin(57600);
	sSerial.begin(9600);
	Serial.println("SLAVE console");
}

void loop(void) {
	if (sSerial.available() >= (int) sizeof(AllThePorts)) {
		AllThePorts ports;
		sSerial.readBytes((char *) & ports, sizeof(ports));
		if (ports.getCRC() == ports.crc) Serial.println(ports);
		else {
			Serial.print("Transmission error: ");
			Serial.println(ports);
		}
	}
}

В передатчике я добавил порчу пакета (уже после расчёта crc) на каждой десятой посылке, чтобы убедиться, что приёмник адекватно реагирует на ошибку. Можете запустить и убедиться, что всё работает нормально.

Ну, вроде так, если я нигде ничего не ляпнул. Если что, спрашивайте.

sadman41
Offline
Зарегистрирован: 19.10.2016

Green, это у меня-то сложный пример? ))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Евгений Петрович, а восстановление по CRC? Для полного Иринкиного щастья )))

Green
Offline
Зарегистрирован: 01.10.2015

sadman41 пишет:

Green, это у меня-то сложный пример? ))

Нет, теперь точно не сложный.))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

а восстановление по CRC? Для полного Иринкиного щастья )))

Без поллитры? Нее ...

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Будет чем вечером заняться. Буду изучать. Большое огромное спасибо за оказываемую помощь.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Green, это у меня-то сложный пример? ))

А у меня-то чего сложного? принтабле что-ли? Так это не про решаемую задачу а про удобство отладочной печати. А по задаче - структура и write c readBytes, где там сложности-то?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Работает. Теперь буду разбираться в коде

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Если что, спрашивайте.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Начала разбираться:

#ifndef  PACKET_H
#define PACKET_H

struct AllThePorts : public Printable{
uint16_t address;//переменная адреса 2 Байта
uint8_t pinB, pinC, pinD, crc;//переменные 1 Байт 

//Считываю порты 
void fillUp(void) {
    pinB = PINB;
    pinC = PINC;
    pinD = PIND;
}

//Тёмный лес
  void setCRC(void) { crc = getCRC(); }
  
  uint8_t getCRC(void) const {
    const uint8_t * p = reinterpret_cast<const uint8_t *>(this);
    uint8_t crc = 0xFF;
    for (uint8_t n = 0; n < sizeof(*this) - sizeof(crc); n++) {
      crc ^= *p++;
      for (uint8_t i = 0; i < 8; i++) crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
    }
    return crc;
  }
//Конец тёмного леса


// Печатает структуру для отладки
size_t printTo(Print& p) const {
return // почему return здесь, а не перед закрывающей скобкой?
p.print("address=") + p.print(address) +
p.print("; pinB=") + p.print(pinB, HEX) +
p.print("; pinC=") + p.print(pinC, HEX) +
p.print("; pinD=") + p.print(pinD, HEX) +
p.print("; crc=") + p.print(crc, HEX);
}
//End Печатает структуру для отладки


} 
 __attribute__ ((packed));//Что значит эта строчка?

#endif  //  

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Irinka пишет:

почему rerurn здесь, а не перед закрывающей скобкой?

Потому, что он относится ко всему, что ниже. Строки №№32-37 это по сути одна строка (return .....;). Просто разнёс на разные строки, чтобы не писать такую длинную. Посмотрите где точка с запятой - одна в самом конце.

Тёмный лес - это стандартная процедура подсчёта 8-битной CRC. Я её не сам придумал, она есть в любом учебнике и, кажется, даже в википедии (сейчас проверю) ....

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А мне жутко интересно узнать, но стыдно спросить.... Но спрошу (если что - к нужным букварям отправьте или скажите - тебе ещё рано :-) )

вот эта сокращённая запись:

crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;

можно ее расшифровать, так сказать?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

ЕвгенийП пишет:

Потому, что он относится ко всему, что ниже. Строки №№32-37 это по сути одна строка (return .....;). Просто разнёс на разные строки, чтобы не писать такую длинную. Посмотрите где точка с запятой - одна в самом конце.

Поняла.

 

void loop(void) {
AllThePorts ports;
ports.address = 1234; // Задала адрес
ports.fillUp();//Получила состояние портов
ports.setCRC();//Посчитала контрольную сумму строки, состоящей из адреса и трех портов
Serial.println(ports);
sSerial.write((char *) & ports, sizeof(ports));
}

пишу...сейчас кое-что првоерю и отпишусь дальше. Почему-то в протеусе не работает проект

sadman41
Offline
Зарегистрирован: 19.10.2016

BOOM пишет:

crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;

можно ее расшифровать, так сказать?

Тернарная условная операция

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Irinka пишет:

Почему-то в протеусе не работает проект

Это известный косяк модели в протеусе. Сделайте там не ардуины, а просто ATmega382P - заработает.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В википедии на нашёл, но не суть - это одна из стандартных процедур (есть и другие), я её просто использую готовую.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Вот момент который не понимаю:

В слейве получаю:

address=1234; pinB=1; pinC=0; pinD=83; crc=38
 
38 это количество байт в строке?
т.е. строка address=1234; pinB=1; pinC=0; pinD=83; равна 38 байт?
 
тогда если в мастере изменяю 
		return 
			p.print(address) +
			p.print(pinB, HEX) +
			p.print(pinC, HEX) +
			p.print(pinD, HEX) +
			p.print(crc, HEX);
	}
}  __attribute__ ((packed));

получаю в мастере строку 1234108338, но в этой строке не 38 байт же

 
 
Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Я совсем не поняла, с мастера я отправляю всю эту строку

address=1234; pinB=1; pinC=0; pinD=83; crc=38

или только значение переменных 1234; 1 0 83 38

как слейв понимает что 1234 это адрес, 1 это  pinB...как просиходит этот "парсинг"?

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:

address=1234; pinB=1; pinC=0; pinD=83; crc=38

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Irinka пишет:

address=1234; pinB=1; pinC=0; pinD=83; crc=38

Понятно, что раз 38 значит 38 и должно быть)

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:

Понятно, что раз 38 значит 38 и должно быть)

Правильный подход к пониманию.

Если мастер послал CRC пакета = 38, то и слейв при проверочном расчёте (тем же способом) CRC на основании данных в пакете должен получить 38. Если вышло что-то другое - пакет битый.

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:

Я совсем не поняла, с мастера я отправляю всю эту строку

address=1234; pinB=1; pinC=0; pinD=83; crc=38

или только значение переменных 1234; 1 0 83 38

А Вы ещё мой пример гляньте - он про то же самое, но несколько проще (хотя ЕвгенийП так не считает, конечно).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

 Если вышло что-то другое - пакет битый.

и если это настоящий crc то запускается процедура воостановления битой информации, а если не удалось, то пакет отбрасывается и отправляется запрос на переотправку битого пакета...
 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Объясниете, не понимаю:

//Добавила переменную
uint16_t text;

size_t printTo(Print& p) const {
		return 
			p.print("address=") + p.print(address) +
			p.print("; pinB=") + p.print(pinB, HEX) +
			p.print("; pinC=") + p.print(pinC, HEX) +
			p.print("; pinD=") + p.print(pinD, HEX) +
      p.print("; text=") + p.print(text) +
			p.print("; crc=") + p.print(crc, HEX);
	}
}  __attribute__ ((packed));
Отправляю на слейв.....

На слейве:


void loop(void) {
if (sSerial.available() >= (int) sizeof(AllThePorts)) {
AllThePorts ports;
sSerial.readBytes((char *) & ports, sizeof(ports));
if (ports.getCRC() == ports.crc){
Serial.println(ports.text);
В каком месте в переменную ports.text произошло присвоение отправленного текста?
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:

В каком месте в переменную ports.text произошло присвоение отправленного текста?

В sSerial.readBytes(). 

В struct у нас как данные хранятся? Последовательно сложенными в линеечку, одна за другой: address | pinB | pinC | pinD | ... 

Т.е. фактически - массив байтов, из которых две ячейки отданы address, по одной pinX и т.д.

write() этот массив выплёскивает в сторону слейва, слейв принимает и складывает в такой же массив на своей стороне, на который можно смотреть через шаблон структуры. Как в советском "Шерлоке Холмсе" показано - накладывают на страницу книги черный лист с дырками и читают тайное слово.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, как в каком, Эта переменная - часть структуры, Вы ей на мастере что-то присвоили? А структура передаётеся полностью! Вот она и передалась, как часть структуры.

Только, если Вы хотите добавлять поля в структуру, дробавляйте их ДО crc, а не после. crc должна быть последним полем в структуре. После неё никаких полей, иначе может сломаться подсчёт crc.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

ЕвгенийП пишет:

 А структура передаётеся полностью!

Так понятнее. Спасибо.

__attribute__ ((packed));

Что значит эта строчка?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
err
Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
#ifndef	PACKET_H
#define	PACKET_H

struct AllThePorts{
	uint16_t address,text;
	uint8_t	pinC, pinB, pinD, crc;

	void fillUp(void) {
		pinB = 2;
		pinC = 3;
		pinD = 4;
	}


	void setCRC(void) { crc = getCRC(); }
	
	uint8_t getCRC(void) const {
		const uint8_t * p = reinterpret_cast<const uint8_t *>(this);
		uint8_t crc = 0xFF;
		for (uint8_t n = 0; n < sizeof(*this) - sizeof(crc); n++) {
			crc ^= *p++;
			for (uint8_t i = 0; i < 8; i++) crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
		}
		return crc;
	}


/*size_t printTo(Print& p) const {
return 

p.print("address=") + p.print(address) +
p.print("; pinB=") + p.print(pinB, HEX) +
p.print("; pinC=") + p.print(pinC, HEX) +
p.print("; pinD=") + p.print(pinD, HEX) +
p.print("; text=") + p.print(text) +
p.print("; crc=") + p.print(crc, HEX);
}*/
}  __attribute__ ((packed));

#endif	//	PACKET_H

Хочу убрать отладочную печать. Где я накосячила?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Irinka пишет:

__attribute__ ((packed));

Что значит эта строчка?

При опциях IDE "из коробки" -  ничего, но она страхует от неприятностей, если опции компилятора поменяются. Она требует, чтобы каждый элемент структуры занимал минимально-достаточное место в памяти. А бывает, что каждый элемент занимает целое количество int'ов (или даже long'ов) - это от опций зависит. Но прямое указание в программе имеет более высокий приорите, чем опции. Потому, лучше указать и не думать какие там опции выставлены.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Irinka пишет:

Хочу убрать отладочную печать. Где я накосячила?

Вроде, нигде. Только в print пихать уже нильзя. А что, ругается? Что за ругань?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Точно, на это и ругался //Serial.println(ports);

Спасибо

Green
Offline
Зарегистрирован: 01.10.2015

Irinka, а вот залетел к вам (в вашу сеть) один лишний байт из вне и что? Всё, накрылась ваша богодельня? Где начало, где конец, где данные, где КС...?