118 lines
21 KiB
HTML
118 lines
21 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="description" content="Архитектура и API прошивки периферийного контроллера Balsam 167 на TMS320F28335.">
|
||
<title>Balsam 167 · Документация прошивки</title>
|
||
<style>
|
||
:root{color-scheme:dark;--bg:#07111f;--panel:#0d1b2c;--panel2:#12243a;--line:#263b54;--text:#e8f0f8;--muted:#9eb0c4;--mint:#55d6be;--blue:#8bc5ff;--amber:#fbbf24;--red:#ff8278;--code:#071521;--radius:16px}
|
||
*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;min-height:100vh;color:var(--text);background:radial-gradient(circle at 85% 0,#143354 0,transparent 31rem),var(--bg);font:15px/1.65 Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}a{color:var(--blue);text-decoration:none}a:hover{text-decoration:underline}code,pre{font-family:Consolas,"Courier New",monospace}:not(pre)>code{padding:2px 6px;border-radius:5px;color:#c4f8ec;background:#15283a}.wrap{width:min(1180px,calc(100% - 32px));margin:auto}header{padding:58px 0 32px}.eyebrow{color:var(--mint);font:800 12px/1.2 Consolas,monospace;letter-spacing:.14em;text-transform:uppercase}h1{max-width:900px;margin:12px 0;font-size:clamp(38px,7vw,72px);line-height:1;letter-spacing:-.05em}h2{margin:0 0 8px;font-size:clamp(27px,4vw,38px);letter-spacing:-.03em}h3{margin:0 0 8px;font-size:19px}.lead,.intro,.card p,.card li{color:var(--muted)}.lead{max-width:850px;font-size:18px}.stats{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}.stat{padding:8px 12px;border:1px solid var(--line);border-radius:999px;background:#0d1b2ccc;color:var(--muted);font-size:13px}.stat b{color:var(--text)}.tabbar{position:sticky;top:0;z-index:10;border-block:1px solid var(--line);background:#07111fe8;backdrop-filter:blur(14px)}.tabs{display:flex;gap:6px;padding:10px 0;overflow-x:auto}.tab{border:0;border-radius:9px;padding:10px 15px;color:var(--muted);background:transparent;font:inherit;font-weight:700;white-space:nowrap;cursor:pointer}.tab:hover{color:var(--text);background:var(--panel)}.tab[aria-selected=true]{color:#07111f;background:var(--mint)}main{padding:34px 0 70px}.pane[hidden]{display:none}.intro{max-width:820px;margin:0 0 24px}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px}.card{grid-column:span 4;min-width:0;padding:21px;border:1px solid var(--line);border-radius:var(--radius);background:linear-gradient(145deg,#12243af0,#0d1b2ceb);box-shadow:0 18px 55px #0003}.card.half{grid-column:span 6}.card.wide{grid-column:span 8}.card.full{grid-column:1/-1}.tag{display:inline-block;margin-bottom:13px;padding:3px 8px;border-radius:6px;color:var(--mint);background:#153d39;font:700 11px/1.5 Consolas,monospace;text-transform:uppercase}.tag.blue{color:var(--blue);background:#15334a}.tag.amber{color:#ffda84;background:#3a2d16}.tag.red{color:#ffaaa3;background:#3b211f}.flow{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin:20px 0}.step{padding:16px;border:1px solid var(--line);border-radius:12px;background:var(--panel)}.step b{display:block;color:var(--mint);font-size:13px}.step span{color:var(--muted);font-size:13px}.filetree,pre{overflow:auto;margin:14px 0 0;padding:17px;border:1px solid var(--line);border-radius:12px;background:var(--code);color:#d6e5f3;font:13px/1.65 Consolas,monospace;white-space:pre}.table-scroll{overflow-x:auto}table{width:100%;min-width:760px;border-collapse:collapse}th,td{padding:11px 13px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}th{color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.06em}td:first-child{color:var(--mint);font-family:Consolas,monospace}.callout{margin-top:16px;padding:15px 17px;border-left:3px solid var(--amber);border-radius:4px 12px 12px 4px;color:#dfd2b4;background:#251f14}.links{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}.button{display:inline-flex;align-items:center;padding:10px 14px;border:1px solid #39708a;border-radius:10px;color:var(--text);background:#123047}.button.primary{border-color:var(--mint);color:#061511;background:var(--mint);font-weight:800}.check{list-style:none;padding:0}.check li{position:relative;padding-left:26px}.check li:before{content:'✓';position:absolute;left:0;color:var(--mint);font-weight:900}footer{padding:24px 0 42px;border-top:1px solid var(--line);color:var(--muted);font-size:13px}@media(max-width:900px){.card,.card.half,.card.wide{grid-column:1/-1}.flow{grid-template-columns:1fr 1fr}}@media(max-width:540px){.wrap{width:min(100% - 20px,1180px)}header{padding-top:36px}.flow{grid-template-columns:1fr}}
|
||
</style>
|
||
<style>
|
||
.analysis-layout{display:grid;grid-template-columns:310px minmax(0,1fr);gap:14px;align-items:start}.analysis-nav{display:grid;gap:9px}.analysis-link{display:block;padding:13px 14px;border:1px solid var(--line);border-radius:11px;color:var(--text);background:var(--panel);font-weight:700}.analysis-link:hover,.analysis-link.active{border-color:var(--mint);color:var(--mint);text-decoration:none;background:#12302f}.analysis-link small{display:block;margin-top:3px;color:var(--muted);font-weight:400}.analysis-frame{width:100%;height:72vh;min-height:620px;border:1px solid var(--line);border-radius:14px;background:#fff}@media(max-width:850px){.analysis-layout{grid-template-columns:1fr}.analysis-nav{grid-template-columns:1fr 1fr}.analysis-frame{height:68vh;min-height:520px}}@media(max-width:540px){.analysis-nav{grid-template-columns:1fr}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header class="wrap">
|
||
<div class="eyebrow">TMS320F28335 · C2000 · Balsam 167</div>
|
||
<h1>Периферийный контроллер<br>карта прошивки</h1>
|
||
<p class="lead">Архитектура измерений, диагностики и обмена для многоролевого контроллера Balsam 167. Страница служит точкой входа, а Doxygen содержит навигацию по исходникам и полное API.</p>
|
||
<div class="stats"><span class="stat"><b>17</b> внутренних C-модулей</span><span class="stat"><b>6</b> ролей платы</span><span class="stat"><b>2× SCI</b> + eCAN-A</span><span class="stat"><b>CCS 3 / 12</b></span></div>
|
||
<div class="links"><a class="button primary" href="api/html/index.html">Открыть Doxygen API</a><a class="button" href="../README_CCS12.md">Сборка CCS 12</a></div>
|
||
</header>
|
||
<nav class="tabbar"><div class="wrap tabs" role="tablist" aria-label="Разделы">
|
||
<button class="tab" role="tab" aria-selected="true" aria-controls="overview">Обзор</button>
|
||
<button class="tab" role="tab" aria-selected="false" aria-controls="architecture">Архитектура</button>
|
||
<button class="tab" role="tab" aria-selected="false" aria-controls="modules">Модули</button>
|
||
<button class="tab" role="tab" aria-selected="false" aria-controls="data">Данные</button>
|
||
<button class="tab" role="tab" aria-selected="false" aria-controls="analysis">Анализ кода</button>
|
||
<button class="tab" role="tab" aria-selected="false" aria-controls="build">Сборка</button>
|
||
</div></nav>
|
||
<main class="wrap">
|
||
<section class="pane" id="overview" role="tabpanel">
|
||
<h2>Что делает проект</h2><p class="intro">Прошивка объединяет измерительный тракт, диагностику, управление выходами и два транспортных интерфейса. Аппаратная роль определяется при старте, поэтому один код работает на нескольких платах комплекса.</p>
|
||
<div class="grid">
|
||
<article class="card wide"><span class="tag">Поток запуска</span><h3>От сброса до рабочего цикла</h3><div class="filetree">InitSysCtrl → PIE / XINTF → get_Mode
|
||
↓
|
||
eCAN-A + SCI-A/SCI-B + SPI EEPROM
|
||
↓
|
||
GPIO / ADC / Timer1 / параметры / маски CAN
|
||
↓
|
||
главный цикл: CAN → команды → кнопки → RS-485</div></article>
|
||
<article class="card"><span class="tag blue">Платформа</span><h3>Texas Instruments C2000</h3><p>TMS320F28335, COFF ABI, large memory model и аппаратные модули ADC, eCAN, SCI, SPI, CPU Timer и XINTF.</p></article>
|
||
<article class="card"><span class="tag amber">Конфигурация</span><h3>BALSAM = 167</h3><p><code>package.h</code> выбирает направление, RS-калибровку, OWEN и раскладку общих регистров.</p></article>
|
||
<article class="card"><span class="tag">Главная модель</span><h3>128 Modbus-регистров</h3><p>Измерения, уставки, ошибки, калибровка и команды представлены через массив <code>modbus</code> и макросы доступа.</p></article>
|
||
<article class="card"><span class="tag red">Реальное время</span><h3>Три контура</h3><p>ADC ISR собирает выборки, Timer1 ведёт измерение или пульт, главный цикл выполняет связь и команды.</p></article>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="pane" id="architecture" role="tabpanel" hidden>
|
||
<h2>Как связаны подсистемы</h2><p class="intro">Быстрые обработчики обновляют состояние, а главный цикл публикует его и принимает управляющие команды. Общая модель связывает подсистемы без динамического выделения памяти.</p>
|
||
<div class="flow"><div class="step"><b>01 · Входы</b><span>ADC, GPIO, SCI, eCAN</span></div><div class="step"><b>02 · Обработка</b><span>фильтры, физические величины</span></div><div class="step"><b>03 · Диагностика</b><span>таймеры, пороги, ERROR</span></div><div class="step"><b>04 · Модель</b><span>modbus и команды</span></div><div class="step"><b>05 · Выходы</b><span>CAN, RS-485, DAC, GPIO</span></div></div>
|
||
<div class="grid">
|
||
<article class="card half"><span class="tag">Измерительная плата</span><h3>ADC ISR + Timer1 SENS</h3><ol><li>ADC ISR накапливает и фильтрует выборки.</li><li><code>cpu_timer1_isr_SENS</code> выбирает канал и планирует пересчёт.</li><li><code>Temper_count</code>, <code>Current_count</code> и <code>Power_count</code> обновляют значения.</li><li><code>er_anal</code> подтверждает ошибки с выдержкой времени.</li></ol></article>
|
||
<article class="card half"><span class="tag blue">Пульт EPLT</span><h3>Timer1 PULT</h3><p>Для роли <code>dsk_EPLT</code> Timer1 направляется в <code>cpu_timer1_isr_PULT</code>. Обработчик ведёт внешнюю индикацию и дискретный интерфейс, не запуская обычный измерительный контур.</p></article>
|
||
<article class="card full"><span class="tag amber">Конкурентный доступ</span><h3>Главный цикл и прерывания используют общие переменные</h3><p>При изменениях учитывайте атомарность доступа C28x, порядок обновления <code>modbus</code>, флаги <code>CanGO</code>/<code>READY</code> и время выполнения ISR. В прерываниях нельзя добавлять блокирующий обмен с EEPROM или UART.</p></article>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="pane" id="modules" role="tabpanel" hidden>
|
||
<h2>Внутренние модули</h2><p class="intro">Таблица показывает назначение каждого слоя и его основные точки входа.</p>
|
||
<article class="card full"><div class="table-scroll"><table><thead><tr><th>Модуль</th><th>Назначение</th><th>Основные API</th></tr></thead><tbody>
|
||
<tr><td>main.c</td><td>Старт платформы и кооперативный главный цикл</td><td><code>main</code>, <code>timer_Init</code></td></tr>
|
||
<tr><td>ADC.c</td><td>Секвенсор ADC, накопление и ISR</td><td><code>setup_adc</code>, <code>adc_isr</code></td></tr>
|
||
<tr><td>measure.c</td><td>Температура, ток, напряжение, мощность и диагностика</td><td><code>Init_sensors</code>, <code>Current_count</code>, <code>Temper_count</code>, <code>Power_count</code></td></tr>
|
||
<tr><td>filter_bat2.c</td><td>IIR-фильтр Баттерворта второго порядка</td><td><code>filterbat</code></td></tr>
|
||
<tr><td>RS485.c</td><td>Два SCI-канала, RX/TX автоматы и тайм-ауты</td><td><code>setup_uart</code>, <code>RS_Send</code>, <code>RS_BSend</code></td></tr>
|
||
<tr><td>bios.c</td><td>Сервисный/загрузочный протокол контроллера</td><td><code>get_command</code>, <code>peek</code>, <code>poke</code>, <code>load</code>, <code>run</code></td></tr>
|
||
<tr><td>message.c</td><td>Modbus, параметры и обмен с OWEN</td><td><code>ReceiveCommandModbus3</code>, <code>Save_params</code>, <code>Load_params</code></td></tr>
|
||
<tr><td>ecan.c</td><td>eCAN-A mailboxes и телеметрия</td><td><code>InitCan</code>, <code>CAN_send</code>, <code>CANa_handler</code></td></tr>
|
||
<tr><td>spise2p.c</td><td>SPI-драйвер последовательной EEPROM</td><td><code>InitSeeprom</code>, <code>Seeprom_read</code>, <code>Seeprom_write</code></td></tr>
|
||
<tr><td>peripher.c</td><td>Распознавание платы, GPIO и мультиплексоры</td><td><code>get_Mode</code>, <code>get_Buttons</code>, <code>select_tpl_canal</code></td></tr>
|
||
<tr><td>DAC.c</td><td>Аналоговый выход платы нагрузки</td><td><code>Init_DAC</code>, <code>Anal_output</code>, <code>Load_runner</code></td></tr>
|
||
<tr><td>pulto.c / kanal.c</td><td>Пульт и последовательная индикация</td><td><code>cpu_timer1_isr_PULT</code>, <code>kanal_Send</code></td></tr>
|
||
<tr><td>crc16.c / tools.c</td><td>CRC, XINTF zone 7 и задержки</td><td><code>get_crc_16</code>, <code>init_zone7</code>, <code>pause_us</code></td></tr>
|
||
</tbody></table></div></article>
|
||
</section>
|
||
|
||
<section class="pane" id="data" role="tabpanel" hidden>
|
||
<h2>Данные и конфигурация</h2><p class="intro">Система построена вокруг статических массивов и битовых слов. Это подходит для C28x, но требует строго сохранять индексы и размеры.</p>
|
||
<div class="grid">
|
||
<article class="card half"><span class="tag">modbus[]</span><h3>Карта регистров</h3><ul><li><code>0x00</code> — слова ошибок каналов.</li><li><code>0x18</code> — текущие измерения.</li><li><code>0x30</code> — верхние уставки.</li><li><code>0x48</code> — нижние уставки.</li><li><code>0x60+</code> — периоды, яркость и служебные параметры.</li><li><code>0x7F</code> — команды.</li></ul></article>
|
||
<article class="card half"><span class="tag blue">ERROR</span><h3>Слово диагностики</h3><p>Биты описывают обрыв, неправильный сигнал, выход за диапазон, перегрев, стоп, готовность, дискретные входы, игнорирование и bypass. Поле <code>all</code> позволяет передавать слово целиком.</p></article>
|
||
<article class="card"><span class="tag amber">caliber.h</span><h3>Заводские таблицы</h3><p>Калибровки зависят от значения <code>BALSAM</code>. Файл содержит определения данных и должен включаться только там, где формируются значения по умолчанию.</p></article>
|
||
<article class="card"><span class="tag">GPIO_table.h</span><h3>Роли платы</h3><p>Направления и начальные уровни GPIO заданы отдельными наборами для COMM, BKSD, BKST, EPLT, SHKF и LOAD.</p></article>
|
||
<article class="card"><span class="tag red">CP1251</span><h3>Кодировка legacy-кода</h3><p>Старые комментарии исходников записаны в Windows-1251. Doxygen настроен декодировать <code>*.c</code> и <code>*.h</code> как CP1251; новые документы — UTF-8.</p></article>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="pane" id="analysis" role="tabpanel" hidden>
|
||
<h2>Анализ кода</h2><p class="intro">Markdown-отчёты из каталога <code>Doc</code> включаются в Doxygen при каждой сборке. Выберите документ — его HTML откроется справа без ухода с этой вкладки.</p>
|
||
<div class="analysis-layout">
|
||
<nav class="analysis-nav" aria-label="Отчёты анализа кода">
|
||
<a class="analysis-link active" href="api/html/phase_break_error_flow.html" target="analysisFrame">Ошибка обрыва фаз<small>Детектирование и передача ошибки</small></a>
|
||
<a class="analysis-link" href="api/html/phase_comparison_balsam.html" target="analysisFrame">Balsam 165 ↔ 167<small>Сравнение фазовой части</small></a>
|
||
<a class="analysis-link" href="api/html/phase_voltage_calculation.html" target="analysisFrame">Расчёт фаз<small>Диагностика и уровни напряжения</small></a>
|
||
<a class="analysis-link" href="api/html/phase_voltage_weak_points.html" target="analysisFrame">Слабые места<small>Риски расчёта и контроля</small></a>
|
||
</nav>
|
||
<iframe class="analysis-frame" name="analysisFrame" title="Выбранный отчёт анализа кода" src="api/html/phase_break_error_flow.html"></iframe>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="pane" id="build" role="tabpanel" hidden>
|
||
<h2>Как собрать документацию</h2><p class="intro">Скрипт повторяет схему эталонных HTML-документов: формирует автономную точку входа и дополнительно запускает Doxygen, если он установлен.</p>
|
||
<div class="grid">
|
||
<article class="card wide"><span class="tag">Команда</span><h3>Запуск из корня репозитория</h3><pre>Doc\build.bat</pre><p>Готовый обзор: <code>Doc\build\index.html</code><br>API: <code>Doc\build\api\html\index.html</code><br>Предупреждения: <code>Doc\build\doxygen-warnings.log</code></p></article>
|
||
<article class="card"><span class="tag blue">Зависимость</span><h3>Doxygen в PATH</h3><p>Без Doxygen обзор всё равно собирается, а скрипт печатает предупреждение. После установки повторный запуск добавит API-справочник.</p></article>
|
||
<article class="card full"><span class="tag amber">Проверка изменений</span><h3>Перед публикацией</h3><ul class="check"><li>Открывается <code>build/index.html</code>.</li><li>Ссылка «Открыть Doxygen API» ведёт на созданный индекс.</li><li>В журнале нет неизвестных команд и неверных ссылок.</li><li>Новые публичные функции описаны в заголовке или <code>api.dox</code>.</li><li>Разметка <code>modbus</code> согласована с внешним описанием данных.</li></ul></article>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
<footer><div class="wrap">Balsam 167 Peripheral · источник истины по поведению — код, по API — Doxygen-комментарии и заголовки.</div></footer>
|
||
<script>
|
||
const tabs=[...document.querySelectorAll('[role=tab]')],panes=[...document.querySelectorAll('[role=tabpanel]')];function show(id,hash=true){const tab=tabs.find(x=>x.getAttribute('aria-controls')===id)||tabs[0];tabs.forEach(x=>x.setAttribute('aria-selected',x===tab));panes.forEach(x=>x.hidden=x.id!==tab.getAttribute('aria-controls'));if(hash)history.replaceState(null,'','#'+tab.getAttribute('aria-controls'))}tabs.forEach((tab,i)=>{tab.onclick=()=>show(tab.getAttribute('aria-controls'));tab.onkeydown=e=>{if(e.key==='ArrowRight')show(tabs[(i+1)%tabs.length].getAttribute('aria-controls'));if(e.key==='ArrowLeft')show(tabs[(i-1+tabs.length)%tabs.length].getAttribute('aria-controls'))}});if(location.hash)show(location.hash.slice(1),false);document.querySelectorAll('.analysis-link').forEach(link=>link.addEventListener('click',()=>{document.querySelectorAll('.analysis-link').forEach(item=>item.classList.remove('active'));link.classList.add('active')}));
|
||
</script>
|
||
</body>
|
||
</html>
|