Jump to content

demiurg1978

Members
  • Content Count

    163
  • Joined

  • Last visited

Community Reputation

22 Обычный

About demiurg1978

  • Rank
    Осваивающийся

Информация

  • Город
    Новосибирск

Электроника

  • Стаж в электронике
    Более 20 лет
  • Сфера радиоэлектроники
    Новосибирская область
  • Оборудование
    Промышленное оборудование

Recent Profile Visitors

1080 profile views
  1. Лучше перебдеть. И если моя практика показывает положительный результат, значит так тому и быть. От всех случаев все равно не защититься.
  2. Ессно, нужно BOD включать. Все показывает практика. Есть один проект. Серия блоков управления. Работают уже несколько лет. Параметры хранятся в EEPROM. Жалоб нет. Там сделано следующим образом. При включении устройства параметры считываются в EEPROM. При выключении или пропадании сетевого напряжения параметры записываются в EEPROM. Ионистор.
  3. На самом деле 511 байтов. А дело вот в чем. При бросках напряжения, помехах, в EEPROM может записаться мусор. По указателю. Поэтому, первый байт никогда не используйте. В конце каждого чтения или записи выставляйте указатель на нулевой адрес. Чтобы указатель указывал на него. асм: clr RCLR .ifdef EEARH out EEARH,RCLR .endif out EEARL,RCLR ret си: #pragma location = 0x00 __eeprom u08 ee_empty_val = 0; //-------------------------------------------- volatile u08 a = ee_empty_val; break; } } }
  4. Например, то что я подарил идею, принцип, как делать сколько угодно сложные световые эффекты, да еще с выводом на микросхемы расширения ввода-вывода.
  5. Ггг, сижу читаю, мысль один в один. "Мир, дружба, жвачка"
  6. Фокус: __C_task main (void) { wdt_enable (WDTO_15_MS); sleep_mode_init (); init_soft_timers (); Init_Events (); __enable_interrupt (); #ifdef __LOGO__ logo (); #endif while (1) { __watchdog_reset (); proc_device (); kbd_drv (); info_service (); proc_outputs (); Process_Events (); } } //======================================================================== struct tab_logo_t __flash tab_logo [] = { {0, SEG_A}, // 0 {0, SEG_B}, // 1 {0, SEG_C}, // 2 {0, SEG_D}, // 3 {0, SEG_E}, // 4 {0, SEG_F}, // 5 {0, SEG_G}, // 6 {0, SEG_H}, // 7 {1<<LED_GREEN, 0}, // 8 {1<<LED_RED, 0}, // 9 {0, 0}, // 10 {(1<<LED_GREEN | 1<<LED_RED), (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_H)}, // 11 {0, 0}, // 12 {(1<<LED_GREEN | 1<<LED_RED), (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_H)}, // 13 {0, 0}, // 14 {0xFF, 0xFF}, // 15 }; //======================================================================== //======================================================================== void logo (void) { u08 _logo = 0; u08 logo_timer = 0; u08 cnt = 0; u08 i; soft_timer ST_LOGO; while (1) { __watchdog_reset (); switch (_logo) { case 0: soft_spi_init (); set_leds_buf (0); out_dsp_buf (0); set_soft_timer (ST_LOGO, OUTPUTS_PERIOD, OUTPUTS_PERIOD); _logo = 1; break; case 1: if (handle_soft_timer (ST_LOGO)) { if (++logo_timer >= LOGO_STEP) { logo_timer = 0; struct tab_logo_t __flash *ptr = tab_logo; ptr += cnt; if (ptr -> leds == 0xFF && ptr -> segments == 0xFF) return; set_leds_buf (ptr -> leds); for (i = 0; i < MAX_LED_IND; i++) dsp_buf [i] = ptr -> segments; cnt++; } i = 0; soft_spi_transf_buf [i++] = get_leds_buf (); for (u08 j = 0; j < MAX_LED_IND; j++) soft_spi_transf_buf [i++] = dsp_buf [j]; for (i = 0; i < SOFT_SPI_BYTES; i++) soft_spi_transf (i); strob_latch_out (); } break; } } } //======================================================================== //======================================================================== void out_dsp_buf (u08 a) { for (u08 i = 0; i < MAX_LED_IND; i++) dsp_buf [i] = a; } //======================================================================== Logo. Обратите внимание на локальные переменные. Дальше в проекте в модулях уже static и иногда extern. Я провернул трюк с локальными переменными. Видео не буду выкладывать. Это на семисегментном дисплее эффекты при включении прибора показываются.
  7. У меня подход - дробление ВСЕХ долгих процессов. Это сделано из-за привязки к системному тику. Никаких долгих циклов. Итерация основного цикла должна с запасом упаковаться в системный тик. В основном это 1 мс. Если у меня такой цикл: while (1) { __watchdog_reset (); proc_device (); kbd_drv (); info_service (); proc_outputs (); Process_Events (); } То он должен выполниться меньше чем за 1 мс. Что бы не было в этих функциях. proc_device - Алгоритм устройства. В том числе АЦП измерения. info_service - вывод информации в буфер. proc_outputs - расширение ввода-вывода. В том числе вывод на дисплей из семисегментных индикаторов.
  8. Вы, наверное, неправильно меня поняли. У меня не вывод на дисплей занимает 84 мс, а полное обновление экрана занимает 84 мс. Поясняю. Если мы будем выводить сразу 20x4 символов, это займет очень много времени. И чтобы как delay вывод не занимал процессорное время, я сделал следующим образом. Отвел в ОЗУ буфер размером Max_X * Max_Y. Специальная функция посимвольно, раз в 1 мс выводит по символу. Если новая строка, сначала отправка адреса. Итого: (20x4) + 4 адреса строк = 84 мс. Вывели адрес или символ, пошли заниматься другими делами. Такой подход сделан из-за помехочувствительности дисплеев. Если статично вывести информацию, через некоторое время на дисплее будут кракозябры. Поэтому идет периодичный вывод содержимого буфера на дисплей.
  9. Все зависит от проекта. Требований к быстродействию. Характера выводимой информации. Статика, динамика. Полное обновление дисплея при посимвольном выводе и 20х4 занимает 84 мс. Если пачками выводить, выйдет быстрее. Так как дисплей медленное устройство, тормозить выполнение прграммы на время вывода информации настолько же неумное решение, как использование delay.
  10. Cлона даже большим ртом можно съесть только кусочками. Это я к тому, если полное обновление занимает много времени, дробите процесс. Посимвольно (каждые 1 мс), по 5 или 10 символов за определенное время. Скажем, каждые 10 мс.
  11. Задержки от единиц мс нужно делать на программных таймерах. Вкратце. Таймер настраивается на тик. Значение зависит от проекта и требуемых минимальных задержек на программных таймерах. 1 мс, 10 мс, 100 мс. Нужное значение кладем в регистр совпадения. Включаем прерывание по совпадению. В прерывании переменная-счетчик считает тики. В основном цикле считываем значение переменной-счетчика, прибавляем к ней нужное количество тиков. Как только накрутило нужное время, что-то делаем.
  12. Вот модуль меню. Ссылка. Он в составе модуля вывода информации. В структуре вы увидите ссылки на функции. Сам модуль вывода информации конечный автомат. Позже дополню.
  13. Я под IAR переделал. Помучался, конечно. Бросал это дело, делал как Arv, на массивах. Не понравилось, сел разобрался и все. Нужно понимать, что суть MicroMenu в навигации. Бесплатным бонусом - не нужно запоминать пути. Все уже прописано. Редактировать переменные не сложно. Вечером выложу пример.
  14. Просто для примера: //======================================================================================================================================================================================================================================================= // NAME PARENT NEXT_LEVEL NEXT_ITEM PREV_ITEM ENTER_FUNC PLUS_FUNC MINUS_FUNC MENU_INIT_FUNC TEXT //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MAKE_MENU (L_OUT_I_ABC, NULL_ENTRY, L_MENU_TIME, NULL_ENTRY, NULL_ENTRY, NULL_FUNC, NULL_FUNC, NULL_FUNC, info_service_out_i_init, "ПАРАМЕТРЫ"); MAKE_MENU (L_MENU_TIME, L_OUT_I_ABC, L_MENU_SET_TIME, L_MENU_CURRENT, NULL_ENTRY, NULL_FUNC, NULL_FUNC, NULL_FUNC, menu_init, "ВРЕМЯ"); MAKE_MENU (L_MENU_CURRENT, L_OUT_I_ABC, L_MENU_MIN_CURR, L_MENU_CYCLE, L_MENU_TIME, NULL_FUNC, NULL_FUNC, NULL_FUNC, menu_init, "ТОК"); MAKE_MENU (L_MENU_CYCLE, L_OUT_I_ABC, L_MENU_QUANT_PASS, NULL_ENTRY, L_MENU_CURRENT, NULL_FUNC, NULL_FUNC, NULL_FUNC, menu_init, "ЦИКЛ"); Есть разница? Создание и редактирование меню в одном месте.
  15. Давай куда-нибудь выйдем, отдельно обсудим, чтобы здесь не засорять. Как связаться?
×
×
  • Create New...