Понятие многофайлового и многомодульного программирования
В процессе написания программ обычно накапливаются подпрограммы и фрагменты кода, которые можно использовать в нескольких программах. Фрагменты исходного кода можно копировать из программы в программу при помощи текстового редактора, в котором вы пишете программы, однако это может привести к некоторым неудобствам. Прежде всего, разрастается текст программы, и в нем становится трудно ориентироваться при написании и редактировании программы. Кроме того, при обнаружении ошибок в отлаженном ранее участке кода или при переходе к работе с другими устройствами (от светодиодного индикатора к жидкокристаллическому, от микросхемы АЦП одного типа к микросхеме другого типа) приходится искать включенные ранее участки кода и заменять их новыми.
Это трудоемкая работа, которая приводит к ошибкам и, в конечном счете, замедляет написание и отладку программ. Но как же решить эту проблему? Намного удобнее использовать и хранить исходный текст программы в нескольких файлах, предоставляя работу по соединению этих файлов в единую программу транслятору. Обычно в один файл помещается участок кода, работающий с каким-либо конкретным устройством (жидкокристаллическим индикатором, последовательной микросхемой ПЗУ и т. д.) или отвечающий за определенную задачу (вывод цифровой и текстовой информации, помехоустойчивое кодирование, прием управляющих сигналов).
Использование готовых участков кодов позволяет собирать новые программы из готовых кусков как в детском конструкторе. Правда, не стоит надеяться, что эти куски будут так же легко соединяться!
Многофайловые программы
Самым простым способом соединения нескольких файлов в одну программу является использование директивы включения текстового файла.
В языке программирования ASM-51 это директива include. Точно так же, только буквами нижнего регистра записывается эта директива и в языке программирования С.
При использовании директивы include в исходный текст программы добавляется содержимое включаемого файла, и только после этого производится трансляция исходного текста в исполняемый код программы. Иными словами, содержимое главного файла программы и включаемых в него файлов объединяются препроцессором транслятора во временном файле, и только после этого производится трансляция полученного временного файла в исполняемый код микроконтроллера. Пример использования директивы включения текстового файла в программе на языке программирования С-51 приведен в листинге 7.17.

В отдельные файлы выделяются, как правило, описания внутренних регистров микроконтроллера и переменных, связанных с выводами микросхемы микроконтроллера. Рассмотрим для примера содержимое включаемых файлов, имена которых использованы в примере, приведенном в листинге 7.17. Фрагменты исходных текстов этих файлов приведены в листингах 7.18 и 7.19.
Содержимое файла IO.h является примером использования отдельного файла для хранения функций, осуществляющих ввод и вывод данных. Такое использование включаемых файлов позволяет разделить программу по функциям. В результате новые программы можно собирать из таких файлов как из кирпичиков, используя готовые уже отлаженные подпрограммы. Таким образом, использование включаемых файлов резко упрощает программирование.


В файле REG51.h объявляются переменные, связанные с регистрами специального назначения микроконтроллера 89с51. Они должны использоваться в любой программе, работающей с микроконтроллером 89с51. Не имеет смысла повторять эти объявления в каждой программе - их можно выделить в отдельный файл, что и сделано в приведенном в листинге 7.19 примере. Более того, файлы объявления регистров специальных функций для различных типов микроконтроллеров обычно поставляются разработчиками компиляторов для исключения ошибок.

Файл объектного кода программы, который будет преобразован в машинные коды микроконтроллера, формируется программой-транслятором в процессе обработки исходного текста программы. Как уже упоминалось ранее, прежде чем начать собственно преобразование исходного текста программы, транслятор производит предварительную обработку программы, в процессе которой выполняются директивы условной трансляции, включения содержимого дополнительных файлов и макроподстановок. Часто говорят, что перед трансляцией программы работает препроцессор.
В результате этой предварительной обработки программы транслятор формирует временный файл. Например, в результате выполнения участка программы, приведенного в листинге 7.17, будет сформирован временный файл, содержание которого приведено в листинге 7.20. Именно этот файл и будет преобразован в машинные коды микроконтроллера, которые будут сохранены на жестком диске компьютера в виде загрузочного файла.



Подведем итоги. При многофайловом программировании:
- использование нескольких файлов позволяет разбить исходный текст программы на несколько частей, каждая из которых реализует свою независимую задачу;
- удобнее всего в отдельные файлы выносить подпрограммы, которые должны быть построены таким образом, чтобы их связь с основной программой была минимальной;
- разбираться с короткими файлами, реализующими одну или несколько связанных между собой функций, намного легче, чем работать с одним большим файлом;
- различные части программы могут быть написаны разными программистами, которым намного легче работать со своей программой, оформленной в виде отдельного файла.
Разбивать на несколько файлов можно не только программы, исходный код которых разработан на языках высокого уровня. Включение файлов можно использовать и в программах на языке ассемблера. В листинге 7.21 приведен пример использования включения файлов в программе на языке ASM-51.