Если нужно, чтобы выполняла действие, как только пришло время - задержка тут не нужна. Нужно именно что-то вроде if (пришло время что-то сделать) { делаем что-то }. Без каких-либо задержек.
Вопросы по С/С++ (СИ)
Любая задержка - это именно задержка. То есть, останавливает всю программу. А будучи помещена в теле цикла - сделает это N раз, соответственно.
Если нужно, чтобы выполняла действие, как только пришло время - задержка тут не нужна. Нужно именно что-то вроде if (пришло время что-то сделать) { делаем что-то }. Без каких-либо задержек.
Если нужно, чтобы выполняла действие, как только пришло время - задержка тут не нужна. Нужно именно что-то вроде if (пришло время что-то сделать) { делаем что-то }. Без каких-либо задержек.
- Реклама
Код: Выделить всё
int q = 0;
1начало
2...
3...
4 if (millis() % 75==0) {
5 q++ ;
6 ...
7 refreshAll(); // вывод на экран
8 if (q < 12) { q=0;}
9 }
10...
11...
12 конецДа, что-то вроде. Цикл не нужен. За один вызов этого кода эта "частичная" отрисовка должна отработать только один раз. А уже на следующем вызове функции, значение q будет уже другое и отрисовано будет уже по-другому. Естественно, q должна быть либо глобальной, либо статической переменной, чтобы сохранять значение между вызовами этого кода.
P.S. Только if (q < 12) { q=0;} - неправильное условие - всегда будет на 0 выходить.
Опять же, условие if (millis() % 75==0) не очень корректное. Потому что именно в эту (одну из 75) миллисекунду, когда остаток от деления на 75 равен нулю, очень велик шанс, что будет выполняться код совсем где-то в другом месте, так что, пока программа придёт к этому месту, всё уже поменяется, и это условие не выполнится.
Лучше значение, возвращаемое millis(), запомнить (например, в переменной oldMillis). А затем, когда снова программа придёт к этому месту, проверить, сколько прошло времени. То есть, что-то вроде.
Тогда это "что-то" будет делаться не чаще раза в 75мс. А если где-то что-то подвиснет на пару миллисекунд в другом месте, то всё равно выполнится. Пусть, не через ровно 75, а на пару миллисекунд больше - некритично.
P.S. Только if (q < 12) { q=0;} - неправильное условие - всегда будет на 0 выходить.
Опять же, условие if (millis() % 75==0) не очень корректное. Потому что именно в эту (одну из 75) миллисекунду, когда остаток от деления на 75 равен нулю, очень велик шанс, что будет выполняться код совсем где-то в другом месте, так что, пока программа придёт к этому месту, всё уже поменяется, и это условие не выполнится.
Лучше значение, возвращаемое millis(), запомнить (например, в переменной oldMillis). А затем, когда снова программа придёт к этому месту, проверить, сколько прошло времени. То есть, что-то вроде.
Код: Выделить всё
static unsigned long oldMillis = 0;
...
unsigned long now = millis();
if (now - oldMIllis >= 75) {
// делаем что-то;
oldMillis = now;
}что то стало получаться, спасибо.
программа перестала тормозить
буду думать дальше.
программа перестала тормозить
буду думать дальше.
- Сообщения: 768
- Зарегистрирован: Вс янв 19, 2014 00:55:09
Есть данные разной байтовой величины и знака. Необходимо сложить их побайтово в буферный массив и отправить в воздух. Оформил это дело в структуру и при попытке записи ее в буфер, 7 студия выдает ворнинг и мессагу, при чем - через раз. Бывает, что и спокойно откомпилирует. Как это дело побороть, подскажите пожалуйста.
Код: Выделить всё
struct payload_t{
uint8_t a;
uint32_t b;
int16_t c;
uint8_t d;
uint8_t e;
uint8_t f;
} payload;
//************
void tx_data(){
TX_send(&payload, sizeof(payload));
...
}
//************
void TX_send(uint8_t* buf, uint8_t len){
...
_write(W_TX_PAYLOAD, buf, len);
...
}Message expected 'uint8_t *' but argument is of type 'struct payload_t *'
Warning passing argument 1 of 'TX_send' from incompatible pointer type
- Реклама
Привести аргумент к типу, который требует функция TX_send:
Либо объявить эту функцию иначе, подразумевая, что в неё может быть передан любой тип указателя:
Код: Выделить всё
TX_send((uint8_t*)&payload, sizeof(payload));Код: Выделить всё
void TX_send(void* buf, uint8_t len);- Сообщения: 768
- Зарегистрирован: Вс янв 19, 2014 00:55:09
WiseLord, Спасибо! Ваш 1 вариант убрал "ругань". Не пойму никак сакральную суть этих указателей...
Функция ожидает указатель на беззнаковый байт, а Вы подсовываете её указатель на структуру. Хотя по сути значение обоих этих указателей (адрес) одно и то же, но для C это разные типы данных.
Почему это важно... ну, например, если для указателя p сделать p++ (увеличить адрес), то если это указатель на uint8_t, то получится прыжок на 1 байт, а для указателя на структуру выйдет прыжок на размер структуры.
Почему это важно... ну, например, если для указателя p сделать p++ (увеличить адрес), то если это указатель на uint8_t, то получится прыжок на 1 байт, а для указателя на структуру выйдет прыжок на размер структуры.
- Сообщения: 768
- Зарегистрирован: Вс янв 19, 2014 00:55:09
Ёшкин коот!
Вот функция записи байта/байт.
Получается, что с предыдущим (ошибочным) вызовом, строка "spi_byte(*buf++);" перескакивала через len байт в каждой итерации?
Вот функция записи байта/байт.
Код: Выделить всё
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;
}Нет. Внутри этой функции указатель в любом случае будет прыгать на sizeof(uint8_t), и что там снаружи передано - она не знает.
Предупреждение возникает снаружи, когда пытаетесь скормить функции не тот указатель. Несмотря на это, внутри оно будет работать правильно в любом случае.
Ах да, ещё у Вас есть один момент, связанный с выравниванием структур, который скорее всего даёт некорректный результат.
У этой структуры sizeof будет, думаю, 16. Ну, или 13, до конца не уверен, надо проверять.
P.S. Проверил - да, sizeof(payload) равен 16
Предупреждение возникает снаружи, когда пытаетесь скормить функции не тот указатель. Несмотря на это, внутри оно будет работать правильно в любом случае.
Ах да, ещё у Вас есть один момент, связанный с выравниванием структур, который скорее всего даёт некорректный результат.
Код: Выделить всё
struct payload_t{
uint8_t a;
uint32_t b;
int16_t c;
uint8_t d;
uint8_t e;
uint8_t f;
} payload;P.S. Проверил - да, sizeof(payload) равен 16
- Сообщения: 768
- Зарегистрирован: Вс янв 19, 2014 00:55:09
WiseLord,
Опять спасибо!
Но что такое "выравнивание структур"? Я полагал, что структура резервирует неразрывную область в памяти, при объявлении, = своему размеру? И у меня sizeof(payload) показывает 10 байт. Как так?
Но что такое "выравнивание структур"? Я полагал, что структура резервирует неразрывную область в памяти, при объявлении, = своему размеру? И у меня sizeof(payload) показывает 10 байт. Как так?
Я вот тоже никак не могу понять, как вышло 16 или 13...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Легко:
Я был только не уверен насчёт последних 3 байтов.
Технически, 10 байт (без дополнительных телодвижений) может быть только если где-то в опциях компилятора стоит принудительная упаковка структур. Что технически даёт не самый оптимальный код.
Вот, например, на PC:

P.S. На STM32:

Если нужно гарантировано получить 10 байтов, объявлять структуру нужно с атрибутом __attribute__((packed))
Неплохая статья на тему (если быстро погуглить): https://tproger.ru/translations/art-of- ... e-packing/
Код: Выделить всё
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;Где показывает?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
А, понятно теперь.
Видимо, это напрямую связано с разрядностью процессора/контроллера? Вы работаете в 64/32 разрядной ОС, оттого и область там = 4 байтам. Надеюсь у 8-ми битных АВР такой "засады" не будет?
Возможно, и не будет. Хотя и не уверен. Есть у меня подозрение, что там выравнивание может быть по 16 байтам, и тогда можно 12 байт для этой структуры получить. Но точно сказать не берусь.
P.S. Проверил - да, на ATmega32 получается 10 байт.
P.S. Проверил - да, на ATmega32 получается 10 байт.
- Сообщения: 768
- Зарегистрирован: Вс янв 19, 2014 00:55:09
WiseLord, спасибо большое за помощь!
И за удовольствие от общения. Вы умеете подавать информацию лаконично и в то же время объемно и очень доступно.
хм... я всё время был уверен, что выравнивание делается для всех полей струткуры, занимающих меньше байт, чем разрядность платформы. а вы пишите, что первый байт выравнивается до 4, а последние три - нет, и 16-битное поле на 2 не выравнивается до 4-х...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.
Там пару сообщений назад я ссылку на неплохой перевод размещал.
Там пару сообщений назад я ссылку на неплохой перевод размещал.
больше программу не тормозит цикл убрали его
тепер другая напасть
начинается отрисовка цифры от начала до конца, потом примерно через 5 сек от середины до конца, потом самый конет отрисовывается и опять от начало до конца...
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;} // для того чтобы знать изменилась цифра или нет
}
посмотрите может скажите куда "грести"?
тепер другая напасть
начинается отрисовка цифры от начала до конца, потом примерно через 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 КБ) 106 скачиваний
Думаю, это из-за того, что вся эта анимация отрисовки занимает не ровно секунду (75ms * 12).
В итоге фаза отрисовки постоянно сползает.
Нужно сделать так, чтобы на каждой новой секунде принудительно сбрасывалось oldMillis = now; shag = 0.
В итоге фаза отрисовки постоянно сползает.
Нужно сделать так, чтобы на каждой новой секунде принудительно сбрасывалось oldMillis = now; shag = 0.


