/* Проверка load_control на модели ПК. Русские пояснения сохранены в UTF-8. */ /* Подключает : настройки и интерфейс stdio. */ #include /* Подключает : настройки и интерфейс string. */ #include /* Подключает "../../Source/Internal/DAC.c": выход ЦАП и автомат защиты нагрузки с проверкой напряжения и свежести CAN. */ #include "../../Source/Internal/DAC.c" /* Объявляет READY — данные READY; Desk — аппаратно определённый тип платы; Mode — рабочий адрес или режим платы, выбранный перемычками. Начальное значение задаётся справа от знака равенства. */ int READY = 1, Desk = 6, Mode = 5; /* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит. */ int modbus[128]; /* Объявляет test_start — данные test_start; test_stop — данные test_stop; test_permission — данные test_permission; test_tick — данные test_tick. */ unsigned int test_start, test_stop, test_permission, test_tick; /* Объявляет test_starts — данные test_starts; test_last_stop_tick — данные test_last_stop_tick; test_last_start_tick — данные test_last_start_tick; test_init_dac — test init ЦАП. */ unsigned int test_starts, test_last_stop_tick, test_last_start_tick, test_init_dac; /* Объявляет test_bad_order — данные test_bad_order. */ int test_bad_order; /* Задаёт CHECK = do { if (!(x)) { printf("FAIL line %d: %s\n", __LINE__, #x); return 1; } } while (0); данные CHECK. */ #define CHECK(x) do { if (!(x)) { printf("FAIL line %d: %s\n", __LINE__, #x); return 1; } } while (0) /* Начинает функцию setup; назначение модуля — проверка load_control на модели ПК. */ static void setup(int mode) { /* Записывает Mode значением mode; READY = 1; рабочий адрес или режим платы, выбранный перемычками. */ memset(modbus, 0, sizeof(modbus)); Mode = mode; READY = 1; /* Записывает test_start значением test_stop = test_permission = test_tick = test_starts = 0; данные test_start. */ test_start = test_stop = test_permission = test_tick = test_starts = 0; /* Записывает test_bad_order значением test_init_dac = 0; данные test_bad_order. */ test_bad_order = test_init_dac = 0; /* Записывает WAKEpowse значением 0; данные WAKEpowse. */ Load_control_init(); Setup_DAC_time(); WAKEpowse = 0; /* Записывает DAC_go значением 4; DAC_stop = 16; DAC_min() = 100; DAC_max() = 3000; начальный ток нагрузки в мА, технологический регистр 0x50. */ DAC_go = 4; DAC_stop = 16; DAC_min() = 100; DAC_max() = 3000; /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Начинает функцию tick; назначение модуля — проверка load_control на модели ПК. */ static void tick(unsigned int n, int exchange, unsigned int volts) { /* Повторяет или ожидает, пока выполняется while (n--). */ while (n--) { /* Проверяет if (exchange) Load_voltage_can(0x8000U | (Mode == 5 ? 305U : 8U), volts, 0, 0); последующий оператор выполняется только при истинном условии. */ if (exchange) Load_voltage_can(0x8000U | (Mode == 5 ? 305U : 8U), volts, 0, 0); /* Изменяет счётчик в выражении test_tick++; Load_runner(); на один для следующего шага. */ test_tick++; Load_runner(); /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Проверяет штатные 6 мА, трёхсекундную реакцию ЗПТ и сохранение защитных остановов на настоящем DAC.c. */ static int startup_test(void) { /* mode перебирает УМП 5/6, attempt контролирует пять пусков, code хранит отправленный код, count — оставшиеся токовые такты ожидания. */ unsigned int mode, attempt, code, count; /* Проверяет оба штатных CAN-индекса: ЗПТ1 у УМП 5 и ЗПТ2 у УМП 6. */ for (mode = 5; mode <= 6; mode++) { /* Подаёт START при заводских 6 мА и свежем нулевом ЗПТ; первые 10 мс включают базовый и стартовый кадры ЦАП. */ setup(mode); DAC_go = 6; Commands = 0x80; tick(10, 1, 0); /* Первая попытка должна удерживать разрешение и получить 6 мА вместо мгновенного STOP. */ CHECK(test_starts == 1 && test_start && test_permission && !test_stop && modbus[0x1C] == 60 && modbus[123] != DAC_min()); /* Запоминает код 6 мА для исключения скрытого повышения тока до подтверждённых 30 В. */ code = modbus[123]; /* Проверяет последний миллисекундный такт перед тремя секундами от первой отправки 6 мА. */ tick(2999, 1, 29); /* До конца выдержки сохраняет одну попытку, рабочее состояние и прежнее задание в масштабе 0,1 мА. */ CHECK(load_state == LOAD_RUN && load_attempts == 1 && modbus[0x1C] == 60 && (unsigned int)modbus[123] == code); /* Ровно через 3000 мс свежее ЗПТ ниже 30 В должно завершить попытку защитным сбросом. */ tick(1, 1, 29); /* Проверяет STOP, снятое разрешение и передачу базового тока 4 мА через калибровочный минимум. */ CHECK(load_state == LOAD_RELOAD && test_stop && !test_permission && modbus[0x1C] == 40 && modbus[123] == DAC_min()); /* После секунды STOP вторая попытка должна снова получить 6 мА и собственные три секунды ожидания. */ tick(1000, 1, 0); /* Исключает повторный START и немедленный STOP в одном вызове обработчика. */ CHECK(test_starts == 2 && test_start && !test_stop && modbus[0x1C] == 60); /* Проходит оставшиеся четыре попытки по реальному миллисекундному времени без ускорения рампы. */ for (attempt = 2; attempt <= 5; attempt++) { /* Даёт каждой попытке 3000 мс свежего нулевого ЗПТ после начальной отправки 6 мА. */ tick(3000, 1, 0); /* Проверяет возврат к 4 мА и полную выдержку каждой попытки до STOP. */ CHECK(test_stop && !test_permission && load_attempts == attempt && modbus[0x1C] == 40 && test_last_stop_tick - test_last_start_tick >= 3000); /* До пятой попытки соблюдает дополнительную секунду STOP, после пятой повтор запрещён. */ if (attempt < 5) tick(1000, 1, 0); /* Закрывает перебор разрешённых пусков. */ } /* Достаточное ЗПТ после ошибки само по себе не должно давать шестой пуск. */ tick(3000, 1, 30); /* Проверяет удержание ошибки, STOP и соблюдение порядка START/STOP/разрешения. */ CHECK(test_starts == 5 && (LOAD_STATUS & 1) && test_stop && !test_bad_order); /* Закрывает независимые проверки обоих адресов УМП. */ } /* Подаёт достаточное ЗПТ в последний такт выдержки: порог 30 В должен иметь приоритет перед истечением ожидания. */ setup(5); DAC_go = 6; Commands = 0x80; tick(3009, 1, 29); tick(1, 1, 30); /* Проверяет, что на границе 3000 мс от первого токового кадра не произошло ложного STOP или второго START. */ CHECK(load_state == LOAD_RUN && test_starts == 1 && !test_stop && test_permission); /* Даёт УМП 5 две секунды низкого ЗПТ при начальном токе 6 мА: первый токовый кадр отправляется на 10 мс. */ setup(5); DAC_go = 6; Commands = 0x80; tick(2010, 1, 29); /* Устройство должно продолжать ожидание на первой попытке без роста выше 6 мА. */ CHECK(load_attempts == 1 && modbus[0x1C] == 60 && !test_stop); /* Запоминает начальный код для проверки роста после прихода достаточного ЗПТ. */ code = modbus[123]; /* Ровно 30 В разрешают разгон; за 300 мс изменение видно даже при разрешении регистра 0,1 мА. */ tick(300, 1, 30); /* Проверяет продолжение первой попытки и рост отправленного токового задания. */ CHECK(test_starts == 1 && load_state == LOAD_RUN && modbus[0x1C] > 60 && (unsigned int)modbus[123] > code); /* После успешного роста падение до 29 В не получает дополнительную трёхсекундную выдержку. */ tick(5, 1, 29); CHECK(load_state == LOAD_RELOAD && test_stop && modbus[0x1C] == 40); /* Даже повышенная начальная уставка 9 мА должна ограничиваться 6 мА до подтверждения роста ЗПТ. */ setup(5); DAC_go = 9; Commands = 0x80; tick(10, 1, 0); /* Исключает преждевременную передачу повышенного начального задания при низком ЗПТ. */ CHECK(modbus[0x1C] == 60 && load_state == LOAD_RUN && test_starts == 1); /* После исчезновения CAN отправленное задание должно остаться 6 мА, даже если начальная уставка равна 9 мА. */ tick(1000, 0, 0); CHECK((LOAD_STATUS & 2) && modbus[0x1C] == 60); /* Короткий тайм-аут 20 мс позволяет проверить приостановку стартовой выдержки при потере выбранного CAN-напряжения. */ setup(5); DAC_go = 6; LOAD_CAN_TIMEOUT = 20; Commands = 0x80; tick(10, 1, 0); /* Дожидается устаревания последнего ЗПТ без новых кадров. */ tick(30, 0, 0); /* Сохраняет остаток стартовых отправок и последний код после перехода в паузу CAN. */ count = load_start_remaining; code = modbus[123]; /* Отсутствие CAN дольше всей выдержки не должно расходовать её остаток или следующую попытку. */ tick(4000, 0, 0); /* Проверяет удержание кода, счётчика ожидания, разрешения и первой попытки во время тайм-аута. */ CHECK((LOAD_STATUS & 2) && load_start_remaining == count && (unsigned int)modbus[123] == code && load_attempts == 1 && !test_stop); /* Свежее низкое ЗПТ возобновляет отсчёт от сохранённого значения. */ tick(5, 1, 29); CHECK(!(LOAD_STATUS & 2) && load_start_remaining == count - 1 && test_starts == 1); /* RESET должен прекратить ожидание сразу и отправить 4 мА на ближайшем токовом такте. */ Commands = 0xC0; tick(5, 1, 29); CHECK(test_stop && !test_permission && modbus[0x1C] == 40); /* Ручная калибровка вместе со START не должна подменять стартовое задание. */ setup(5); DAC_go = 6; Commands = 0x280; DAC_cal() = 4095; tick(6, 1, 0); /* Команда инициализации на первом токовом такте не подтверждает отправку 6 мА и не расходует выдержку. */ cInitDac = 1; tick(4, 1, 0); CHECK(load_start_remaining == 600 && modbus[0x1C] == 40); /* Следующий такт должен выдать настоящий начальный ток вместо ручного кода 4095. */ tick(5, 1, 0); CHECK(modbus[0x1C] == 60 && modbus[123] != 4095 && load_start_remaining == 599); /* Последний такт перед тремя секундами от токового кадра ещё сохраняет ожидание. */ tick(2999, 1, 0); CHECK(load_state == LOAD_RUN); /* Следующий такт завершает выдержку и возвращает 4 мА без подмены ручной калибровкой. */ tick(1, 1, 0); CHECK(load_state == LOAD_RELOAD && modbus[0x1C] == 40 && modbus[123] == DAC_min()); /* Возвращает успех после проверки реакции ЗПТ, пяти попыток, CAN, RESET и калибровки. */ return 0; /* Закрывает проверку стартового этапа нагрузки. */ } /* Проверяет настраиваемый лимит, независимость счётчика, уменьшение лимита в паузе STOP и верхнюю 16-битную границу. */ static int attempt_limit_test(void) { /* Адреса 5/6 выбирают оба УМП; limit задаёт общий предел START, attempt считает проверяемые неудачи. */ unsigned int mode, limit, attempt, out[8], error; /* Ноль из старой EEPROM должен превратиться в прежние заводские пять пусков. */ setup(5); CHECK(LOAD_MAX_ATTEMPTS == 5); /* Подготовка тактов ЦАП после загрузки параметров обязана сохранять ненулевую пользовательскую настройку. */ LOAD_MAX_ATTEMPTS = 7; Setup_DAC_time(); CHECK(LOAD_MAX_ATTEMPTS == 7); /* Проверяет одинаковый смысл лимита для ЗПТ1 и ЗПТ2, выбранных штатными CAN-адресами. */ for (mode = 5; mode <= 6; mode++) { /* Значения 1, 2 и 7 проверяют отсутствие дополнительных пусков и снятие прежнего жёсткого предела пяти. */ for (limit = 1; limit <= 7; limit = limit == 1 ? 2 : 7) { /* Новый сеанс начинает работу с указанным пределом; START включается только штатной командой. */ setup(mode); LOAD_MAX_ATTEMPTS = limit; Commands = 0x80; /* Каждая успешная реакция ЗПТ позволяет затем проверить немедленную защиту при его падении. */ for (attempt = 1; attempt <= limit; attempt++) { /* Даёт 1010 мс на первый пуск либо окончание секундного STOP перед очередным START. */ tick(1010, 1, 30); /* Переводит рампу выше границы 6 мА при достаточном ЗПТ, затем имитирует его падение до нуля. */ load_count_ramp = time_dac / 6; tick(5, 1, 30); tick(5, 1, 0); /* Проверяет число реальных START и неизменность записанного лимита после работы Timer1. */ CHECK(test_starts == attempt && load_attempts == attempt && LOAD_MAX_ATTEMPTS == (int)limit); /* До последней попытки допускается повтор; последняя неудача обязана зафиксировать LOAD_FAULT. */ CHECK(load_state == (attempt == limit ? LOAD_FAULT : LOAD_RELOAD)); /* Завершает проверку всех разрешённых попыток текущего сеанса. */ } /* Достаточное напряжение и повышение лимита сами по себе не снимают уже зафиксированную ошибку. */ LOAD_MAX_ATTEMPTS = limit + 1; tick(3000, 1, 30); /* Счётчик остаётся прежним, аппаратный STOP и запрет разрешения сохраняются после изменения настройки. */ CHECK(test_starts == limit && load_attempts == limit && test_stop && !test_permission); /* Диагностический блок версии 1 продолжает возвращать текущий счётчик в слове 5, независимо от лимита 0x7D. */ CHECK(Load_protection_prepare(3, 0x1300, 8, out, &error) == 8 && !error && out[5] == limit); /* Снятие START обнуляет счётчик, но сохраняет лимит для следующего сеанса пуска. */ Commands = 0; tick(1000, 1, 30); CHECK(!load_attempts && LOAD_MAX_ATTEMPTS == (int)(limit + 1)); /* Значение 7 — последний сценарий; выход исключает повторение итерации с неизменным limit. */ if (limit == 7) break; /* Завершает перебор проверяемых пользовательских лимитов. */ } /* Завершает проверку обоих адресов УМП. */ } /* Подготавливает первый неудачный пуск с разрешёнными пятью попытками. */ setup(5); Commands = 0x80; tick(1010, 1, 30); /* Падение уже подтверждённого ЗПТ переводит автомат в секундный STOP перед повтором. */ load_count_ramp = time_dac / 6; tick(5, 1, 0); CHECK(load_state == LOAD_RELOAD); /* Уменьшает предел до уже использованной одной попытки во время STOP, проверяя защиту перед следующим START. */ LOAD_MAX_ATTEMPTS = 1; tick(3000, 1, 30); CHECK(load_state == LOAD_FAULT && test_starts == 1); /* Верхняя граница регистра сохраняется после подготовки автомата и не трактуется как отрицательный лимит. */ setup(6); LOAD_MAX_ATTEMPTS = 65535U; Setup_DAC_time(); WAKEpowse = 0; /* Проверяет чтение максимального 16-битного значения без обнуления пользовательской настройки. */ CHECK((unsigned int)LOAD_MAX_ATTEMPTS == 65535U); /* Доводит первый пуск до защитной паузы, затем моделирует последнюю попытку без 65534 циклов ожидания. */ Commands = 0x80; tick(1010, 1, 30); load_count_ramp = time_dac / 6; tick(5, 1, 0); /* Значение 65534 соответствует числу ранее выданных START перед последней разрешённой попыткой. */ load_attempts = 65534U; tick(1000, 1, 30); CHECK(load_attempts == 65535U && test_starts == 2); /* Последняя неудача фиксирует ошибку до возможного переполнения 16-битного счётчика. */ load_count_ramp = time_dac / 6; tick(5, 1, 0); tick(3000, 1, 30); /* Проверяет удержание максимального счётчика, отсутствие дополнительного START и неизменность лимита. */ CHECK(load_state == LOAD_FAULT && load_attempts == 65535U && test_starts == 2 && (unsigned int)LOAD_MAX_ATTEMPTS == 65535U); /* Возвращает успех после проверки сохранения лимита и пограничных сценариев его применения. */ return 0; /* Завершает проверки настраиваемого количества попыток запуска. */ } /* Запускает новые стартовые сценарии и прежние регрессии автомата на программных подменах периферии. */ int main(void) { /* Объявляет out — данные out; error — ошибка; count — число; ramp — данные ramp; code — данные code. */ unsigned int out[8], error, count, ramp, code, stopped_at; /* Сначала проверяет исправляемый штатный пуск с 6 мА, затем выполняет остальные регрессии защиты. */ CHECK(startup_test() == 0); /* Дополнительно проверяет записываемый лимит 0x7D до прежних регрессий автомата нагрузки. */ CHECK(attempt_limit_test() == 0); /* Вызывает setup с аргументами (5) в текущей последовательности операций. */ setup(5); /* Boot ISR before parameters: no divide-by-zero and no GPIO start. */ /* Записывает Commands значением 0x80; tick(10, 1, 0); CHECK(!test_starts); слово команд, технологический регистр 127. */ Load_control_init(); Commands = 0x80; tick(10, 1, 0); CHECK(!test_starts); /* Записывает WAKEpowse значением 0; данные WAKEpowse. */ Setup_DAC_time(); WAKEpowse = 0; /* Вызывает tick с аргументами (10, 0, 0); CHECK(test_starts == 1 && test_permission) в текущей последовательности операций. */ tick(10, 0, 0); CHECK(test_starts == 1 && test_permission); /* Вызывает CHECK с аргументами (LOAD_CAN_TIMEOUT == 600) в текущей последовательности операций. */ CHECK(LOAD_CAN_TIMEOUT == 600); /* Wrong ZPT and masked slots never confirm freshness. */ /* Записывает Commands значением 0x80; слово команд, технологический регистр 127. */ setup(5); Commands = 0x80; /* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */ Load_voltage_can(0x8000U | 8U, 200, 0, 0); /* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */ Load_voltage_can(305U, 200, 0, 0); tick(10, 0, 0); /* Вызывает CHECK с аргументами (!test_starts && (LOAD_STATUS & 2)) в текущей последовательности операций. */ CHECK(!test_starts && (LOAD_STATUS & 2)); /* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */ Load_voltage_can(0x2000U | 303U, 0, 0, 30); /* Вызывает tick с аргументами (1, 0, 0); CHECK(test_starts == 1) в текущей последовательности операций. */ tick(1, 0, 0); CHECK(test_starts == 1); /* Freeze current and code at timeout; unrelated exchange cannot unfreeze. */ /* Вызывает tick с аргументами (1000, 1, 30); tick(600, 0, 0) в текущей последовательности операций. */ tick(1000, 1, 30); tick(600, 0, 0); /* Записывает ramp значением load_count_ramp; code = modbus[123]; данные ramp. */ ramp = load_count_ramp; code = modbus[123]; /* Вызывает tick с аргументами (2000, 0, 0); CHECK(load_count_ramp == ramp && (unsigned int)modbus[123] == code) в текущей последовательности операций. */ tick(2000, 0, 0); CHECK(load_count_ramp == ramp && (unsigned int)modbus[123] == code); /* Вызывает CHECK с аргументами (test_permission && !test_stop && (LOAD_STATUS & 2)) в текущей последовательности операций. */ CHECK(test_permission && !test_stop && (LOAD_STATUS & 2)); /* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */ Load_voltage_can(0x8000U | 8U, 200, 0, 0); tick(10, 0, 0); /* Вызывает CHECK с аргументами (load_count_ramp == ramp) в текущей последовательности операций. */ CHECK(load_count_ramp == ramp); /* Вызывает tick с аргументами (10, 1, 30); CHECK(load_count_ramp > ramp) в текущей последовательности операций. */ tick(10, 1, 30); CHECK(load_count_ramp > ramp); /* Exactly 30 V permits growth; 29 V fails strictly above 6 mA. */ /* Записывает Commands значением 0x80; tick(10, 1, 30); слово команд, технологический регистр 127. */ setup(6); Commands = 0x80; tick(10, 1, 30); /* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 30); load число ramp. */ load_count_ramp = time_dac / 6; tick(5, 1, 30); /* Вызывает CHECK с аргументами (load_state == LOAD_RUN && modbus[0x1C] >= 60) в текущей последовательности операций. */ CHECK(load_state == LOAD_RUN && modbus[0x1C] >= 60); /* Вызывает tick с аргументами (5, 1, 29); CHECK(load_state == LOAD_RELOAD && test_stop && !test_permission) в текущей последовательности операций. */ tick(5, 1, 29); CHECK(load_state == LOAD_RELOAD && test_stop && !test_permission); /* Вызывает CHECK с аргументами (!test_start && load_count_ramp == 0 && modbus[0x1C] == 40) в текущей последовательности операций. */ CHECK(!test_start && load_count_ramp == 0 && modbus[0x1C] == 40); /* Записывает stopped_at значением test_last_stop_tick; данные stopped_at. */ CHECK(modbus[123] == DAC_min()); stopped_at = test_last_stop_tick; /* Вызывает tick с аргументами (999, 1, 0); CHECK(test_starts == 1 && test_stop) в текущей последовательности операций. */ tick(999, 1, 0); CHECK(test_starts == 1 && test_stop); /* Вызывает tick с аргументами (1, 1, 0); CHECK(test_starts == 2 && test_last_start_tick-stopped_at == 1000) в текущей последовательности операций. */ tick(1, 1, 0); CHECK(test_starts == 2 && test_last_start_tick-stopped_at == 1000); /* Вызывает CHECK с аргументами (!test_stop && test_permission && !test_bad_order) в текущей последовательности операций. */ CHECK(!test_stop && test_permission && !test_bad_order); /* Five total attempts, then a persistent fault; no sixth start. */ /* Повторяет или ожидает, пока выполняется while (load_state != LOAD_FAULT). */ while (load_state != LOAD_FAULT) { /* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 0); load число ramp. */ load_count_ramp = time_dac / 6; tick(5, 1, 0); /* Проверяет if (load_state == LOAD_RELOAD) tick(1000, 1, 0); последующий оператор выполняется только при истинном условии. */ if (load_state == LOAD_RELOAD) tick(1000, 1, 0); /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Вызывает CHECK с аргументами (test_starts == 5 && load_attempts == 5 && (LOAD_STATUS & 1)) в текущей последовательности операций. */ CHECK(test_starts == 5 && load_attempts == 5 && (LOAD_STATUS & 1)); /* Вызывает tick с аргументами (3000, 1, 200); CHECK(test_starts == 5 && test_stop && !test_permission) в текущей последовательности операций. */ tick(3000, 1, 200); CHECK(test_starts == 5 && test_stop && !test_permission); /* Записывает Commands значением 0xC0; tick(10, 1, 200); CHECK(load_state == LOAD_FAULT); слово команд, технологический регистр 127. */ Commands = 0xC0; tick(10, 1, 200); CHECK(load_state == LOAD_FAULT); /* Записывает Commands значением 0; tick(1000, 1, 200); CHECK(!(LOAD_STATUS & 1)); слово команд, технологический регистр 127. */ Commands = 0; tick(1000, 1, 200); CHECK(!(LOAD_STATUS & 1)); /* Записывает Commands значением 0x80; test_starts = 0; tick(10, 1, 200); CHECK(load_attempts == 1); слово команд, технологический регистр 127. */ Commands = 0x80; test_starts = 0; tick(10, 1, 200); CHECK(load_attempts == 1); /* Manual reset dominates START; releasing it alone cannot start again. */ /* Записывает Commands значением 0xC0; tick(1, 1, 200); CHECK(test_stop && !test_permission); слово команд, технологический регистр 127. */ Commands = 0xC0; tick(1, 1, 200); CHECK(test_stop && !test_permission); /* Записывает Commands значением 0x80; tick(1500, 1, 200); CHECK(test_starts == 1); слово команд, технологический регистр 127. */ Commands = 0x80; tick(1500, 1, 200); CHECK(test_starts == 1); /* Versioned simulation writes are bounded, read-only fields reject writes. */ /* Записывает count значением Load_protection_prepare(3, 0x1300, 8, out, &error); число. */ count = Load_protection_prepare(3, 0x1300, 8, out, &error); /* Вызывает CHECK с аргументами (count == 8 && !error && out[0] == 0x5550 && out[1] == 1) в текущей последовательности операций. */ CHECK(count == 8 && !error && out[0] == 0x5550 && out[1] == 1); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1303, 0, out, &error); CHECK(error == 3); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1304, 0, out, &error); CHECK(error == 2); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1302, 4, out, &error); CHECK(error == 3); /* Записывает Commands значением 0x80; tick(10, 1, 200); слово команд, технологический регистр 127. */ setup(5); Commands = 0x80; tick(10, 1, 200); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1303, 20, out, &error); CHECK(!error); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1302, 1, out, &error); CHECK(!error); /* Вызывает tick с аргументами (30, 1, 200); CHECK(LOAD_STATUS & 2) в текущей последовательности операций. */ tick(30, 1, 200); CHECK(LOAD_STATUS & 2); /* Записывает ramp значением load_count_ramp; tick(100, 1, 200); CHECK(load_count_ramp == ramp); данные ramp. */ ramp = load_count_ramp; tick(100, 1, 200); CHECK(load_count_ramp == ramp); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1302, 0, out, &error); /* Вызывает tick с аргументами (10, 1, 200); CHECK(!(LOAD_STATUS & 2) && load_count_ramp > ramp) в текущей последовательности операций. */ tick(10, 1, 200); CHECK(!(LOAD_STATUS & 2) && load_count_ramp > ramp); /* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */ Load_protection_prepare(6, 0x1302, 2, out, &error); /* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 200); CHECK(load_state == LOAD_RELOAD); load число ramp. */ load_count_ramp = time_dac / 6; tick(5, 1, 200); CHECK(load_state == LOAD_RELOAD); /* Calibration must not replace the forced 4 mA output during reload. */ /* Устанавливает биты Commands значением 0x200; DAC_cal() = 4095; tick(5, 1, 200); слово команд, технологический регистр 127. */ Commands |= 0x200; DAC_cal() = 4095; tick(5, 1, 200); /* Вызывает CHECK с аргументами (modbus[123] == DAC_min() && modbus[0x1C] == 40) в текущей последовательности операций. */ CHECK(modbus[123] == DAC_min() && modbus[0x1C] == 40); /* A calibration code preceding START must be replaced by 4 mA first. */ /* Записывает Commands значением 0x200; DAC_cal() = 4095; слово команд, технологический регистр 127. */ setup(5); Commands = 0x200; DAC_cal() = 4095; /* Вызывает tick с аргументами (10, 1, 200); CHECK(modbus[123] == 4095 && !load_zero_sent) в текущей последовательности операций. */ tick(10, 1, 200); CHECK(modbus[123] == 4095 && !load_zero_sent); /* Записывает Commands значением 0x280; tick(1, 1, 200); CHECK(!test_starts); слово команд, технологический регистр 127. */ Commands = 0x280; tick(1, 1, 200); CHECK(!test_starts); /* Вызывает tick с аргументами (4, 1, 200); CHECK(!test_starts && modbus[123] == DAC_min()) в текущей последовательности операций. */ tick(4, 1, 200); CHECK(!test_starts && modbus[123] == DAC_min()); /* Вызывает tick с аргументами (1, 1, 200); CHECK(test_starts == 1) в текущей последовательности операций. */ tick(1, 1, 200); CHECK(test_starts == 1); /* Timeout while STOP is held cannot initiate the pending retry. */ /* Начинает пуск с заводскими 6 мА и свежим нулевым ЗПТ, чтобы затем проверить исчезновение CAN во время STOP. */ setup(5); DAC_go = 6; Commands = 0x80; tick(10, 1, 0); /* Даёт три секунды на реакцию ЗПТ после первой отправки 6 мА, затем проверяет потерю CAN во время защитного сброса. */ tick(3000, 1, 0); /* Вызывает CHECK с аргументами (load_state == LOAD_RELOAD) в текущей последовательности операций. */ CHECK(load_state == LOAD_RELOAD); /* Вызывает tick с аргументами (1500, 0, 0); CHECK(test_starts == 1 && test_stop) в текущей последовательности операций. */ tick(1500, 0, 0); CHECK(test_starts == 1 && test_stop); /* Вызывает tick с аргументами (1, 1, 0); CHECK(test_starts == 2 && !test_stop) в текущей последовательности операций. */ tick(1, 1, 0); CHECK(test_starts == 2 && !test_stop); /* Вызывает Load_control_init. Сбрасывает все переменные автомата нагрузки до разрешения прерываний; COFF не обнуляет всю .ebss. */ Load_control_init(); CHECK(!load_simulation); /* Сообщает об успехе проверки реального автомата, включая новый старт 6 мА с выдержкой 3 секунды и прежние защитные сценарии. */ /* Сообщает о проверке рабочих исходников, настраиваемого лимита и прежних режимов защиты нагрузки. */ puts("PASS: production DAC control, startup, timeout, CAN, STOP ordering, writable attempt limit, simulation"); /* Завершает main и возвращает 0. */ return 0; /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ }