Создание пользовательского класса

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

Smith2007 пишет:
где расположен младший байт, а гле старший?
Снчала младший, потом старший, но пользоваться этим - гнусный хак. Если надо обращаться к куску структуры с другим типом - используйте union.

Smith2007
Offline
Зарегистрирован: 30.10.2017

Не могу понять как в памяти расположены переменные uin16   Uint32

Младший байт числа с меньшим адресом памяти или с большим?

хм... опять туплю. Память 16 битная же? Т.е. Uint16 располагается по одному адресу. А как расположена uint32?

Smith2007
Offline
Зарегистрирован: 30.10.2017

Как расположены элементы массива типа байт в памяти? Каждый байт в своём адресе т.е. Байт реально в памяти займёт 16 бит. Или два байта будут размещены по одному адресу?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Smith2007 пишет:

хм... опять туплю. Память 16 битная же? Т.е. Uint16 располагается по одному адресу. А как расположена uint32?

Тупите и несёте дичь. То, что память 16-битная, не означает, что uint16 располагается по одному адресу. Это означает лишь, что адресация памяти 16-битная, т.е. адрес любой ячейки памяти выражается двумя байтами.

uint16 хранится в памяти, начиная с какого-либо её адреса, сначала идёт младший байт, затем - старший. Аналогично, начиная с какого-либо адреса, может лежать uint32, начиная с младшего байта, 4 байта занимает.

Smith2007
Offline
Зарегистрирован: 30.10.2017

Правильно понимаю

Uint16_t var

Переменная var расположена

младший бай по адресу <адрес>

старший байт <адрес +1>

Smith2007
Offline
Зарегистрирован: 30.10.2017

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

Smith2007 пишет:
где расположен младший байт, а гле старший?
Снчала младший, потом старший, но пользоваться этим - гнусный хак. Если надо обращаться к куску структуры с другим типом - используйте union.

Внутри структуры это тоже будет работать?

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

А почему нет?

Smith2007
Offline
Зарегистрирован: 30.10.2017

Пока до компа далеко....

верной будет следующая запись? (На первую заглавную не обращайте внимания. Смартфон ее сам заглавной делает. Я осознаю эту ошибку в написании.)

Union dataU {
  Uint8_t var8[4];
  Uint16_t  var15[2];
  Uint32 var32;
}

Strict packet_t {
  Uint8_t adr;
  Uint8_t cod;
  DataU data;
  Uint8_t crc;
}

В программе обращаюсь

Packet_t packet;

Packet.adr=7;
Packet.data.var32=0x44332211;

Uint8_t a=packet.data.var8[0]; // 0x11
Uint16_t b=packet.data.var16[0]; // 0x2211

 

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

Ну, если ещё ; после закрывающих } поставить, и вместо strict написать struct,  то как-то примерно так. Если dataU сама по себе не нужна, то можно было её прямо в теле packet_t прописать.

Smith2007
Offline
Зарегистрирован: 30.10.2017

Сама по себе dataU не нужна. Только я не понимаю синтаксис как это записать в блоке структуры. И как потом к обращаться к таким эоементам

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

Не понимаете - пишите как понимаете.

В принципе, записать несложно

struct packet_t {
	uint8_t adr;
	uint8_t cod;
	union {
		uint8_t var8[4];
		uint16_t  var15[2];
		uint32_t var32;
	} data;
	uint8_t crc;
};

// Обращаться также, как Вы собирались при Вашей записи

но Вы не комплексуйте, а делайте как умеете. "Синтаксическое чутьё" придёт с опытом.

Smith2007
Offline
Зарегистрирован: 30.10.2017

Вот так сделал, без указание типа union. Все прокатило !

Надо отметить, что Си мне нравится все больше и больше :) Этоже такая гибкость! Осталось обрести опыт и делать меньше глюков.

  // Структура буфера приема
  struct packetIn_t {   // Структура принятого пакета
    uint8_t adr;
    uint8_t cmd;
    uint8_t reg;
	union {
		uint8_t b[4];   // 4- х байтный массив
		uint16_t w[2];  // Массив из двух uint16
		uint32_t d;     // unsigned long int
		float f;        // float
	};
  };

packetIn_t  packetIn;

Обращение к переменным packet.In.b[0] ... packet.In.b[3], packet.In.w[0]..  packet.In.w[0], packet.In.d, packet.In.f

Все так просто! А я раскладывал байт, сдвигал , операции "И" и т.д. В общем тонна замудренного кода, когда все так лаконично и ясно.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Smith2007 пишет:

Все так просто! А я раскладывал байт, сдвигал , операции "И" и т.д. В общем тонна замудренного кода, когда все так лаконично и ясно.

Ещё много вкусностей есть, например - битовые поля, здорово помогают экономить память на всяких флагах, плюс не надо морочиться вручную со сдвигами и пр:

// тривиальный подход
bool flag1;
bool flag2;
bool flag3;

// подход с битовыми полями
typedef struct
{
 bool flag1 : 1;
 bool flag2 : 1;
 bool flag3 : 1;
} Flags;

Flags flags;
flags.flag1 = true;
flags.flag3 = true;

И читабельность кода сохраняется, к слову.

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

Smith2007 пишет:

Вот так сделал, без указание типа union. Все прокатило !

Не понял, чем это отличается от того, что я давал в #161? Или ничем, просто сообщаете, что получилось?

Smith2007
Offline
Зарегистрирован: 30.10.2017

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

Smith2007 пишет:

Вот так сделал, без указание типа union. Все прокатило !

Не понял, чем это отличается от того, что я давал в #161? Или ничем, просто сообщаете, что получилось?

struct packet_t {
	uint8_t adr;
	uint8_t cod;
	union {
		uint8_t var8[4];
		uint16_t  var15[2];
		uint32_t var32;
	} data;
	uint8_t crc;
};

// Обращаться также, как Вы собирались при Вашей записи

Вы указываете union data

я использовал union без имени.

Но вообще от радости написал, что получилось :)

Спасибо всем откликнувшимся. Особенно Вам, Евгений.

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

Smith2007 пишет:

Вы указываете union data

Вы очень невнимательны. Программисту так нельзя. Посмотрите #161 ещё раз. Имени union'а нет ни у меня, ни у Вас. Я собственно и писал-то пример, чтобы показать Вам безымянный union.

Smith2007
Offline
Зарегистрирован: 30.10.2017
struct packet_t {
	uint8_t adr;
	uint8_t cod;
	union {
		uint8_t var8[4];
		uint16_t  var15[2];
		uint32_t var32;
	} data;
	uint8_t crc;
};

А как читать union {. } data;

data это разве не имя union?

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

Нет. Имя union пишется сразу после слова union, а data - имя экземпляра.

Smith2007
Offline
Зарегистрирован: 30.10.2017

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

Нет. Имя union пишется сразу после слова union, а data - имя экземпляра.

понятно по синтаксису union.

Но не понятна конструкция struct 

Мы же описываем тип, структуру. Как в тип структуры можно включить экземпляр?

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

Поля структуры это экземпляры других типов. Почему Вас не смущает поле типа int, а поле типа union .... смущает?

Smith2007
Offline
Зарегистрирован: 30.10.2017

Да, действительно. Не дошло сразу.

конструкция то аналогичная...

Float f;

union {} data;

 

Понимание приходит, но как то со скрипом :)

Smith2007
Offline
Зарегистрирован: 30.10.2017

Имеется некоторый класс Channel

В процедурах класса имеются вызовы Serial.available(), Serial.write(..) etc. В общем использую методы класса Serial.

Что бы класс Channel был законченным, мне бы хотелось передать ему конкретный Serial/Serial1/Serial2/.... в конструкторе

Можно конечно передавать 0,1,2,3 и в классе делать сравнение:

if (nSerial == 0) { xxx = Serial.read()}; 

if (nSerial == 1) { xxx = Serial1.read()}; 

Но выглядит это крайне криво и расточительно к ресурсам МК. Я понимаю, что нужно передать сам Serial... но не соображу как.

Подскажите синтаксис пожалуйста. Застрял опять.

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

Можно указатель на Serial передать, например. Тип, по-моему, HardwareSerial. С мобилы смотреть ардуиновские хидеры сложно.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А вот здесь вы нарвались на плюху. Serial это скорее консоль, а не привычный вам канал. И ваш канал к Serial-у как бубен зайцу. ПС: Это мое ИМХО.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Smith2007 пишет:

 

Подскажите синтаксис пожалуйста. Застрял опять.

HardwareSerial наследуется от Stream, указатель на Stream и передавайте. Тем более используемые вами методы как раз определены в классе Stream.

class Some
{
 Stream* s;
 public:
  void setStream(Stream* s) {_s = s;}
};

Some some;

void setup()
{
 some.setStream(&Serial1);
  
}