Языки высокого уровняПричины использования языков. Помимо ассемблеров для программирова­ния приложений используются различные языки высокого уровня, что обусловле­но следующими причинами:

●     существует множество алгоритмов и готовых программ на языках высокого уровня, которые можно непосредственно вставить в разрабатываемую при­кладную программу. Если возникает необходимость переноса программ на другие микроконтроллеры, то такой перенос выполняется намного проще, чем перенос программ на ассемблере;

●     при программировании на языках высокого уровня имеется ряд возможностей, которыми не располагают ассемблеры. Например, разработчик может авто­матически вводить в программу коды сложных операций, производить эф­фективный контроль синтаксических ошибок и др. Поэтому составление про­грамм на языках высокого уровня требует меньших затрат;

●     при разработке программ на языке высокого уровня значительно упрощается поддержка приложения, связанная с модификацией и отладкой программно­го кода.

К наиболее распространенным языкам относятся C/C++, BASIC и Forth. С помощью компиляторов языки высокого уровня преобразуются в язык ассемб­лера, а затем в объектный код (биты и байты), который выполняется микроконтроллером. Имеется множество компиляторов, разработанных для различных мик­роконтроллеров. Их эффективность определяется требуемым объемом памяти программ и данных, а также ресурсами, необходимыми для поддержания объект­ного кода.

Языки высокого уровня характеризуются рядом показателей, реализация ко­торых во встраиваемых микроконтроллерах может оказаться проблематичной, что обусловлено:

●     ограниченным объемом памяти программ (ROM) и данных (RAM);

●     отсутствием BIOS или операционной системы;

●     наличием переопределяемых выводов контроллеров (когда вывод может ис­пользоваться как цифровой/аналоговый/последовательный вход–выход).

Рассмотрим основные особенности и показатели языков высокого уровня применительно к микроконтроллерам.

Библиотеки и функции. Функция — это подпрограмма, при выполнении ко­торой определенные параметры вызываются из исходной программы, а после за­вершения возвращаются обратно. Библиотека содержит набор функций (для ма­тематических операций, преобразования и пересылки данных, консольного вво­да–вывода и др.), скомпонованных в виде объектного файла.

Встроенные (в стандартные подключаемые библиотеки) функции, необходи­мые для некоторых приложений, могут оказаться невостребованными для других. Вряд ли найдется приложение, использующее одновременно все функции стан­дартной библиотеки. Поэтому в микроконтроллерах, имеющих ограниченный объем памяти, использование стандартных библиотек может привести к неоправ­данным затратам памяти.

Функция стандартной библиотеки предварительно проверяет наличие обору­дования (и его характеристики) и только после этого выполняет заданные дей­ствия. Из–за схемных особенностей различных микроконтроллеров (например, контроллер может содержать или не содержать некоторый функциональный узел) необходимость такой проверки приводит к увеличению времени исполнения про­граммы и объема памяти конкретного контроллера.

Указанные проблемы можно решить путем компоновки в программный код (объектный файл, или библиотеку) только тех функций, которые необходимы для конкретного применения с учетом специфики используемого микроконтроллера. Другой подход состоит в том, что включение в объектный код требуемых фраг­ментов реализуется с помощью условной компиляции. В этом случае объектным файлом является вся программа, т. е. отдельный объектный файл с набором функ­ций не создается.

Типы данных и операции над данными.Тип данных — это форма представ­ления данных для компьютерной обработки. Важную роль играют типы данных, которые поддерживаются аппаратным обеспечением и для которых требуются специальные форматы.

Типы данных можно разделить на две категории: числовые и нечисловые.

Числовые типы данных. Среди них главными являются целые двоичные числа со знаком и без знака. Для их представления обычно используется 8, 16, 32 и 64 бита. В целых числах со знаком старший разряд отводится под знак, по­этому значения N–разрядного числа лежат в пределах от –(2N–11) до +(2N–1 – 1), диапазон значений чисел без знака составляет 0...2N – 1.

Для представления нецелых чисел (например, 4.5) используется две формы: с плавающей и фиксированной точкой. Их длина может составлять 32,64 и 80 бит.

В компьютерах имеются отдельные регистры для целочисленных операндов и для операндов с плавающей точкой.

Для представления десятичных чисел используется двоично–десятичный фор­мат, в котором для кодирования одного разряда отводится 4 или 5 бит. Для кор­рекции результатов десятичной арифметики используются специальные команды.

Нечисловые типы данных. Для обработки текстов или управления базой данных необходимо использовать нечисловые типы данных. Для этой цели исполь­зуются такие символьные коды как ASCII или UNICODE, поддерживающие 7–бит­ные и 16–битные символы соответственно.

В микроконтроллерах широкое распространение получил целочисленный тип данных длиной 8 и 16 бит. Операции над числами, имеющими разрядность больше базовой (8 бит), часто реализуются с помощью библиотечных функций, которые увеличивают время выполнения и объем требуемой памяти. Обработка 16–раз­рядных данных реализуется с помощью небольшого увеличения объема программ­ного кода и памяти данных. В тоже время 16–разрядные данные обеспечивают достаточно большой диапазон представления обрабатываемых данных. При пра­вильной организации вычислений обработка данных практически для всех встроенных приложений, использующих 8–разрядные микроконтроллеры, может быть выполнена с использованием 8–и и 16–и разрядных целых чисел.

Обработка целочисленных данных. При обработке данных с разрядно­стью более 8 бит необходимо вводить дополнительные команды.

Пример. Рассмотрим операцию сложения, представленную в виде выражения на языке С:

FirstVar = FirstVar + SecondVar

Для 8–разрядных операндов эта операция выполняется микроконтроллером 8051 с помощью следующей последовательности команд:

MOV              A, FirstVar                ;Поместить первую переменную FirstVar в

;аккумулятор А

ADD               A, SecondVar           ;Содержимое А сложить со второй

;переменной SecondVar

MOV               FirstVar, А               ;Сумму поместить в ячейку FirstVar

 

Для 16–разрядных переменных программный код усложняется:

MOV              A, FirstVar                ;Сложить младшие 8 бит

ADD               A, SecondVar

MOV              FirstVar, А

INCSKIP                                         ;Если перенос С не установлен,

;то пропустить увеличение

INC                FirstVar + 1              ;Увеличить старшие 8 бит результата

SKIP

MOVA, FirstVar + 1          ;Сложить старшие 8 бит

ADD A, SecondVar + 1

MOV FirstVar + 1, А

Для выполнения более сложных операций, программный код может быть реа­лизован с помощью ряда стековых операций. Например, для вычисления

FirstVar = SecondVar + (ThirdVar * FourthVar)

последовательность операций, обеспечивающих получение необходимого ре­зультата, имеет вид

push      SecondVar

push      ThirdVar

push      FourthVar

mul

add

pop       FirstVar

 

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

FirstVar = SecondVar + ( ThirdVar * Fourth Var )

более эффективно реализуется в виде следующей последовательности операций:

Temp = ThirdVar * FourthVar; FirstVar = SecondVar + Temp;

Еще одно возможное представление приведенного выше примера касается того, как компилятор преобразует числа и обрабатывает промежуточные пере­менные. Если переменная «FirstVar» не определена как порт ввода–вывода, то программный код можно представить в следующем виде:

FirstVar = ThirdVar * Fourth Var;

FirstVar = FirstVar + SecondVar;

При таком представлении компилятор учитывает, что переменная FirstVar не используется при выполнении операции, и ее можно использовать для хранения промежуточных результатов.

Глобальные и локальные переменные. Во многих языках высокого уровня существует два типа переменных:

●     глобальные переменные, которые заданы для всей программы. Их значения не могут переопределяться. Они обычно используются в основном теле про­граммы и при выполнении многих подпрограмм, когда передача значения пе­ременной в качестве параметра подпрограммы не эффективна;

●     локальные переменные используются при выполнении конкретной подпрог­раммы и создаются при обращении к ней. Обычно локальные переменные загружаются в стек при вызове подпрограммы и извлекаются из него при возвращении управления вызывающей программе. Значение локальной пере­менной теряется после выхода из подпрограммы. Параметры, передаваемые подпрограмме, в большинстве случаев становятся локальными переменными. При этом первоначальные значения параметров сохраняются, а текущие зна­чения при выполнении подпрограммы могут изменяться.

Указатели и структуры данных. Эти средства служат для повышения эффек­тивности программирования при больших объемах памяти.

Указатели предназначены для управления ресурсами памяти. При программи­ровании микроконтроллеров с малым объемом памяти указатели обычно не ис­пользуются. В таких контроллерах вместо указателей в начале раздела памяти создается массив, который путем индексирования используется для обращения к любому элементу в этой памяти. Чтобы выбрать необходимый элемент в массиве данных, следует к значению индекса, задающего адрес начального элемента массива, прибавить смещение, указывающее позицию выбираемого элемента.

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

Например, структуру процессорной команды на языке С можно определить следующим образом:

struct instruct {        // Формат команды

int       address;         // Адрес команды

char    instruct;          // Команда

int       value;             //16–битные данные

}:

 

Обычно на структуру ссылаются с помощью указателя, но те же данные можно поместить в массив 16 разрядных слов (целочисленные данные типа int на языке С) и ссылаться на него при помощи индекса. Чтобы выбрать необходимый элемент в массиве данных, следует к значению индекса, задающего адрес на­чального элемента массива, прибавить смещение, указывающее позицию выби­раемого элемента.

Проиллюстрируем использование указателей и структур данных на конкрет­ном примере. При использовании указателя для выбора некоторой величины из области данных необходимый программный код имеет следующий вид:

structinstruct * Ptr;             //Определение указателя на структуру

.

;

i = Ptr —> value;                  //Прочесть "value" из текущего элемента

При организации массива эта процедура выглядит следующим образом:

structinstruct Array[100];  //Определение массива структур

.

;

i = = Array[ Index ].value;

Этот код немного сложнее кода с указателем, но в нем не используется указа­тель, за которым необходимо следить, чтобы он всегда корректно обращался к требуемому элементу структуры.

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

char Greeting [13] = "Hello there I";

Компилятор языка размещает таблицы в памяти программ. Информация в таблице выбирается как массив, идентичный массивам, считываемым из опера­тивной памяти.

Доступ к аппаратным средствам. Прикладная программа на языках высоко­го уровня должна обеспечить доступ к таким аппаратным средствам как регистры микроконтроллера. Для обращения к регистрам используется вставка в тело про­граммы ассемблерных инструкций и некоторых позиций адресного пространства данных, используемых в качестве указателей регистров.

Оба способа поддерживаются языками высокого уровня.

Символическая информация. Для упрощения отладки компиляторы выдают символическую информацию, представляющую собой ссылки на используемые строки, метки, переменные и указание на их размещение в памяти. Эта информа­ция используется симуляторами и эмуляторами, чтобы отображать выполнение программы на уровне исходного текста, а не на уровне машинного кода (ассемб­лера). Следует иметь в виду, что не все компиляторы выдают одинаковую символическую информацию. Это обстоятельство необходимо учитывать при вы­боре компилятора.

Из материала по языкам программирования следует, что:

●     при программировании управляющих систем чаще всего используются ма­шинно–ориентированный язык ассемблера или языки С / С++. Язык ассемблера применяется при жестких ограничениях на объем требуемой памяти или на время выполнения программных модулей. Такие случаи являются достаточно типич­ными при решении задач управления, поэтому ассемблеры являются одним из основных средств создания программного обеспечения для микроконт­роллерных систем. В тех случаях, когда указанные ограничения не очень жес­ткие, для создания программного обеспечения используются языки высокого уровня (обычно С / С++);

 

●     при разработке программного обеспечения для универсальных микропроцес­сорных систем используется достаточно широкий набор языков высокого уровня, для которых имеются соответствующие компиляторы. Чаще всего ис­пользуются языки С, С++, FORTRAN, Pascal, Forth. Для решения ряда задач применяются языки поддержки искусственного интеллекта Ada, Modula–2 и некоторые другие.


Рекомендуйте эту статью другим!



Общая характеристика оптоэлектронных приборов
сен 02, 2016 592

Общая характеристика оптоэлектронных приборов

Оптоэлектронными называют приборы, которые чувствительны к электромагнитному излучению в…
Обмен данными в параллельном коде
нояб 01, 2015 687

Обмен данными в параллельном коде

Прямой ввод/вывод данных. Как уже отмечалось, прямой ввод/вывод воз­можен только с…
dvig per toka 1
мая 12, 2017 140

Испытания электродвигателей переменного тока, перечень работ, периодичность

Помимо проверки состояния механических элементов и смазки, при капитальных и текущих…
Второй закон Киргоффа
дек 21, 2013 8510

Второй закон Кирхгофа. Определение и формула.

Второй закон Кирхгофа описывает алгебраическую зависимость между падениями напряжений и…
Нулевой рабочий проводник 1
фев 12, 2014 11318

Нулевой рабочий проводник

Нулевой рабочий проводник также называют нейтралью. Большинство бытовых приборов питаются…