| Форум РадиоКот https://radiokot.ru/forum/ |
|
| Оптимизация кода на С, возможно ли для этого кода? https://radiokot.ru/forum/viewtopic.php?f=57&t=190675 |
Страница 1 из 2 |
| Автор: | grachevvlad2023 [ Вс ноя 05, 2023 20:23:39 ] |
| Заголовок сообщения: | Оптимизация кода на С, возможно ли для этого кода? |
Всем привет. Можно ли как то оптимизировать и сократить этот код? У кого какие идеи? А то что то громоздкий получился. СпойлерКод: #define F_CPU 32000000UL #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <util/delay.h> #include "keyboard.h" #include "lcd_lib.h" #define PAUSE 150 int k = 0; int b = 0; int i = 0; int c = 0; int cont = 0; int col[5] = {0b00000000, 0b00000001, 0b00000010, 0b00000100, 0b00001000}; int row[6] = {0b00011111, 0b00011110, 0b00011101, 0b00011011, 0b00010111, 0b00001111}; unsigned char buf = 0; unsigned char buttons[4]; void selectKey(int r, int c, int delay) { PORTD = col[r]; PORTC = row[c]; _delay_ms(PAUSE); PORTC = row[0]; PORTD = col[0]; _delay_ms(delay); } void send(void) { selectKey(1, 5, PAUSE); // RES selectKey(1, 4, PAUSE); // PRI selectKey(1, 1, PAUSE); // TOT selectKey(1, 2, PAUSE); // CAL int i; for ( i = 0; i < 4; i++) { selectKey(3, 5, PAUSE); // 0 } selectKey(4, 5, PAUSE); // OK selectKey(2, 2, PAUSE); // 1 } void end(void) { selectKey(1, 4, PAUSE); // PRI selectKey(1, 5, PAUSE); // RES } void fin(void) { LCD_Clear(); LCD_Goto(0, 0); LCD_SendString("Kod otpravlen! "); _delay_ms(1000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } cont = 0; } int main(void) { DDRD=0xFF; DDRC=0xFF; LCD_Init(); LCD_Goto(0, 0); LCD_SendString("Vvedite "); LCD_Goto(4, 1); LCD_SendString("Koefitsent: "); _delay_ms(2000); LCD_Clear(); KEYB_Init(); while (1) { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if (buf) { if (b < 4 && buf != '*'&& buf != '#') { // Проверяем, есть ли еще место в массиве и выполняем ограничения на ввод if (b == 0 && buf != '1') { LCD_Goto(0, 0); LCD_SendString("Oshibka"); _delay_ms(2000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } continue; // Пропускаем ввод, если первый адрес массива не равен единице } if (b == 1 && (buf != '0' && buf != '1')) { LCD_Clear(); LCD_Goto(0, 0); LCD_SendString("Oshibka"); _delay_ms(2000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } continue; // Пропускаем ввод, если второй адрес массива не равен нулю или единице } buttons[b++] = buf; LCD_Goto(k++, 1); LCD_WriteData(buf); } if (buf == '*') { for (c = 0; c < 4; c++) { if (buttons[c] >= '0' && buttons[c] <= '9') { int digit = buttons[c] - '0'; cont = cont * 10 + digit; } } switch(cont) { case 1001: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1002: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1003: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1004: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1005: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1006: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1007: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1008: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1009: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1010: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1011: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1012: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1013: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1014: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1015: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1016: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1017: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1018: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1019: send(); selectKey(3, 5, PAUSE); selectKey(2, 2, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1020: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1021: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1022: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1023: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1024: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1025: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1026: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1027: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1028: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1029: send(); selectKey(3, 5, PAUSE); selectKey(3, 2, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1030: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1031: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1032: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1033: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1034: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1035: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1036: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1037: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1038: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1039: send(); selectKey(3, 5, PAUSE); selectKey(4, 2, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1040: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1041: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1042: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1043: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1044: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1045: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1046: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1047: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1048: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1049: send(); selectKey(3, 5, PAUSE); selectKey(2, 3, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1050: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1051: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1052: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1053: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1054: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1055: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1056: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1057: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1058: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1059: send(); selectKey(3, 5, PAUSE); selectKey(3, 3, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1060: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1061: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1062: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1063: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1064: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1065: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1066: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1067: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1068: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1069: send(); selectKey(3, 5, PAUSE); selectKey(4, 3, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1070: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1071: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1072: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1073: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1074: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1075: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1076: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1077: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1078: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1079: send(); selectKey(3, 5, PAUSE); selectKey(2, 4, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1080: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1081: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1082: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1083: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1084: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1085: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1086: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1087: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1088: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1089: send(); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1090: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; case 1091: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(2, 2, PAUSE); end(); fin(); break; case 1092: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(3, 2, PAUSE); end(); fin(); break; case 1093: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(4, 2, PAUSE); end(); fin(); break; case 1094: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(2, 3, PAUSE); end(); fin(); break; case 1095: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(3, 3, PAUSE); end(); fin(); break; case 1096: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(4, 3, PAUSE); end(); fin(); break; case 1097: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(2, 4, PAUSE); end(); fin(); break; case 1098: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; case 1099: send(); selectKey(3, 5, PAUSE); selectKey(4, 4, PAUSE); selectKey(4, 4, PAUSE); end(); fin(); break; case 1100: send(); selectKey(2, 2, PAUSE); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); end(); fin(); break; } } if (b > 0&&buf == '#') { LCD_Clear(); LCD_Goto(0, 4); LCD_SendString("Ochistka"); _delay_ms(2000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } } } } return 0; } |
|
| Автор: | Martian [ Вс ноя 05, 2023 20:38:51 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
ну хотя бы send(); end(); fin(); выкинуть из каждого case. И какой смысл передавать одну и ту же PAUSE в selectKey? но без алгоритма такую портянку оптимизировать - только за деньги. Но думаю, что cont явно просится передаться в selectKey без всяких switch-case... |
|
| Автор: | grachevvlad2023 [ Вс ноя 05, 2023 20:55:09 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
...но без алгоритма такую портянку оптимизировать - только за деньги. .. В этом коде при наборе комбинации от 1001 до 1100 происходит последовательное включение светодиодов в определенном порядке. С начало идёт включение по функции send(); затем набранная комбинация после чего команды из функции end(); после чего вывод на ЖК дисплей через функцию fin(); хотя думаю end(); и fin(); можно было объединить в одну. |
|
| Автор: | Martian [ Вс ноя 05, 2023 21:01:55 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
эта комбинация как формируется? могу я изменить правило формирования, например, не 1001...1100, а 1002...1202, то есть, те же сто, только все чётные? или эти числа где-то ещё используются - отображаются? |
|
| Автор: | grachevvlad2023 [ Вс ноя 05, 2023 21:18:39 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
эта комбинация как формируется?... Прикрепил схему. Функция send(); поочерёдно включает комбинацию светодиодов RES-PRI-TOT-CALL-0-OK-1. Затем поочередно включает последовательность набранной комбинации с клавиатуры. Оно может быть от 1001, 1002, 1003 и тд. до 1100. К примеру, комбинация 1012 будет выглядеть так: Код: selectKey(3, 5, PAUSE); // 0 selectKey(2, 2, PAUSE); //1 selectKey(3, 2, PAUSE); //2 Начальная единица уже прописана внутри функции send(); и в коде проверяется на её присутствие, если начальный символ другой то код выдаст ошибку и остановиться. 1100 конечная максимальная комбинация, далее нельзя. Затем срабатывает комбинация из функции end(); При этом поочерёдно включаются и выключаются светодиоды PRI и RES. Подправил функцию Код: void selectKey(int r, int c) { PORTD = col[r]; PORTC = row[c]; _delay_ms(PAUSE); PORTC = row[0]; PORTD = col[0]; _delay_ms(PAUSE); } и Код: void end(void) { selectKey(1, 4); // PRI selectKey(1, 5); // RES _delay_ms(2); LCD_Clear(); LCD_Goto(0, 0); LCD_SendString("Kod otpravlen! "); _delay_ms(1000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } cont = 0; } Теперь switch выглядит так: Код: case 1001: send(); selectKey(3, 5); selectKey(3, 5); selectKey(2, 2); end(); break; ЗЫ: PAUSE устанавливает время через которое светодиоды должны отключиться. |
|
| Автор: | Martian [ Вс ноя 05, 2023 21:56:50 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
Массивы можно выбросить. из аргументов selectKey убрать PAUSE - она нигде не отличается тогда получится: Код: void selectKey(unsigned char r, unsigned char c) // чтобы не вычитать единицу, номера столбов-строк должны начинаться с 0 { PORTD = (unsigned char)(1 << r); PORTC = (0x1f & (unsigned char)(~(1 << c))); _delay_ms(PAUSE); PORTC = 0x1f; PORTD = 0; _delay_ms(PAUSE); } ну и это: Код: switch(cont) { case 1001: send(); selectKey(3, 5, PAUSE); selectKey(3, 5, PAUSE); selectKey(3, 4, PAUSE); end(); fin(); break; переписать как Код: send(); switch(cont) { case 1001: selectKey(2, 4); selectKey(2, 4); selectKey(2, 3); break; } end(); fin(); 299 строк минус... Добавлено after 12 minutes 44 seconds: но если я правильно понял алгоритм, то весь этот громадный switch сокращается до перебора буфера и отправки каждой цифры: Код: send(); for (i = 0; i < 4; i++) { switch(buttons[i] - '0') { case 0: selectKey(3, 5, PAUSE); break; case 1: selectKey(3, 5, PAUSE); break; case 2: selectKey(3, 5, PAUSE); break; case 3: selectKey(3, 5, PAUSE); break; case 4: selectKey(3, 5, PAUSE); break; case 5: selectKey(3, 5, PAUSE); break; case 6: selectKey(3, 5, PAUSE); break; case 7: selectKey(3, 5, PAUSE); break; case 8: selectKey(3, 5, PAUSE); break; case 9: selectKey(3, 5, PAUSE); break; } end(); fin(); только надо поставитm правильные строки-столбцы. ну и можно выкинуть PAUSE А можно снова воспользоваться массивами. тогда сократится до Код: send(); for (i = 0; i < 4; i++) { selectKey(arr1[buttons[i] - '0'], arr2[buttons[i] - '0'], PAUSE); } end(); fin(); в общем, есть куда ещё подумать. |
|
| Автор: | grachevvlad2023 [ Вс ноя 05, 2023 22:03:04 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
если я правильно понял алгоритм, то весь это громадный switch сокращается Почти да, но в Вашем коде комбинация от 0 до 9. А в моём от 1001 до 1100. Спасибо за подсказки и советы. ЗЫ: а вот над этим Код: { мне надо поэкспериментировать )
selectKey(arr1[buttons[i] - '0'], arr2[buttons[i] - '0'], PAUSE); } |
|
| Автор: | Martian [ Вс ноя 05, 2023 22:04:56 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
Вы перебрали все 100 вариантов для комбинаций буфера я же перебрал 10 вариантов для каждой ячейки в буфере. если буфер станет 100 ячеек, в моём варианте достаточно изменить число итераций в цикле. а в Вашем? дописать ещё десяток тыщ строк... |
|
| Автор: | veso74 [ Пн ноя 06, 2023 10:34:42 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
Бы попробовал заменить "длинный" switch(count) на напр. 6 массивов возможных состояний. Написанно так будет "короче" как код (будет произведена только замена с данными (один раз в осн. цикле), заданными индексом массива). (Не гарантирую, что будет занимать меньше ресурса (памяти). Должно быть проверено). Пример: Код: const uint8_t r0[] = {3, 3, 3 ... }; const uint8_t c0[] = {5, 5, 5 ... }; const uint8_t r1[] = {3, 3, 3 ... }; const uint8_t c1[] = {5, 5, 5 ... }; const uint8_t r2[] = {2, 3, 4 ... }; const uint8_t c2[] = {2, 2, 2 ... }; ... uint8_t x = count - 1001; send(); selectKey(r0[x], c0[x]); selectKey(r1[x], c1[x]); selectKey(r2[x], c2[x]); end(); fin(); (Если выбранный компилятор сам не помещает массивы во flash (const), добавьте необходимые функции/команды для этого). |
|
| Автор: | AlexS4 [ Пн ноя 06, 2023 13:06:35 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
по мне так самая очевидная оптимизация switch(cont) это просто использовать массив из 2-3-4 байтных константных слов, упаковать можно множеством способов, хоть побитно, хоть используя 2й индекс , после получения указателя - разбирать их и грузить куда нужно. исходный это какойто кошмар с которым никакой O2 не справится, это и по размеру кода в разы и по нагрузке на ядро вдвое неэффективно. на научном языке такое называется классический ГК Добавлено after 18 minutes 16 seconds: забавно veso74 почти тожесамое написал, не даром говорят у программистов мысли совпадают |
|
| Автор: | Azeront [ Пн ноя 06, 2023 15:49:18 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
1. В оригинальной функции selectKey два раза используется функция _delay_ms, причем при первом вызове всегда передается константа PAUSE, а при втором вызове - аргумент delay. С учетом того, что далее по коду в функцию selectKey в качестве аргумента delay всегда передается константа PAUSE, то это выглядит крайне странно. Если вам нужно выдерживать 2 разных по длительности интервала, то используйте и 2 разных константы (или макросы, как у вас). Иначе это выглядит как опечатка, и оба вызова _delay_ms должны быть с аргументом delay. Как заметил Martian, можно просто убрать аргумент delay и сразу прописать PAUSE, т.к. как я понял этот интервал зависит от аппаратной реализации вашей схемы, и не меняется в runtime. 2. При вводе числового кода, у вас есть проверка на то, что первые 2 цифры должны быть "10" или "11". Проверка разделена на 2 условия, и в обоих условиях продублирован практически один и тот же код. Можно объединить в одну проверку: СпойлерКод: // Пропускаем ввод, если первый адрес массива не равен единице char isKeycodeInvalid_First = (b == 0 && buf != '1'); // Пропускаем ввод, если второй адрес массива не равен нулю или единице char isKeycodeInvalid_Second = (b == 1 && (buf != '0' && buf != '1')); if (isKeycodeInvalid_First || isKeycodeInvalid_Second) { if (isKeycodeInvalid_Second) LCD_Clear(); LCD_Goto(0, 0); LCD_SendString("Oshibka"); _delay_ms(2000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) buttons[i] = 0; continue; } Кроме того, часть алгоритма (очистка переменных b, k и buttons, очистка LCD) также продублирована в методе fin. Это тоже можно оптимизировать, либо а) вынести общую часть алгоритма очитки в отдельную функцию, и вызывать эту функцию из функции fin и из условия проверки первых двух цифр, либо б) сделать одну общую функцию "завершения ввода комбинации", в которую через аргументы передавать причину очистки (строки "Код отправлен!", "Ошибка", "Очистка" через аргумент типа const char*). 3. Как уже отметили veso74 и AlexS4, можно использовать массив значений для функции selectKey. Я бы использовал массив структур, т.к. не уловил закономерности (зависимость вводимого кода 1001-1100 от порядка и номеров установки Row и Col при вызове selectKey): СпойлерКод: typedef struct { char Row; char Col; } TSelectedKey; typedef struct { TSelectedKey Key[3]; } TSelectedKeys; // все возможные комбинации const TSelectedKeys SelectedKeys[100] = { { {3, 5}, {3, 5}, {2, 2} }, // 1001 { {3, 5}, {3, 5}, {3, 2} }, // 1002 { {3, 5}, {3, 5}, {4, 2} }, // 1003 { {3, 5}, {3, 5}, {2, 3} }, // 1004 { {3, 5}, {3, 5}, {3, 3} }, // 1005 ... // и т.д. }; ... // работаем с оригинальной глобальной переменной 'cont', в которой уже посчитано введённое значение { int index = cont - (1001); // т.к. массивы индексируются с нуля const TSelectedKey* key = SelectedKeys[index].Key; // далее из оригинала: send(); selectKey(key[0].Row, key[0].Col, PAUSE); selectKey(key[1].Row, key[1].Col, PAUSE); selectKey(key[2].Row, key[2].Col, PAUSE); end(); fin(); } Однако тут есть важное замечание: для работы с массивами вам необходимо организовать проверку на выход за границы этого самого массива (при использовании "динамического" индекса)! Например, в оригинальном коде не было проверки на вводимые числа 1101-1199, есть только отдельные проверки на *0**-*1** и **00-**99, что не эквивалентно проверке *001-*100. При этом в оригинальном коде использовался switch-case, и все неописанные комбинации не выполнялись (не изменялось состояние портов). Т.е. при нажатии 'звездочки' при неправильном числовом коде ничего не происходило: ни пины не дергались, ни дисплей не реагировал, но можно было это стереть через 'решетку'. При использовании же массивов всегда будет что-то выполняться, и если входные данные некорректные, то программа просто поломается (лечится перезагрузкой МК). P.S. Пишите понятные имена объектов. Функции вы нормально назвали (по имени ясно, что она делает), а вот переменные обделили (b, k, ...) |
|
| Автор: | Martian [ Пн ноя 06, 2023 18:57:05 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
Да не надо там такой громадный массив. Там приблизительно такая логика: есть некий буфер, размером 4. Его цифровое десятичное содержимое (или часть) надо последовательно высветить на экране. Вот и всё. Так как каждое значение имеет лишь десять вариантов, то просо необходим цикл с числом итераций не больше размера этого буфера, где либо проверяется на совпадение одному из 10 состояний, либо адресуется к массиву[10] |
|
| Автор: | grachevvlad2023 [ Вт ноя 07, 2023 21:21:17 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
Используя Ваши подсказки и советы, за что Вам премного благодарен, немного переписал код и теперь он состоит только из 651 строк против начальных ~2900.: СпойлерКод: #define F_CPU 32000000UL // Определение тактовой частоты для функций задержки #include <inttypes.h> // Библиотека для работы с типами int #include <avr/io.h> // Библиотека для ввода-вывода #include <avr/interrupt.h> // Библиотека для работы с прерываниями #include <avr/sleep.h> // Библиотека для управления режимами сна #include <util/delay.h> // Библиотека для работы с задержками #include "keyboard.h" // Библиотека для работы с клавиатурой #include "lcd_lib.h" // Библиотека для работы с LCD #define PAUSE 150 // Определение времени задержки int k = 0; int b = 0; int i = 0; int c = 0; int cont = 0; // Определение столбцов и строк int col[5] = {0b00000000, 0b00000001, 0b00000010, 0b00000100, 0b00001000}; int row[6] = {0b00011111, 0b00011110, 0b00011101, 0b00011011, 0b00010111, 0b00001111}; unsigned char buf = 0; unsigned char buttons[4]; // Функция выбора ключа void selectKey(int r, int c) { PORTD = col[r]; // Выбор столбца PORTC = row[c]; // Выбор строки _delay_ms(PAUSE); // Ждем PORTC = row[0]; // Выбираем первую строку PORTD = col[0]; // Выбираем первый столбец _delay_ms(PAUSE); // Ждем } // Функция отправки void send(void) { selectKey(1, 5); // RES selectKey(1, 4); // PRI selectKey(1, 1); // TOT selectKey(1, 2); // CAL int i; for ( i = 0; i < 4; i++) { selectKey(3, 5); // 0 } selectKey(4, 5); // OK selectKey(2, 2); // 1 } // Функция завершения void end(void) { selectKey(1, 4); // PRI selectKey(1, 5); // RES _delay_ms(2); // задержка LCD_Clear(); // очищаем экран LCD_Goto(0, 0); // выбираем позицию на экране LCD_SendString("Kod otpravlen! "); // выводим сообщение _delay_ms(1000); // задержка LCD_Clear(); // очищаем экран b = 0; k = 0; for (i = 0; i < 4; i++) // обнуляем массив { buttons[i] = 0; } cont = 0; // обнуляем вход } int main(void) { // Установить все выводы порта D и C как выводы DDRD=0xFF; DDRC=0xFF; // Инициализировать LCD, установить курсор в начало и отобразить сообщение. LCD_Init(); LCD_Goto(0, 0); LCD_SendString("Vvedite "); LCD_Goto(4, 1); LCD_SendString("Koefitsent: "); _delay_ms(2000); // задержка LCD_Clear(); // очищаем экран KEYB_Init(); // инициализируем клавиатуру //начинаем основной цикл while (1) { // сканируем клавиатуру и получаем значение введенной клавиши KEYB_ScanKeyboard(); buf = KEYB_GetKey(); // если была нажата клавиша if (buf) { // условие ввода символов и исключения некоторых клавиш if (b < 4 && buf != '*'&& buf != '#') { // проверяем правильность кода char isKeycodeInvalid_First = (b == 0 && buf != '1'); char isKeycodeInvalid_Second = (b == 1 && (buf != '0' && buf != '1')); if (isKeycodeInvalid_First || isKeycodeInvalid_Second) { if (isKeycodeInvalid_Second) LCD_Clear(); LCD_Goto(0, 0); LCD_SendString("Oshibka"); _delay_ms(2000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) buttons[i] = 0; continue; } buttons[b++] = buf; LCD_Goto(k++, 1); LCD_WriteData(buf); } // по нажатию '*' выполняем обработку и отправку введенных данных if (buf == '*') { for (c = 0; c < 4; c++) { if (buttons[c] >= '0' && buttons[c] <= '9') { int digit = buttons[c] - '0'; cont = cont * 10 + digit; } } send(); switch(cont) // здесь указана привязка введенных значений к функциям (это нужно прокомментировать подробнее) { case 1000: selectKey(3, 5); selectKey(3, 5); selectKey(3, 5); break; // и так далее... для каждого действия } end(); } // Клавиша '#' очищает все введенные значения if (b > 0&&buf == '#') { LCD_Clear(); LCD_Goto(0, 4); LCD_SendString("Ochistka"); _delay_ms(2000); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } } } } return 0; } |
|
| Автор: | Martian [ Вт ноя 07, 2023 21:55:02 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
что-то странное и очень много. Рискну утверждать, что ниже приведенный код из 154 строк эквивалентен начальному на 99% Код: #define F_CPU 32000000UL #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <util/delay.h> #include "keyboard.h" #include "lcd_lib.h" #define PAUSE 150 unsigned char k = 0; unsigned char b = 0; unsigned char i = 0; unsigned char buf = 0; unsigned char col[5] = {0b00000000, 0b00000001, 0b00000010, 0b00000100, 0b00001000}; unsigned char row[6] = {0b00011111, 0b00011110, 0b00011101, 0b00011011, 0b00010111, 0b00001111}; unsigned char buttons[4]; void selectKey(unsigned char r, unsigned char c) { PORTD = col[r]; PORTC = row[c]; _delay_ms(PAUSE); PORTC = row[0]; PORTD = col[0]; _delay_ms(PAUSE); } void clear(void) { LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } } void send(void) { selectKey(1, 5); // RES selectKey(1, 4); // PRI selectKey(1, 1); // TOT selectKey(1, 2); // CAL for (i = 0; i < 4; i++) { selectKey(3, 5); // 0 } selectKey(4, 5); // OK selectKey(2, 2); // 1 } void end(void) { selectKey(1, 4); // PRI selectKey(1, 5); // RES LCD_Clear(); LCD_Goto(0, 0); LCD_SendString("Kod otpravlen! "); _delay_ms(1000); clear(); } int main(void) { DDRD=0xFF; DDRC=0xFF; LCD_Init(); LCD_Goto(0, 0); LCD_SendString("Vvedite "); LCD_Goto(4, 1); LCD_SendString("Koefitsent: "); _delay_ms(2000); LCD_Clear(); KEYB_Init(); while (1) { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if (buf) { if (b < 4 && buf != '*'&& buf != '#') { // Проверяем, есть ли еще место в массиве и выполняем ограничения на ввод if ((b == 0 && buf != '1') || (b == 1 && (buf != '0' && buf != '1'))) { LCD_Goto(0, 0); LCD_SendString("Oshibka"); _delay_ms(2000); clear(); continue; // Пропускаем ввод, если первый адрес массива не равен единице и если если второй адрес массива не равен нулю или единице } buttons[b++] = buf; LCD_Goto(k++, 1); LCD_WriteData(buf); } if ((buf == '*') && (buttons[0] = '1')) { send(); for (i = 1; i < 4; i++) { switch(buttons[i]) { case '0': selectKey(3, 5); break; case '1': selectKey(2, 2); break; case '2': selectKey(3, 2); break; case '3': selectKey(4, 2); break; case '4': selectKey(2, 3); break; case '5': selectKey(3, 3); break; case '6': selectKey(4, 3); break; case '7': selectKey(2, 4); break; case '8': selectKey(3, 4); break; case '9': selectKey(4, 4); break; } end(); } if (b > 0&&buf == '#') { LCD_Clear(); LCD_Goto(0, 4); LCD_SendString("Ochistka"); _delay_ms(2000); LCD_Clear(); clear(); } } } } Добавлено after 5 minutes 26 seconds: и думаю, что можно ещё оптимизировать. Особенно в плане проверки этого: Код: if (buf) { if (b < 4 && buf != '*'&& buf != '#') { // Проверяем, есть ли еще место в массиве и выполняем ограничения на ввод if ((b == 0 && buf != '1') || (b == 1 && (buf != '0' && buf != '1'))) но мне неохота разбираться, верно ли сиё алгоритму. Но чувствуется некое противоречие |
|
| Автор: | grachevvlad2023 [ Вт ноя 07, 2023 22:21:06 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
что-то странное и очень много. Рискну утверждать, что ниже приведенный код из 154 строк эквивалентен начальному на 99% Проверил Ваш код. При вводе 1012, или 1058 отрабатывает 1 и 0, при вводе 1100 отрабатывает 1 и 1. Два конечных символов не отрабатываются в switch. |
|
| Автор: | Martian [ Вт ноя 07, 2023 22:53:08 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
ну, это и есть 1% - я ж досконально не знаю алгоритма. Но он всё же отрабатывает, значит, осталось откорректировать в каком порядке и сколько должно браться, и с каким элементом в буфере сравнивается '1' то есть, всего лишь это: Код: if ((buf == '*') && (buttons[0] = '1')) { send(); for (i = 1; i < 4; i++) и условие заполнения буфера тоже проверить: Код: if (b < 4 && buf != '*'&& buf != '#') { // Проверяем, есть ли еще место в массиве и выполняем ограничения на ввод if ((b == 0 && buf != '1') || (b == 1 && (buf != '0' && buf != '1'))) { Добавлено after 24 minutes 47 seconds: Поскольку в некоторых функциях уже нет нужды (send и end), можно их исключить, и оптимизировать вывод на дисплей. Итого 134 строк. Код: #define F_CPU 32000000UL
#include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <util/delay.h> #include "keyboard.h" #include "lcd_lib.h" #define PAUSE 150 unsigned char k = 0; unsigned char b = 0; unsigned char i = 0; unsigned char buf = 0; unsigned char col[5] = {0b00000000, 0b00000001, 0b00000010, 0b00000100, 0b00001000}; unsigned char row[6] = {0b00011111, 0b00011110, 0b00011101, 0b00011011, 0b00010111, 0b00001111}; unsigned char buttons[4]; void selectKey(unsigned char r, unsigned char c) { PORTD = col[r]; PORTC = row[c]; _delay_ms(PAUSE); PORTC = row[0]; PORTD = col[0]; _delay_ms(PAUSE); } void Message(string message, unsigned short delay) { LCD_Clear(); LCD_Goto(0, 0); LCD_SendString(message); _delay_ms(delay); LCD_Clear(); b = 0; k = 0; for (i = 0; i < 4; i++) { buttons[i] = 0; } } int main(void) { DDRD=0xFF; DDRC=0xFF; LCD_Init(); LCD_Goto(0, 0); LCD_SendString("Vvedite "); LCD_Goto(4, 1); LCD_SendString("Koefitsent: "); _delay_ms(2000); LCD_Clear(); KEYB_Init(); while (1) { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if (buf) { if ((b < 4) && (buf != '*') && (buf != '#')) { // Проверяем, есть ли еще место в массиве и выполняем ограничения на ввод if (((b == 0) && (buf != '1')) || ((b == 1) && ((buf != '0') && (buf != '1')))) { Message("Oshibka", 2000); continue; // Пропускаем ввод, если первый адрес массива не равен единице } buttons[b++] = buf; LCD_Goto(k++, 1); LCD_WriteData(buf); } if (buf == '*') { selectKey(1, 5); // RES selectKey(1, 4); // PRI selectKey(1, 1); // TOT selectKey(1, 2); // CAL for (i = 0; i < 4; i++) { selectKey(3, 5); // 0 } selectKey(4, 5); // OK for (i = 0; i < 4; i++) { switch(buttons[i]) { case '0': selectKey(3, 5); break; case '1': selectKey(2, 2); break; case '2': selectKey(3, 2); break; case '3': selectKey(4, 2); break; case '4': selectKey(2, 3); break; case '5': selectKey(3, 3); break; case '6': selectKey(4, 3); break; case '7': selectKey(2, 4); break; case '8': selectKey(3, 4); break; case '9': selectKey(4, 4); break; } selectKey(1, 4); // PRI selectKey(1, 5); // RES Message("Kod otpravlen!", 1000); } if ((b > 0) && (buf == '#')) { Message("Ochistka", 2000); } } } } |
|
| Автор: | grachevvlad2023 [ Ср ноя 08, 2023 10:17:07 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
ну, это и есть 1% - я ж досконально не знаю алгоритма... Как отправить Вм видео файл работы устройства? Вы бы смогли понять алгоритм.. |
|
| Автор: | Martian [ Ср ноя 08, 2023 10:22:31 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
А зачем? Вам осталось совсем немного, код получился простой, довести до ума совершенно не сложно. Да и не люблю алгоритмы на видео, я люблю их в виде блок-схем или хотя бы подробного текстового описания.... |
|
| Автор: | grachevvlad2023 [ Ср ноя 08, 2023 10:44:48 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
Прикрепил видео работы устройства. СпойлерТак же прикрепил немного оптимизированный код. |
|
| Автор: | Martian [ Ср ноя 08, 2023 10:47:55 ] |
| Заголовок сообщения: | Re: Оптимизация кода на С, возможно ли для этого кода? |
grachevvlad2023 писал(а): Так же прикрепил немного оптимизированный код. Поглядел. Осознал, что я зря потратил время... |
|
| Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


