Files
Balsam_167/Source/Internal/main.c
Andrey 3ebfdca0a0 Исправить скорость SCI и добавить диагностику ошибок приёма RS232
Округлить делитель SCI по формуле аппаратуры, настроить вход RX и обработку ошибок FIFO. Добавить диагностические поля и проверки модели, установить 9600 бод для RS485 при Owen. Сохранить скрипт сборки, обновлённый образ прошивки и карту линковки.
2026-10-12 16:44:51 +03:00

385 lines
29 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Порядок запуска периферии и обслуживание команд в главном цикле. Русские пояснения сохранены в UTF-8. */
/* Подключает "DSP2833x_Device.h": поставляемое TI описание Device для семейства C2833x. */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
/* Подключает "cntrl_adr.h": собственный и универсальный адрес устройства. */
#include "cntrl_adr.h"
/* Подключает "RS485.h": приём и передача SCI-A/SCI-B, упаковка команд и FIFO первого порта. */
#include "RS485.h"
/* Подключает "BIOS_DSP.h": настройки и интерфейс BIOS_DSP. */
#include "BIOS_DSP.h"
/* Подключает "Message.h": настройки и интерфейс Message. */
#include "Message.h"
/* Подключает "filter_bat2.h": накопительный фильтр измерительных каналов. */
#include "filter_bat2.h"
/* Подключает "measure.h": обработка датчиков, вычисление величин и миллисекундный такт системы. */
#include "measure.h"
/* Подключает "package.h": адреса устройств, типы плат и псевдонимы технологических регистров. */
#include "package.h"
/* Подключает "spise2p.h": драйвер SPI EEPROM, адресация, страницы и автомат завершения операций. */
#include "spise2p.h"
/* Подключает "tools.h": настройка внешней памяти и служебные задержки. */
#include "tools.h"
/* Подключает "peripher.h": перемычки режима платы, дискретные входы и выходы. */
#include "peripher.h"
/* Подключает "ADC.h": настройка АЦП, обработка преобразований и первичная фильтрация измерений. */
#include "ADC.h"
/* Подключает "DAC.h": выход ЦАП и автомат защиты нагрузки с проверкой напряжения и свежести CAN. */
#include "DAC.h"
/* Подключает "ecan.h": штатный eCAN и отдельный служебный обмен УМП/GAS. */
#include "ecan.h"
/* Подключает "kanal.h": последовательный вывод данных канала индикации. */
#include "kanal.h"
/* Подключает "pulto.h": обмен и индикация пульта. */
#include "pulto.h"
/* Подключает "log_to_mem.h": двухбанковый регистратор событий нагрузки во внешней RAM. */
#include "log_to_mem.h"
/* Подключает "measure.h": обработка датчиков, вычисление величин и миллисекундный такт системы. */
#include "measure.h"
/* Объявляет интерфейс функции DSP28x_usDelay; реализация вызывается через этот прототип. */
extern void DSP28x_usDelay(Uint32 Count);
/* Назначает обработчик Timer1 по типу платы и задаёт период основного такта. */
void timer_Init()
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Разрешение записи в защищённые регистры периферии. */
EALLOW; // This is needed to write to EALLOW protected registers
/* Проверяет if(Desk==dsk_EPLT) PieVectTable.XINT13 = &cpu_timer1_isr_PULT; последующий оператор выполняется только при истинном условии. */
if(Desk==dsk_EPLT) PieVectTable.XINT13 = &cpu_timer1_isr_PULT;
/* Выполняет альтернативу, если предыдущее условие if оказалось ложным. */
else PieVectTable.XINT13 = &cpu_timer1_isr_SENS;
/* Закрытие доступа к защищённым регистрам периферии. */
EDIS; // This is needed to disable write to EALLOW protected registers
/* Вызывает ConfigCpuTimer с аргументами (&CpuTimer1, SYSCLKOUT/1000000, 1000000/READY_FREQ) в текущей последовательности операций. */
ConfigCpuTimer(&CpuTimer1, SYSCLKOUT/1000000, 1000000/READY_FREQ);
/* Записывает CpuTimer1Regs.TCR.all значением 0x4020; представление регистра целым словом без разбиения на битовые поля. */
CpuTimer1Regs.TCR.all = 0x4020; // Use write-only instruction to set TSS bit = 0
/* Устанавливает биты IER значением M_INT13; регистр разрешения прерываний ядра C28x. */
IER |= M_INT13;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
void main()
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Объявляет i — данные i; j — данные j; mask — маска. */
int i,j,mask;
/* Объявляет cancount — данные cancount; cancell — данные cancell; rscount — данные rscount. */
static unsigned int cancount[2], cancell[2], rscount;
/* Объявляет rs — данные rs. Хранит указатель на данные. */
RS_DATA * rs;
/* Объявляет presbyt — данные presbyt. Начальное значение задаётся справа от знака равенства. */
int presbyt=0;
/* Инициализирует модуль вызовом InitSysCtrl(); перед его дальнейшим использованием. */
InitSysCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
/* Запрет маскируемых прерываний ядра. */
DINT;
/* Инициализирует модуль вызовом InitPieCtrl(); перед его дальнейшим использованием. */
InitPieCtrl();
/* Записывает IER значением 0x0000; регистр разрешения прерываний ядра C28x. */
IER = 0x0000;
/* Записывает IFR значением 0x0000; регистр ожидающих прерываний ядра C28x. */
IFR = 0x0000;
/* Инициализирует модуль вызовом InitPieVectTable(); перед его дальнейшим использованием. */
InitPieVectTable();
/* Вызывает init_zone7. Настраивает временные параметры внешней шины XINTF Zone7 для RAM регистратора. */
init_zone7();
/* Вызывает get_Mode. Определяет адрес и тип платы по аппаратным перемычкам и задаёт рабочий режим. */
get_Mode();
/* Вызывает InitCan. Настраивает eCAN, скорость, почтовые ящики и маршрутизацию прерываний для выбранного режима платы. */
InitCan(0,Mode);
/* Вызывает create_uart_vars. Инициализирует структуры обоих SCI и таблицу длин команд. */
create_uart_vars(sizeof(CMD_TO_TMS));
/* Вызывает setup_uart. Настраивает выбранный SCI, скорость и обработчики прерываний. */
setup_uart(COM_1,115200);
/* Проверяет if(Owen)setup_uart(COM_2,57600); последующий оператор выполняется только при истинном условии. */
if(Owen)setup_uart(COM_2,9600);
/* Выполняет альтернативу, если предыдущее условие if оказалось ложным. */
else setup_uart(COM_2,115200);
/* Инициализирует модуль вызовом InitSeeprom(); перед его дальнейшим использованием. */
InitSeeprom();
/* Вызывает setup_leds_line с аргументами () в текущей последовательности операций. */
setup_leds_line();
/* Вызывает led1_on с аргументами () в текущей последовательности операций. */
led1_on();
/* Вызывает led2_off с аргументами () в текущей последовательности операций. */
led2_off();
/* Цикл for (i=0;i<10;i++); задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0;i<10;i++)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Вызывает pause_us. Формирует задержку в микросекундах через калиброванную функцию DSP28x_usDelay. */
pause_us(50000);
/* Вызывает led2_toggle с аргументами () в текущей последовательности операций. */
led2_toggle();
/* Вызывает led1_toggle с аргументами () в текущей последовательности операций. */
led1_toggle();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает led1_off с аргументами () в текущей последовательности операций. */
led1_off();
/* Вызывает led2_off с аргументами () в текущей последовательности операций. */
led2_off();
/* Вызывает unsetup_leds_line с аргументами () в текущей последовательности операций. */
unsetup_leds_line();
/* Вызывает clear_mem. Обнуляет выделенный диапазон внешней RAM журнала и задаёт границы кольцевого буфера. */
clear_mem();
/* Вызывает ump_log_init. Явно инициализирует оба банка регистратора до включения IRQ; повторный старт записи архив не стирает. */
ump_log_init();
Load_control_init(); /* Explicit initialization before IRQ. */ /* Вызывает Load_control_init. Сбрасывает все переменные автомата нагрузки до разрешения прерываний; COFF не обнуляет всю .ebss. */
/* Вызывает set_cntrl_addr. Устанавливает собственный и универсальный адрес для проверки адресованных команд. */
set_cntrl_addr(Mode,16);
/* Вызывает timer_Init. Назначает обработчик Timer1 по типу платы и задаёт период основного такта. */
timer_Init();
/* Вызывает EnableInterrupts с аргументами () в текущей последовательности операций. */
EnableInterrupts();
/* Проверяет if(Desk!=dsk_EPLT); последующий оператор выполняется только при истинном условии. */
if(Desk!=dsk_EPLT)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Вызывает setup_adc. Настраивает каналы, последовательность преобразований и запуск АЦП. */
setup_adc();
/* Инициализирует модуль вызовом Init_sensors(); перед его дальнейшим использованием. */
Init_sensors();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Инициализирует модуль вызовом Init_packMask(); перед его дальнейшим использованием. */
Init_packMask();
/* Вызывает Load_params. Читает сохранённые регистры из области параметров EEPROM и применяет настройки платы. */
Load_params();
/* Инициализирует модуль вызовом Init_sensors_more(); перед его дальнейшим использованием. */
Init_sensors_more();
/* Проверяет if(Desk==dsk_LOAD); последующий оператор выполняется только при истинном условии. */
if(Desk==dsk_LOAD)
/* Вызывает Setup_DAC_time. Вычисляет такты ЦАП; для недопустимого сохранённого тайм-аута CAN возвращает 600 мс. */
Setup_DAC_time();
/* Записывает LastMode значением Mode; последний режим платы, технологический регистр 126. */
LastMode = Mode;
/* Разрешение записи в защищённые регистры периферии. */
EALLOW;
/* Записывает SysCtrlRegs.WDCR значением 0x2F; данные WDCR. */
SysCtrlRegs.WDCR= 0x2F;
/* Закрытие доступа к защищённым регистрам периферии. */
EDIS;
/* Записывает READY значением 1; данные READY. */
READY=1;
/* Повторяет или ожидает, пока выполняется while(1). */
while(1)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Чтение логгера по CAN не блокирует цикл управления. */
/* Вызывает UMP_CAN_service. В главном цикле готовит замороженный ответ служебного CAN и отправляет его двухсловными фрагментами. */
UMP_CAN_service();
/* Проверяет if(CanGO); последующий оператор выполняется только при истинном условии. */
if(CanGO)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает CanGO значением 0; CAN GO. */
CanGO=0;
/* Проверяет if(Owncount); последующий оператор выполняется только при истинном условии. */
if(Owncount)
/* Проверяет if(++rscount>=Owncount); последующий оператор выполняется только при истинном условии. */
if(++rscount>=Owncount)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает rscount значением 0; данные rscount. */
rscount=0;
/* Вызывает SendCommandModbus4 с аргументами (&rs_b) в текущей последовательности операций. */
SendCommandModbus4(&rs_b);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Цикл for(i=0;i<2;i++); задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<2;i++)
/* Проверяет if(++cancount[i] >= Cancount[i]); последующий оператор выполняется только при истинном условии. */
if(++cancount[i] >= Cancount[i])
/* Проверяет if(Cancount[i] и cancount[0]); последующий оператор выполняется только при истинном условии. */
if(Cancount[i] && cancount[0])
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает cancount[i] значением 0; данные cancount. */
cancount[i] = 0;
/* Повторяет или ожидает, пока выполняется while(1). */
while(1)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Проверяет if(cancell[i] >= 0x80) cancell[i]=0; последующий оператор выполняется только при истинном условии. */
if(cancell[i] >= 0x80) cancell[i]=0;
/* Записывает mask значением Maska[i][cancell[i]/16] >> (cancell[i]%16); маска. */
mask = Maska[i][cancell[i]/16] >> (cancell[i]%16);
/* Проверяет if(!mask) cancell[i] = (cancell[i] + 0x10) & 0xFFF0; последующий оператор выполняется только при истинном условии. */
if(!mask) cancell[i] = (cancell[i] + 0x10) & 0xFFF0;
/* Выполняет альтернативу, если предыдущее условие if оказалось ложным. */
else
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Повторяет или ожидает, пока выполняется while(!(mask & 1)). */
while(!(mask & 1))
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Изменяет счётчик в выражении cancell[i]++; mask >>= 1; на один для следующего шага. */
cancell[i]++; mask >>= 1;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Прерывает ближайший цикл или ветвь switch и продолжает после него. */
break;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
} }
/* Вызывает CAN_send. Упаковывает адрес и технологические слова в штатный CAN-кадр и запускает передачу mailbox. */
CAN_send(0,modbus,cancell[i]);
/* Увеличивает cancell[i] значением 3; данные cancell. */
cancell[i]+=3;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
} }
/* Проверяет if(cDefParam); последующий оператор выполняется только при истинном условии. */
if(cDefParam)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает cDefParam значением 0; данные cDefParam. */
cDefParam=0;
/* По команде восстановления записывает заводские параметры; для LOAD тайм-аут свежести CAN становится 2000 мс. */
Default_params();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Проверяет if(cSaveParam); последующий оператор выполняется только при истинном условии. */
if(cSaveParam)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает cSaveParam значением 0; данные cSaveParam. */
cSaveParam=0;
/* Вызывает Save_params. Сохраняет технологические регистры в область параметров, отделённую от загрузочного образа EEPROM. */
Save_params();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Проверяет if(cLoadParam); последующий оператор выполняется только при истинном условии. */
if(cLoadParam)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает cLoadParam значением 0; данные cLoadParam. */
cLoadParam=0;
/* Вызывает Load_params. Читает сохранённые регистры из области параметров EEPROM и применяет настройки платы. */
Load_params();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Проверяет if(cKoefCalc); последующий оператор выполняется только при истинном условии. */
if(cKoefCalc)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает cKoefCalc значением 0; данные cKoefCalc. */
cKoefCalc=0;
/* Вызывает calc_sensor_koef с аргументами () в текущей последовательности операций. */
calc_sensor_koef();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает get_Buttons. Считывает кнопки, обновляет флаги команд и учитывает текущий тип платы. */
get_Buttons();
/* Проверяет if(Desk==dsk_COMM); последующий оператор выполняется только при истинном условии. */
if(Desk==dsk_COMM)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Проверяет if(!bTermoCal & presbyt) cSaveParam=1; последующий оператор выполняется только при истинном условии. */
if(!bTermoCal & presbyt) cSaveParam=1;
/* Записывает presbyt значением bTermoCal; данные presbyt. */
presbyt = bTermoCal;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Timer1 owns START/STOP/permission and the DAC ramp together.
* Main must not re-enable the output during a protected reload. */
/* Снимок после обновления входов и формирования пусковых выходов. */
/* Вызывает ump_log_io. Обслуживает изменения дискретных входов и выходов из главного цикла. */
ump_log_io();
/* Цикл for(i=0;i<2;i++); задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<2;i++)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Проверяет if(i) rs = &rs_a; последующий оператор выполняется только при истинном условии. */
if(i) rs = &rs_a;
/* Выполняет альтернативу, если предыдущее условие if оказалось ложным. */
else rs = &rs_b;
/* Записывает j значением get_command(rs); данные j. */
j = get_command(rs);
/* Проверяет if(j!=-1); последующий оператор выполняется только при истинном условии. */
if(j!=-1)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает Lonely значением 0; данные Lonely. */
Lonely=0;
/* Вызывает led2_toggle с аргументами () в текущей последовательности операций. */
led2_toggle();
/* Вызывает switch с аргументами (j) в текущей последовательности операций. */
switch(j)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Ветвь выбора для CMD_INIT; выполняется при совпадении селектора switch. */
case CMD_INIT: init(rs); break; // начальные установки
/* Ветвь выбора для CMD_INITLOAD; выполняется при совпадении селектора switch. */
case CMD_INITLOAD: initload(rs); break; // настройка загрузки
/* Ветвь выбора для CMD_RUN; выполняется при совпадении селектора switch. */
case CMD_RUN: run(rs); break; // загрузить блок
/* Ветвь выбора для CMD_LOAD; выполняется при совпадении селектора switch. */
case CMD_LOAD: load(rs); break; // загрузить блок
/* Ветвь выбора для CMD_PEEK; выполняется при совпадении селектора switch. */
case CMD_PEEK: peek(rs); break; // прочитать ачейку памати
/* Ветвь выбора для CMD_POKE; выполняется при совпадении селектора switch. */
case CMD_POKE: poke(rs); break; // записать в ачейку памати
/* Ветвь выбора для CMD_UPLOAD; выполняется при совпадении селектора switch. */
case CMD_UPLOAD: upload(rs); break; // передать блок памати
/* Ветвь выбора для CMD_EXTEND; выполняется при совпадении селектора switch. */
case CMD_EXTEND: extendbios(rs); break; // расширенные команды дла биоса
/* Ветвь выбора для CMD_TFLASH; выполняется при совпадении селектора switch. */
case CMD_TFLASH: tflash(rs); break; // прошить TMS
/* Ветвь выбора для CMD_MODBUS_3; выполняется при совпадении селектора switch. */
case CMD_MODBUS_3: ReceiveCommandModbus3(rs); break;
/* Ветвь выбора для CMD_MODBUS_6; выполняется при совпадении селектора switch. */
case CMD_MODBUS_6: ReceiveCommandModbus6(rs); break;
/* Ветвь выбора для ANS_MODBUS_4; выполняется при совпадении селектора switch. */
case ANS_MODBUS_4: ReceiveAnswerModbus4(rs); break;
/* Обрабатывает значения селектора, для которых нет отдельной ветви case. */
default: break;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
} } } } }