Как бы мне параллельно, что ты скажешь. Это дело целесообразности, какую реализацию делать.
Как оптимизировать использование функций?
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
2 Dimon456. Сразу определимся. Цель? Потому что я тебя ловил на том, что я выкладывал свои примеры, и ты нелицеприятно отзывался. Тема топика оптимизация. И я следую этой теме.
Как бы мне параллельно, что ты скажешь. Это дело целесообразности, какую реализацию делать.
Как бы мне параллельно, что ты скажешь. Это дело целесообразности, какую реализацию делать.
- Реклама
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Demiurg, а ты начни примерно вот с этого
Код: Выделить всё
int m_sprintf(char *out, const char *format, ...)
{
int *varg = (int *)(&format);
return m_print(&out, varg);
}
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Нет, не этого ответа ждал.Demiurg писал(а):Ты этого ответа ждал?
Там же предлагали tiny_printf, ну что-то вроде этого, урезать отрезать до какого то формата, что бы не дербанить строку
Код: Выделить всё
dsprintf(string, "%02i/%02i/20%02i", day, month, year);Если ваш код в байт 500 выйдет, то ...
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Вообще с часами я мало работал. Не нужно было. Я проекты делал практически всегда на продажу. Для себя мало что делал. Потому с часами так и получилось. Глянул один свой проект с часами. Хм, дело было так. Так как с часами практически не работал, часть с часами писал, чтобы заработало. Не оптимизировал. Нужно посидеть, урезать проект, оставить только часы. Жди. Несколько дней. Сильно занят.
Добавлено after 2 minutes 9 seconds:
Даю что есть, как есть.
bcd.h:
bcd.c:
Пока это даю.
Добавлено after 2 minutes 9 seconds:
Даю что есть, как есть.
bcd.h:
Спойлер
Код: Выделить всё
#ifndef BCD_H
#define BCD_H
#include "bcd.h"
#include "main_def_func.h"
//==================
extern char num_str_buf [];
extern char tmp_num_str_buf [];
//==================
//==================
typedef enum
{
VAL_08_BIT = 0,
VAL_16_BIT,
VAL_32_BIT,
} type_val_t;
void val_to_str (u32 value, type_val_t type_val);
u16 str_to_int (void);
u32 str_to_long (void);
//==================
//==================
void clr_tmp_num_str_buf (void);
void clr_num_str_buf (void);
//==================
#endif //BCD_H
Спойлер
Код: Выделить всё
//==================
#include "bcd.h"
//==================
//==================
char num_str_buf [11];
char tmp_num_str_buf [11];
//==================
//==================
void clr_tmp_num_str_buf (void)
{
char *ptr = tmp_num_str_buf;
u08 cnt = 10;
while (cnt)
{
*ptr++ = ' ';
cnt--;
}
*ptr = 0;
}
//==================
//==================
void clr_num_str_buf (void)
{
char *ptr = num_str_buf;
u08 cnt = 10;
while (cnt)
{
*ptr++ = ' ';
cnt--;
}
*ptr = 0;
}
//==================
//==================
u32 __flash tab_hex_dec [] =
{
1000000000U,
100000000U,
10000000U,
1000000U,
100000U,
10000U,
1000U,
100U,
10U,
};
//==================
//==================
void val_to_str (u32 value, type_val_t type_val)
{
u32 a;
bool flag = false;
u08 cnt_1;
u08 cnt_2;
u08 displace;
clr_num_str_buf ();
switch (type_val)
{
case VAL_08_BIT:
displace = 7;
cnt_1 = 2;
break;
case VAL_16_BIT:
displace = 5;
cnt_1 = 4;
break;
case VAL_32_BIT:
displace = 0;
cnt_1 = 9;
break;
}
char *ptr = num_str_buf + displace;
u32 __flash *ptr_f = tab_hex_dec + displace;
while (cnt_1)
{
a = *ptr_f;
cnt_2 = 0;
while (value >= a)
{
value -= a;
cnt_2++;
}
if (flag == false)
{
if (cnt_2 == 0)
{
*ptr++ = ' '; // Гашение незначащих нулей.
}
else
{
*ptr++ = (cnt_2 | 0x30);
flag = true;
}
}
else
{
*ptr++ = (cnt_2 | 0x30);
}
ptr_f++;
cnt_1--;
}
*ptr++ = (value | 0x30);
*ptr = 0;
}
//==================
//==================
u16 str_to_int (void)
{
char *ptr_num = tmp_num_str_buf + 5;
u32 __flash *ptr_f = tab_hex_dec + 5;
u16 a;
u08 cnt = 0;
u16 tmp_value = 0;
while (cnt < 4)
{
if ((*ptr_num > 0x30) && (*ptr_num < 0x3A))
{
a = (*ptr_num - 0x30);
while (a)
{
tmp_value += *ptr_f;
a--;
}
}
*ptr_num++;
ptr_f++;
cnt++;
}
return tmp_value += (*ptr_num - 0x30);
}
//==================
//==================
u32 str_to_long (void)
{
char *ptr_num = tmp_num_str_buf;
u32 __flash *ptr_tab_10 = tab_hex_dec;
u32 a;
u08 cnt = 0;
u32 tmp_value = 0;
while (cnt < 9)
{
if ((*ptr_num > 0x30) && (*ptr_num < 0x3A))
{
a = (*ptr_num - 0x30);
while (a)
{
tmp_value += *ptr_tab_10;
a--;
}
}
*ptr_num++;
ptr_tab_10++;
cnt++;
}
return tmp_value += (*ptr_num - 0x30);
}
//==================
- Реклама
- Сообщения: 362
- Зарегистрирован: Вс апр 03, 2022 07:01:29
Ну, для часов то printf как бы и не нужен
Три-пять чисел можно и "вручную" вывести. Разложить число на разряды можно либо самописно, либо через библиотечную ф-цию itoa()
По оптимизации: надо было быстро простенький проект составить (чтение из ацп, небольшая обработка измерения и реакция на него. и так 2 абсолютно одинаковых независимых процесса, каждый берёт со своего входа и выводит в свой вывод) логично написать функцию, но т.к. при обработке использьвались накопительные буфера - понадобилось использовать указатели, чтоб каждая задача работала со своим буфером... чтото у меня не пошло = компилятор выдал ошибку, разбираться было некогда, да и место позволяло... запихнул тело функции в дефайн и вызвал его 2 раза, для каждого процесса по разу...
Потом, когда позволило время, решил разобраться и написать как хотел (причиной ошибки оказалось отсутствие скобок) обнаружил, что прошивка с дефайнами оказалась короче, чем с функциями...
П.С.: среда кодевижен, оптимизация по размеру.
думаю, что в варианте с дефайнами компилятор понял, что код повторяется и сам оптимально вынес его в функцию.
Потом, когда позволило время, решил разобраться и написать как хотел (причиной ошибки оказалось отсутствие скобок) обнаружил, что прошивка с дефайнами оказалась короче, чем с функциями...
П.С.: среда кодевижен, оптимизация по размеру.
думаю, что в варианте с дефайнами компилятор понял, что код повторяется и сам оптимально вынес его в функцию.
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
У меня в том проекте было сделано так: даты были не нужны, только время. При включении устройства считывается rtc. Дальше я опрашивал секундный вывод rtc. Чтобы не возиться, я сделал так: значения часов минут и секунд было в hex. Отсюда преобразование. Деталей, если честно не помню. Может быть, позже сяду, проанализирую. Но print точно не буду использовать.
Время print наступит позднее. Когда будут более жирные проекты и МК. А может уже и не наступит, учитывая текущие политические обстоятельства.
Я уже два или три года не занимаюсь проектами на МК.
Время print наступит позднее. Когда будут более жирные проекты и МК. А может уже и не наступит, учитывая текущие политические обстоятельства.
Я уже два или три года не занимаюсь проектами на МК.
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Хорошо, тогда нужен оптимальный код разложения на составляющие.
И такформируем строкуКакие будут ваши предложения?
И так
Код: Выделить всё
dsprintf(string, "%2i/%02i/20%02i", day, month, year); Код: Выделить всё
if (day < 10) {
string[0] = 0x20;
itoa(day, &string[1], 10);
} else itoa(day, &string[0], 10);
string[2] = '/';
if (month < 10) {
string[3] = '0';
itoa(month, &string[4], 10);
} else itoa(month, &string[3], 10);
string[5] = '/';
string[6] = '2';
string[7] = '0';
if (year < 10) {
string[8] = '0';
itoa(year, &string[9], 10);
} else itoa(year, &string[8], 10);- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Что то кучеряво как то в твоём примере... Это как бы не критика, пока. Я уже очень давно не садился за проекты. Попробую вечерами посидеть, вспомнить что да как.
ну я б и itoa убрал.
вместо неё - преобразование байта в 2 символа.
Функция преобразует число в диапазоне 0..99 в 2 символа в строке. leadingSpace - выбор - впереди пробел или ноль для чисел меньше 10.
И да, если вычисление остатка нигде больше не используется - value % 10 даст большой оврхед, поэтому остаток считаем как указано выше. На мегах с аппаратным умножителем даёт экономию кода.
вместо неё - преобразование байта в 2 символа.
Код: Выделить всё
void byte2charArr(char* arr, uint8_t value, uint8_t leadingSpace){
uint8_t val_10 = value / 10;
if (val_10) arr[0] = '0'+val_10;
else arr[0] = leadingSpace ? ' ' : '0';
arr[1] = value - val_10*10 + '0';
И да, если вычисление остатка нигде больше не используется - value % 10 даст большой оврхед, поэтому остаток считаем как указано выше. На мегах с аппаратным умножителем даёт экономию кода.
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Это пока не важно, важно имели одну строку, а получили кучу, и что бы отредактировать что-либо придется чуть ли не все исправлять.GoldenAndy писал(а):ну я б и itoa убрал.
Dimon456, ну тут вопрос - шашечки или ехать.
Вынести весь вывод на дисплей в отдельный файл - а там всё рядышком.
Редактировать же, насколько я понял - уже нечего. Надо затолкать 9.5 кб кода в 8 кб МК. тут уже все средства хороши.
И жертвовать придется и красотой кода.
(я вот сейчас глянул в папку с проектами и понял, что в своих поделиях на МК я ни разу не пользовался библиотечным форматным выводом. Только ручками, только хардкор. И форматный вывод тоже ручками. И свой вариант itoa, заточенный на размерности данных в каждом случае)
Вынести весь вывод на дисплей в отдельный файл - а там всё рядышком.
Редактировать же, насколько я понял - уже нечего. Надо затолкать 9.5 кб кода в 8 кб МК. тут уже все средства хороши.
И жертвовать придется и красотой кода.
(я вот сейчас глянул в папку с проектами и понял, что в своих поделиях на МК я ни разу не пользовался библиотечным форматным выводом. Только ручками, только хардкор. И форматный вывод тоже ручками. И свой вариант itoa, заточенный на размерности данных в каждом случае)
[uquote="Dimon456",url="/forum/viewtopic.php?p=4212814#p4212814"]важно имели одну строку, а получили кучу[/uquote]
Ну если это так принципиально - сколько строк исходника... Редактировать ничего не надо: отлаженная и оттестированная процедура будет "вечной" . А вот если в результате вместо нескольких байт применение itoa даст "кучу кода" - это, по-моему, существенней.
Ну если это так принципиально - сколько строк исходника... Редактировать ничего не надо: отлаженная и оттестированная процедура будет "вечной" . А вот если в результате вместо нескольких байт применение itoa даст "кучу кода" - это, по-моему, существенней.
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
да это не важно, можете свой написать.Jack_A писал(а):itoa даст
Пример
Код: Выделить всё
sprintf (string_out,"U=%2d.%02dV", x_u_izm/100, (x_u_izm)%100);
sprintf (string_out,"I=%1d.%02dA", x_i_izm/100, (x_i_izm)%100);Код в студию. Только не тяните кое кого за хвост, хотел бы видеть оригинальное разложение этой строки.
- Сообщения: 362
- Зарегистрирован: Вс апр 03, 2022 07:01:29
Ребят, вы чего, часы никогда не делали, штоль? Ну либо на Сях комбинации /10 и %10, либо на асме процедура bin-to-BCD с поразрядным распаковыванием, коль уж не нравится библиотечные itoa.
А когда sprintf используете, просто закидываете в параметры переменные часов, минут, секунд, даты, месяца, года, как они есть, а перед ними пишите форматирующую строку. Названия дней недели или месяц текстом можно вывести отдельно через табличку (массив текстовых строк), когда номер дня недели или месяца является индексом в табличке, а в массиве строк прописаны текстом названия).
А когда sprintf используете, просто закидываете в параметры переменные часов, минут, секунд, даты, месяца, года, как они есть, а перед ними пишите форматирующую строку. Названия дней недели или месяц текстом можно вывести отдельно через табличку (массив текстовых строк), когда номер дня недели или месяца является индексом в табличке, а в массиве строк прописаны текстом названия).
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Давайте все посмотрим на задачу с точки зрения целесообразности. Конечно, и тут могут быть варианты, типа, что мы понимаем под целесообразностью.
Начнем с того, что мы имеем на руках МК AVR. Опять же. Какой, точнее, что у него на борту. Либо у нас на руках, скажем ATMEGA8. Это один разговор. Если от, скажем, ATMEGA32 и выше. Это уже другой разговор.
Если у нас на руках МК типа ATMEGA128 или 256. Тут уже целесообразнее писать "красиво". И можно уже вовсю использовать библиотеки. Здесь работает скорость написания проекта. Пусть неоптимально по выхлопу, но быстрее "писать".
Если же у нас поджимает объем SRAM либо FLASH, тут уже начинается оптимизация. И отказ от библиотек. И утаптывание кода по выхлопу. Красивость кода тут не работает. От слова совсем.
Работа со временем, то бишь, чтобы МК обеспечивал нужный функционал это уже совсем другой разговор.
Тут просили пример кода. Здесь нужно смотреть "сверху". Хотим оптимально? Забудем о красивости кода. И начнем дербанить "красивые", в одну строку, куски кода.
К примеру. Нам нужно вывести время. Пусть формат типа: 12:03:43 03/07/2022.
Делаем во Flash строку-шаблон. Пробел, пробел, двоеточие, пробел, пробел, двоеточие, пробел, пробел, пробел, пробел, пробел, слеш, пробел, пробел, слеш, пробел, пробел. Что мы этим получили. Вывели шаблон. Быстро. Потом выводим время и дату в соответствии со знакоместами. Быстро. Кратко. Это простой пример. Да, некрасиво, не "в одну строку". Но оптимально. И по скорости и по выхлопу.
Начнем с того, что мы имеем на руках МК AVR. Опять же. Какой, точнее, что у него на борту. Либо у нас на руках, скажем ATMEGA8. Это один разговор. Если от, скажем, ATMEGA32 и выше. Это уже другой разговор.
Если у нас на руках МК типа ATMEGA128 или 256. Тут уже целесообразнее писать "красиво". И можно уже вовсю использовать библиотеки. Здесь работает скорость написания проекта. Пусть неоптимально по выхлопу, но быстрее "писать".
Если же у нас поджимает объем SRAM либо FLASH, тут уже начинается оптимизация. И отказ от библиотек. И утаптывание кода по выхлопу. Красивость кода тут не работает. От слова совсем.
Работа со временем, то бишь, чтобы МК обеспечивал нужный функционал это уже совсем другой разговор.
Тут просили пример кода. Здесь нужно смотреть "сверху". Хотим оптимально? Забудем о красивости кода. И начнем дербанить "красивые", в одну строку, куски кода.
К примеру. Нам нужно вывести время. Пусть формат типа: 12:03:43 03/07/2022.
Делаем во Flash строку-шаблон. Пробел, пробел, двоеточие, пробел, пробел, двоеточие, пробел, пробел, пробел, пробел, пробел, слеш, пробел, пробел, слеш, пробел, пробел. Что мы этим получили. Вывели шаблон. Быстро. Потом выводим время и дату в соответствии со знакоместами. Быстро. Кратко. Это простой пример. Да, некрасиво, не "в одну строку". Но оптимально. И по скорости и по выхлопу.
Последний раз редактировалось Demiurg Пн апр 11, 2022 18:31:29, всего редактировалось 1 раз.
- Сообщения: 362
- Зарегистрирован: Вс апр 03, 2022 07:01:29
Эммм... я тут чето потерял нить темы. Если не ошибасю, вначале у топикстартера была проблема с тем, что нужна была единая функция ввода чисел, так? Так вот, это реализуется одной единственной функцией, в которую передается указатель на изменяемую переменную, а кнопки просто инкрементируют или декрементируют эту переменную по указателю. Назначения функций кнопок выбираются через таблицу указателей на функции в соответствии с текущим режимом менюшки.
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Я в топике привел пример. В том примере у меня секунды, минуты, часы и так далее это отдельные участки памяти в соответствии с размерностью. То есть, до годов это байты. Год это уже два байта. При включении устройства считывается rtc и данные распаковывается по участкам памяти. Дальше я работаю с ними как с обычными шестнадцатеричными числами. Вот годы посложнее. Заманаешься инкремент и декремент производить.
Тут уже поразрядно. Опять же. Можно и все поразрядно. Но, все равно перевод в шестнадцатеричные числа.
У меня сейчас график жёсткий. Попробую в ближайшие дни урезать проект, оставить только часы и выложить свой пример.
У меня сейчас график жёсткий. Попробую в ближайшие дни урезать проект, оставить только часы и выложить свой пример.






