Исправить TESTLAMP, запуск CAN и расчёт фазных токов

Сохранить состояние TESTLAMP при кратких провалах входа и исключить повторный вход Timer1 во время передачи индикации.
Явно сбрасывать служебный обмен CAN при запуске и выбирать соседнюю фазу по локальному индексу канала АЦП.
Сохранить текущую последовательность DATA/CLK и проверочные варианты таймингов, добавить поведенческие тесты и обновить образ прошивки с картой памяти.
This commit is contained in:
2026-10-13 14:13:43 +03:00
parent fa20ed085b
commit 04a9d989fb
18 changed files with 1983 additions and 655 deletions

View File

@@ -75,6 +75,31 @@ static unsigned int ump_can_waiting;
/* Объявляет ump_can_sent_at — время последней передачи фрагмента ответа CAN. */
static unsigned long ump_can_sent_at;
/* Сбрасывает служебный обмен до включения CAN: загрузка COFF не гарантирует обнуление неинициализированной RAM. */
static void ump_can_init(void)
/* Начинает сброс состояния; InitCan вызывается при запрещённых глобальных прерываниях. */
{
/* Убирает остаточный запрос, чтобы главный цикл не обрабатывал команду из RAM предыдущего запуска. */
ump_can_pending = 0;
/* Сбрасывает идентификатор и функцию запроса; действительные значения поступят из CANa_handler. */
ump_can_tag = 0;
/* Сбрасывает адрес запрошенного регистра до приёма новой команды. */
ump_can_address = 0;
/* Сбрасывает прежнее значение записи или число запрошенных слов. */
ump_can_value = 0;
/* Нулевая длина запрещает отправку старого буфера; новый запрос заполнит все доступные для передачи слова. */
ump_can_length = 0;
/* Начинает следующий подготовленный ответ с первого слова, исключая продолжение старого фрагмента. */
ump_can_index = 0;
/* Убирает прежний идентификатор ответа и код ошибки до подготовки новой команды. */
ump_can_reply_tag = 0;
/* Отменяет ожидание подтверждения старой передачи, которая после включения ещё не запускалась. */
ump_can_waiting = 0;
/* Сбрасывает отметку тайм-аута в тактах Timer1; новый фрагмент установит актуальное время отправки. */
ump_can_sent_at = 0;
/* Завершает сброс управляющих полей; содержимое буфера недоступно при нулевой длине ответа. */
}
/* Настраивает eCAN, скорость, почтовые ящики и маршрутизацию прерываний для выбранного режима платы. */
void InitCan(int Port, int DevNum)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
@@ -92,6 +117,9 @@ void InitCan(int Port, int DevNum)
/* Объявляет id — данные id. Начальное значение задаётся справа от знака равенства. */
long id = 0x80BA0000;
/* Обнуляет состояние служебного обмена до настройки mailbox и разрешения прерываний CAN. */
ump_can_init();
/* Изменяет счётчик в выражении DevNum--; на один для следующего шага. */
DevNum--;
/* Проверяет if(DevNum<0)DevNum=0; последующий оператор выполняется только при истинном условии. */

View File

@@ -148,7 +148,7 @@ void RESET()
void SENDBIT(int x)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Выставляет передаваемый бит DATA до подъёма CLOCK, чтобы данные присутствовали на линии на протяжении импульса такта. */
/* Вызывает DOUT с аргументами (x); DCLK(1) в текущей последовательности операций. */
DOUT(x); DCLK(1);
/* Условие компиляции POWS0>0: выбранный блок включается в текущий вариант прошивки. */
#if POWS0>0
@@ -156,12 +156,12 @@ void SENDBIT(int x)
DSP28x_usDelay(POWS0);
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif
/* Удерживает CLOCK высоким при действительном DATA; POWS0+1 сохраняет прежний аргумент цикловой задержки TI из SENDBIT, а не задаёт число микросекунд. */
DSP28x_usDelay(POWS0+1);
/* Сначала опускает CLOCK при ещё действительном DATA; восстанавливает прежний порядок пользователя и сохраняет бит для приёмника, считывающего по спаду. */
DCLK(0);
/* Сбрасывает DATA только после спада CLOCK, чтобы завершающий фронт такта не считывал принудительный ноль вместо единичного бита. */
/* Вызывает DOUT с аргументами (0) в текущей последовательности операций. */
DOUT(0);
/* Вызывает DSP28x_usDelay с аргументами (POWS0+1) в текущей последовательности операций. */
DSP28x_usDelay(POWS0+1);
/* Вызывает DCLK с аргументами (0) в текущей последовательности операций. */
DCLK(0);
/* Условие компиляции POWS1>0: выбранный блок включается в текущий вариант прошивки. */
#if POWS1>0
/* Вызывает DSP28x_usDelay с аргументами (POWS1) в текущей последовательности операций. */

View File

@@ -829,8 +829,8 @@ void Current_count(int chan)
/* Записывает sens значением pow_addr + chan; данные sens. */
sens = pow_addr + chan;
/* Записывает pair значением sens_pair[chan]; данные pair. */
pair = sens_pair[chan];
/* Младший бит локального канала АЦП выбирает соседнюю фазу (0 <-> 1, 2 <-> 3); sens_pair хранит глобальные номера датчиков со смещением pow_addr и не подходит для индексации lev_count. */
pair = chan ^ 1;
/* Записывает ist значением !(chan & 1); данные ist. */
ist = !(chan & 1);
/* Записывает feed значением (chan >>1); данные feed. */

View File

@@ -405,8 +405,8 @@ void get_Buttons()
if(Desk==dsk_EPLT)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает bTestLamp значением er_anal(GpioDataRegs.GPADAT.bit.GPIO26, &INcount0, 1000, 0); данные bTestLamp. */
bTestLamp = er_anal(GpioDataRegs.GPADAT.bit.GPIO26, &INcount0, 1000, 0);
/* Сохраняет предыдущее состояние TESTLAMP, пока накопитель INcount0 не достигнет одного из порогов; 1000 — число опросов главного цикла, а не миллисекунды. Краткий провал GPIO26 больше не переключает передачу с тестовых масок на рабочие. */
bTestLamp = er_anal(GpioDataRegs.GPADAT.bit.GPIO26, &INcount0, 1000, bTestLamp);
/* Проверяет if(GpioDataRegs.GPADAT.bit.GPIO27) butt +=0x0001; последующий оператор выполняется только при истинном условии. */
if(GpioDataRegs.GPADAT.bit.GPIO27) butt +=0x0001;

View File

@@ -75,8 +75,8 @@ interrupt void cpu_timer1_isr_PULT(void)
EALLOW;
/* Изменяет счётчик в выражении CpuTimer1.InterruptCount++; на один для следующего шага. */
CpuTimer1.InterruptCount++;
/* Устанавливает биты IER значением MINT13; регистр разрешения прерываний ядра C28x. */
IER |= MINT13; // Set "global" priority
/* Оставляет только ранее разрешённые источники более высокого приоритета по маске TI MINT13 и запрещает повторный Timer1 через M_INT13 (бит 12 IER); вложенная передача не должна перемешивать фронты DATA/CLK и менять фазу яркости. IRET восстановит маску вызывающего кода. */
IER &= (MINT13 & ~M_INT13);
/* Разрешение маскируемых прерываний ядра. */
EINT;
/* Закрытие доступа к защищённым регистрам периферии. */