Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

Ёшкин коот! :shock:
Вот функция записи байта/байт.

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

void _write(uint8_t reg, uint8_t* buf, uint8_t len){
	CS_LOW;
	spi_byte((reg & REGISTER_MASK) | W_REGISTER);
	while(len--){
		spi_byte(*buf++);
	}
	CS_HIGH;
}
Получается, что с предыдущим (ошибочным) вызовом, строка "spi_byte(*buf++);" перескакивала через len байт в каждой итерации?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Нет. Внутри этой функции указатель в любом случае будет прыгать на sizeof(uint8_t), и что там снаружи передано - она не знает.

Предупреждение возникает снаружи, когда пытаетесь скормить функции не тот указатель. Несмотря на это, внутри оно будет работать правильно в любом случае.

Ах да, ещё у Вас есть один момент, связанный с выравниванием структур, который скорее всего даёт некорректный результат.

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

struct payload_t{
   uint8_t a;
   uint32_t b;
   int16_t c;
   uint8_t d;
   uint8_t e;
   uint8_t f;
} payload;
У этой структуры sizeof будет, думаю, 16. Ну, или 13, до конца не уверен, надо проверять.

P.S. Проверил - да, sizeof(payload) равен 16
Контактная информация:
Реклама
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

WiseLord, :) Опять спасибо!
Но что такое "выравнивание структур"? Я полагал, что структура резервирует неразрывную область в памяти, при объявлении, = своему размеру? И у меня sizeof(payload) показывает 10 байт. Как так?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18793
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Я вот тоже никак не могу понять, как вышло 16 или 13...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Легко:

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

struct payload_t{
// -----------------------------------------------------
   uint8_t a;       // 1 байт
                    // дырка 3 байта - выравнивание до 4
// -----------------------------------------------------
   uint32_t b;      // 4 байта
// -----------------------------------------------------
   int16_t c;       // 2 байта
   uint8_t d;       // 1 байт
   uint8_t e;       // 1 байт
// -----------------------------------------------------
   uint8_t f;       // 1 байт
                    // дырка 3 байта - выравнивание до 4
} payload;
Я был только не уверен насчёт последних 3 байтов.
MOHCTEP писал(а):И у меня sizeof(payload) показывает 10 байт. Как так?
Где показывает?

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

Вот, например, на PC:

Изображение

P.S. На STM32:

Изображение

Если нужно гарантировано получить 10 байтов, объявлять структуру нужно с атрибутом __attribute__((packed))

Неплохая статья на тему (если быстро погуглить): https://tproger.ru/translations/art-of- ... e-packing/
Контактная информация:
Реклама
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

А, понятно теперь. :) Видимо, это напрямую связано с разрядностью процессора/контроллера? Вы работаете в 64/32 разрядной ОС, оттого и область там = 4 байтам. Надеюсь у 8-ми битных АВР такой "засады" не будет?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Возможно, и не будет. Хотя и не уверен. Есть у меня подозрение, что там выравнивание может быть по 16 байтам, и тогда можно 12 байт для этой структуры получить. Но точно сказать не берусь.

P.S. Проверил - да, на ATmega32 получается 10 байт.
Контактная информация:
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

WiseLord, спасибо большое за помощь! :beer: И за удовольствие от общения. Вы умеете подавать информацию лаконично и в то же время объемно и очень доступно.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18793
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

WiseLord писал(а):

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

struct payload_t{
// ----------
   uint8_t a;       // 1 байт
                    // дырка 3 байта - выравнивание до 4
// ----------
   uint32_t b;      // 4 байта
// ----------
   int16_t c;       // 2 байта
   uint8_t d;       // 1 байт
   uint8_t e;       // 1 байт
// ----------
   uint8_t f;       // 1 байт
                    // дырка 3 байта - выравнивание до 4
} payload;
хм... я всё время был уверен, что выравнивание делается для всех полей струткуры, занимающих меньше байт, чем разрядность платформы. а вы пишите, что первый байт выравнивается до 4, а последние три - нет, и 16-битное поле на 2 не выравнивается до 4-х...
чего я не понимаю?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Однобайтные поля не выравниваются, двухбайтные выравниваются по границам чётных адресов, четырёхбайтные - по границам адресов, кратных 4.

Там пару сообщений назад я ссылку на неплохой перевод размещал.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

больше программу не тормозит цикл убрали его :)))

тепер другая напасть
начинается отрисовка цифры от начала до конца, потом примерно через 5 сек от середины до конца, потом самый конет отрисовывается и опять от начало до конца...
Спойлерif (s0 != lasts0){showDigit( s0 * 12 + shag, 28, dig3x7q);} // s0 * 12 + q - номер строки в масиве dig3x7q (смотрим вкладку "fonts.h")
else showDigit(s0, 28, dig3x7s); // s0 - номер строки в масиве dig3x7s (смотрим вкладку "fonts.h")

if (s1 != lasts1) showDigit( s1 * 12 + shag, 24, dig3x7q); //24- позиция экрана с которой начинать печать
else showDigit(s1, 24, dig3x7s); //24- позиция экрана с которой начинать печать

if (m0 != lastm0) showDigit( m0 * 12 + shag, 17, dig4x8q); // dig3x7q - указатель на масив данных (смотрим вкладку "fonts.h")
else showDigit(m0, 17, dig4x8); // dig4x8 - указатель на масив данных (смотрим вкладку "fonts.h")

if (m1 != lastm1) showDigit( m1 * 12 + shag, 12, dig4x8q); // (m1 != lastm1)- проверяем изменилась цифра или нет
else showDigit(m1, 12, dig4x8);

if (h0 != lasth0) showDigit( h0 * 12 + shag, 5, dig4x8q);
else showDigit(h0, 5, dig4x8);

if (h1>0){
if (h1 != lasth1)showDigit( h1 * 12 + shag, 0, dig4x8q);
else showDigit(h1, 0, dig4x8);}

refreshAll(); // обновляем экран после каждой строки

unsigned long now = millis();
if (now - oldMillis >= 75) {
shag++;
Serial.print(now - oldMillis);
oldMillis = now;
}
if (shag >= 12) { shag=0; lasth1 = h1; lasth0 = h0; lastm1 = m1; lastm0 = m0; lasts1 = s1; lasts0 = s0;} // для того чтобы знать изменилась цифра или нет
}


посмотрите может скажите куда "грести"?
Вложения
chernjvik.zip
(42.36 КБ) 116 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Думаю, это из-за того, что вся эта анимация отрисовки занимает не ровно секунду (75ms * 12).

В итоге фаза отрисовки постоянно сползает.

Нужно сделать так, чтобы на каждой новой секунде принудительно сбрасывалось oldMillis = now; shag = 0.
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Serzh2000, атмега не "читает" ваши строчки. Их читает компилятор, который преобразует это дело в машинный код, который исполняет atmega.
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

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

  if(second!=lastSec){                     // проверка начала новой секунды
    lastSec=second;                         // в переменную сатрой секунды устанавливаем значение новой секунды
    oldMillis = now;                          // в начале новой секунды сбрасываем в "0"
    shag = 0;                                  // в начале новой секунды сбрасываем в "0"
  }
большое спасибо ! нет ОГРОМНОЕ спасибо!!! :beer:

теперь все четко отрисовывается! :))) и ничего не тормозит :wink:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Гораздо красивей, имхо, был бы сдвиг циферек. Текущая выдвигается, следующая вдвигается. Например, сверху-вниз.
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

я такие где то часы видел.
у меня три варианта шрифта и 8 режимов
может потом когда налюбуюсь этим режимом в другом шрифте и режиме сделаю сверху-вниз.
а пока у меня душа поет от этой отрисовки я долго над ней голову ломал, спасибо хорошему человеку
помог мне.
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

Подскажите, кто в курсе: есть некая структура данных

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

volatile struct {
  int a;
  int b;
  char *buf;
  // ... чего-то там еще
} var_name;
и доступ к этой структуре может осуществляться, как из основного кода, так и из прерываний. Не пойму, достаточно ли только саму структуру объявить, как volatile или этот модификатор надо указывать и для всех полей?
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

a5021, помечая структуру как volatile, вы делаете все её члены как volatile. Т.е. достаточно и так, если вам оно и нужно. Но учтите, что с указателями внутри так будет "засада" - т.о. будет только адрес помечен как volatile, но не данные по его адресу. Для того, чтобы пометить данные как volatile, надо указывать volatile char *buf; внутри.
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

Ну типа пытаюсь писать на "С" под AVR. Написал по инструкциям в тырнете мигалку, а транслятор выдает такое:

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

E:\Disk_D\comp\avr8-gnu-toolchain\bin>avr-gcc -mmcu=atmega48 -o blinker.a e:\bli
nker.c
In file included from e:\blinker.c:5:0:
e:\disk_d\comp\avr8-gnu-toolchain\avr\include\util\delay.h:95:3: warning: #warni
ng "Compiler optimizations disabled; functions from <util/delay.h> won't work as
 designed" [-Wcpp]
 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't
 work as designed"
Результат трансляции работает как ожидалось. Тогда что это было? Чего-то пошло не так?
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Shuspano, добавьте ключик оптимизации при компиляции -Os и всё будет ок.
Функции _delay требуют включенную оптимизацию компилятора, чтобы правильно время рассчитывать, о чем соб-но и написано в предупреждении.
Ответить

Вернуться в «Разные вопросы по МК»