Миландр 1986ве91т: Бегущие огни

Автор
avatar-alexevsalexevs
Notebook

Генерация кода для Миландр 1986ВЕ91Т (Бегущие огни)

Введение

В этом примере рассмотрена генерация кода из модели Engee для микроконтроллера 1986ВЕ91Т от АО "ПКК Миландр". Модель воспроизводит работу "бегущих огней" на отладочной плате микроконтроллера, сборка проекта осуществляется в среде Keil μVision, а загрузка исполняемого кода - через отладчик J-Link.

Аппаратная часть

Целевое устройство - микроконтроллер от АО "ПКК Миландр" 1986ВЕ91Т (MDR32F9Q1). В примере используется отладочный модуль для микросхем 1986ВЕ91Т, 1986ВЕ94Т (версия 5):

plata.jpg

В примере тестируется работа цифровых выходов PORT_Pin_10 - PORT_Pin_14 порта PORTD микроконтроллера, которые на отладочной плате соединены со светодиодами VD5 - VD9. Для тестирования работы воспроизведём "бегущий огонь" - последовательное включение и выключение светодиодов. Время включения каждого из светодиодов зададим равным 100 мс.

Описание модели

Модель примера - mdr32f9q1_running_lights.engee. Длительность выдачи высокого уровня сигнала на цифровые выходы устанавливается в модели блоком period_msec.

model_2.jpg

Блок Chart воcпроизводит алгоритм изменения с заданным периодом номера выходного светодиода по порядку. Блок Demultiplexer по номеру выходного светодиода выдаёт на соответствующий выходной порт единицу. Конечный автомат, реализуемый блоком Chart, включает в себя пять состояний, циклически поочередно активируемых.

chart.jpg

Для перехода между состояниями конечного автомата используется темпоральная логика.

Блоки периферии

Блоки PORTD_CONFIG и PORT1 - PORT5 добавляют в модель код Си для работы с периферией контроллера. Для того чтобы добавить в сгенерированный код строки с подключением необходимых заголовочных файлов, во вкладке Build options блока PORTD_CONFIG прописаны имена и путь к подключаемых файлов заголовков. Сами файлы не содержат код и не используются при моделировании. При сборке же проекта подключаемые файлы будут добавлены из пакета поддержки для микроконтроллера.

cfunc_options.jpg

Блок PORTD_CONFIG добавляет в сгенерированный из модели код с функциями для инициализации используемых в проекте портов, а блоки PORT1 - PORT5 - код с функциями для установки и сброса активного состояния соответствующих цифровых пинов.
Содержимое кодовых ячеек периферийных блоков "обёрнуто" в условные директивы препроцессора:

#if defined ( USE_MDR1986VE9x )
    // пользовательский код
#endif

Это позволяет выполнять код из блоков только на определенных целевых устройствах, игнорируя его, например, при моделировании в Engee.

Результаты моделирования

Загрузим и выполним модель примера:

In [ ]:
# @markdown **Программное управление моделированием:**  
# @markdown Требуется ввести только имя модели
имя_модели = "mdr32f9q1_running_lights" # @param {type:"string"}
if имя_модели in [m.name for m in engee.get_all_models()]
    модель = engee.open( имя_модели );
else
    модель = engee.load( "$(@__DIR__)/"*имя_модели*".engee" );
end
данные = engee.run(модель);

Построим графики выходных переменных. Сигналы единичных импульсов по каналам отмасштабируем для наглядности:

In [ ]:
gr(size = (900,400))
plot(данные["channel"].time, [данные["channel"].value, 1.05.*данные["vd5"].value,
     1.1.*данные["vd6"].value, 1.15.*данные["vd7"].value, 1.2.*данные["vd8"].value, 1.25.*данные["vd9"].value,];
     label=[:none "vd5" "vd6" "vd7" "vd8" "vd9"], title="Бегущие огни", st = :step)
Out[0]:

Как видно из графиков, конечный автомат и демультиплексор отрабатывают заданный алгоритм, формируя последовательно импульсы на пять каналов с заданной длительностью.

Генерация кода

Сгенерируем код из разработанной модели.

In [ ]:
# @markdown **Генерация кода:**  
# @markdown Папка для результатов генерации кода будет создана в папке скрипта:
папка = "code" # @param {type:"string"}

# @markdown Генерация кода для подсистемы:
включить = false # @param {type:"boolean"}
if(включить)
    подсистема = "" # @param {type:"string"}
    engee.generate_code( "$(@__DIR__)/"*имя_модели*".engee", "$(@__DIR__)/"*папка;
                     subsystem_name = подсистема)
else
    engee.generate_code( "$(@__DIR__)/"*имя_модели*".engee", "$(@__DIR__)/"*папка)
end

# @markdown Генерировать `main.c`?
использовать = false # @param {type:"boolean"}

if (!использовать)
    cd("$(@__DIR__)/"*папка)
    rm("main.c")
end
[ Info: Generated code and artifacts: /user/start/examples/codegen/mdr32f9q1_running_lights/code

Так как в проекте будет использоваться готовый main.c, для устранения путаницы кодовая ячейка выше удаляет сгенерированный из модели шаблон main.c. Готовый main.c и сгенерированные из модели файлы теперь необходимо добавить в проект среды разработки Keil μVision.

Состав проекта

Для работы с микроконтроллером в среде разработке необходимо установить пакет поддержки. Для этого примера мы использовали неофициальный пакет поддержки.

Далее следуют стандартные шаги при работе в Keil μVision. - создание проекта, добавление файлов источников для необходимой периферии и файлов заголовков для конфигурации устройства, а также настройка сборщика и дебаггера. После этого скачаем файлы примера из папки \code, а также main.c и добавим их в проект Keil.

project.jpg

Далее можно перейти к сборке проекта и загрузке/отладке кода.

Сборка проекта и загрузка кода

Соберём проект Keil, после чего в терминале среды должно быть выведено аналогичное сообщение:

Build started: Project: new_project_1
*** Using Compiler 'V6.22', folder: 'C:\Users\engeeuser\AppData\Local\Keil_v5\ARM\ARMCLANG\Bin'
Build target 'Target_1'
compiling main.c...
mdr32f9q1_running_lights.c(49): warning: variable 'seq' is uninitialized when used here [-Wuninitialized]
   49 |         cfunc_symbols->seq = seq;
      |                              ^~~
mdr32f9q1_running_lights.c(44): note: initialize the variable 'seq' to silence this warning
   44 |         int8_t seq;
      |                   ^
      |                    = '\0'
mdr32f9q1_running_lights.c(291): warning: comparison of integers of different signs: 'int64_t' (aka 'long long') and 'uint64_t' (aka 'unsigned long long') [-Wsign-compare]
  291 |         return counter * numerator >= (uint64_t)ceil(condition * denominator);
      |                ~~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mdr32f9q1_running_lights.c(338): warning: unused variable 'seq' [-Wunused-variable]
  338 |                 double seq = PORTD_CONFIG_cfunc_symbols.seq;
      |                        ^~~
mdr32f9q1_running_lights.c(351): warning: variable 'Chart_selector' set but not used [-Wunused-but-set-variable]
  351 |                 int Chart_selector;
      |                     ^
4 warnings generated.
compiling mdr32f9q1_running_lights.c...
linking...
Program Size: Code=5264 RO-data=224 RW-data=16 ZI-data=1672  
".\Objects\new_project_1.axf" - 0 Error(s), 4 Warning(s).
Build Time Elapsed:  00:00:00

Сборка прошла без ошибок, перейдём к загрузке кода в микроконтроллер. Подключим питание платы и JTAG-отладчик. В данном примере - это SEGGER J-link.