Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ответы мкр и мпс.doc
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
3.97 Mб
Скачать

5.10.2 Перемещаемые сегменты памяти.

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

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

data - размещает сегмент во внутренней памяти данных с прямой адресацией;

idata - размещает сегмент во внутренней памяти данных с косвенной адресацией;

bit - размещает сегмент во внутренней памяти данных с битовой адресацией;

xdata - размещает сегмент во внешней памяти данных;

code - размещает сегмент в памяти программ;

Директива rseg после определения имени сегмента можно использовать этот сегмент при помощи директивы rseg. Использование сегмента зависит от области памяти, для которой он предназначен. Если это память данных, то в сегменте объявляются байтовые или битовые переменные. Если это память программ, то в сегменте размещаются константы или участки кода программы.

Пример использования директив segment и rseg для объявления битовых переменны:

_data segment idata

public VershSteka, buferKlav

;Определение переменных----------------------------

rseg _data

buferKlav: ds 8

VershSteka:

End

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

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

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

  1. Операторы языка программирования С-51. Операторы присваивания, условные операторы, безусловного перехода, структурный оператор.

  1. Операторы языка программирования С-51. Операторы циклов for, while, do while.

  1. Определение переменных в языке программирования С-51.

  1. Структуры в языке программирования C-51.

  1. Использование подпрограмм в языке программирования С-51.

Определение подпрограмм. Предварительное объявление подпрограмм. Вызов подпрограмм, рекурсивный вызов подпрограмм. Подпрограммы обработки прерываний в языке программирования С-51. Области действия переменных и подпрограмм

  • В отличие от других языков программирования высокого уровня в языке С нет деления на основную программу, процедуры и функции. В этом языке вся программа строится только из функций. .

  • Функция - это совокупность объявлений и операторов, обычно предназначенная для решения определенной задачи. Термин функция в языке программирования С эквивалентен понятию подпрограммы.

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

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

Определение подпрограмм

  • Определение функции записывается в следующем виде:

  • [спецификатор класса памяти] [спецификатор типа] имя функции ([список формальных параметров]) //Заголовок функции

  • { //тело функции

  • }

  • Заголовок функции задает тип возвращаемого значения, имя функции, типы и число формальных параметров.

  • Тело функции - это составной оператор, содержащий операторы, определяющие действие функции. Тело функции начинается с фигурной скобки '{' и состоит из объявления переменных и исполняемых операторов. Именно эти операторы, входящие в тело функции, и определяют действие функции. Завершается тело функции закрывающей фигурной скобкой '}'.

  • Пример определения функции:

  • bit SostKnIzm(void)//Заголовок функции

  • {//---------------начало тела функции--------------

  • bit tmp=0;

  • if(P0!=0xff)tmp=1;

  • return tmp;

  • }//---------------конец тела функции-----------------

  • //================== Вызывающая подпрограмма ==========

  • ...

  • if(SostKnIzm()) //Вызов подпрограммы SostKnIzm

  • DecodSostKn();

В приведенном примере показано как при помощи функции, возвращающей битовую переменную можно повысить наглядность исходного текста программы. Оператор if(SostKnIzm()) DecodSostKn(); практически не требует комментариев. Имя функции SostKnIzm показывает что контролирует эта функция.

Необязательный спецификатор класса памяти задает класс памяти функции, который может быть static или extern.

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

  • Использование спецификатора класса памяти extern используется для связывания подпрограмм, находящихся в других модулях (и возможно написанных на других языках программирования) с вызовом подпрограммы из данного программного модуля

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

  • Функция не может возвращать массив или функцию, но может возвращать указатель на любой тип, в том числе и на массив и на функцию. Тип возвращаемого значения, задаваемый в определении функции, должен соответствовать типу в объявлении этой функции.

  • Функция возвращает значение, если ее выполнение заканчивается оператором return, содержащим некоторое выражение. Указанное выражение вычисляется, преобразуется, если необходимо, к типу возвращаемого значения и возвращается в точку вызова функции в качестве результата.

Пример определения подпрограммы-функции:

  • #include <reg51.h> //Подключить описания внутренних регистров микроконтроллера

  • char getkey () //Заголовок функции, возвращающей байт, принятый по последовательному порту

  • {while (!RI); //Если последовательный порт принял байт,

  • RI = 0; //то подготовиться к приёму следующего байта

  • return (SBUF); //и передать принятый байт в вызывающую подпрограмму.

  • }

  • В операторе return возвращаемое значение может записываться как в скобках, так и без них.

Параметры подпрограмм.

  1. Список формальных параметров - это последовательность объявлений формальных параметров, разделенная запятыми. Формальные параметры - это переменные, используемые внутри тела функции и получающие значение при вызове функции путем копирования в них значений соответствующих фактических параметров.

  2. Пример определения функции с одним параметром:

  • int rus (unsigned char r) //Заголовок функции

  • {//---------------начало тела функции--------------

  • if (r>='А' && c<=' ')

  • return 1;

  • else

  • return 0;

  • }//---------------конец тела функции-----------------

  • В данном примере определена функция с именем rus, имеющая один параметр с именем r и типом unsigned char. Функция возвращает целое значение, равное 1, если параметр функции является буквой русского алфавита, или 0 в противном случае.

\ Подпрограммы обработки прерываний.

Атрибут INTERRUPT позволяет объявить подпрограмму-процедуру обработки сигналов прерываний, поступающих от внешних устройств. Подпрограмма процедура с этим атрибутом вызывается при получении микроконтроллером соответствующего сигнала прерывания. Подпрограмма обработки прерываний не может быть подпрограммой функцией и не может иметь переменные-параметры. Формат использования атрибута:

interrupt N;

где N-любое десятичное число от 0 до 31.

Число N определяет номер обрабатываемого прерывания. При этом номер 0 соответствует внешнему прерыванию от ножки INT0, номер 1 соответствует прерыванию от таймера 0, номер 2 соответствует внешнему прерыванию от ножки INT1 и так далее. Пример подпрограммы-обработчика прерывания от таймера 0:

void IntTim0(void) interrupt 2

{TH0=25; TL0=32; //Задать новый интервал времени таймера T0

TF=0; //Сбросить флаг таймера T0 для разрешения следующего прерывания от данного таймера

}

При работе с прерываниями определяющим фактором является время реакции на прерывание. Для того, чтобы не сохранять содержимое используемых регистров микроконтроллера в стеке, в микроконтроллерах предусмотрено использование отдельных регистровых банков. В языке программирования С-51 для этого необходимо в объявлении подпрограммы указать используемый ею банк регистров. Для этого служить атрибут using:

void IntTim0(void) interrupt 2 using 1

{TH0=25; TL0=32; //Задать новый интервал времени таймера T0

TF=0; //Сбросить флаг таймера T0 для разрешения следующего прерывания от данного таймера

}

Многомодульные программы*.

Язык программирования C-51 позволяет писать многомодульные программы.

Оттранслированный программный модуль сохраняется в виде отдельного файла в объектном формате, где кроме машинных команд сохраняется информация о именах переменных, адресах команд, требующих модификации при объединении модулей в единую программу и отладочная информация.

Раздельная трансляция программы возможна при использовании двух программ: транслятора исходного текста программы c-51 и редактора связей bl-51.

При программировании на языке С раздельная трансляция не вызывает каких либо проблем. Однако если при компиляции исходного текста программы транслятор обнаружит переменную, которая не была заранее объявлена, то будет сформировано сообщение об ошибке и объектный модуль будет стёрт с диска компьютера.

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

declare

RejRab byte external,

UrovGr byte external,

NomKan word external,

Sost bit external,

Soob bit external;

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

Все используемые подпрограммы тоже должны быть предварительно объявлены. При использовании подпрограмм из других модулей они должны быть объявлены как внешние. При этом должны быть полностью объявлены все параметры подпрограмм. Пример объявления внешних подпрограмм на языке программирования PLM-51:

TestOZU: procedure byte external;

end TestOZU;

Rd558: procedure (AdrRAM,NachAdr,Nbyte) byte external;

var (AdrRAM,NachAdr,Nbyte )byte;

end Rd558;

Wr558: procedure (AdrRAM,NachAdr,Nbyte) byte external;

var (AdrRAM,NachAdr,Nbyte )byte;

end Wr558;

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

Переменные, к которым можно обращаться из других модулей, тоже должны быть объявлены с атрибутом PUBLIC.

Программа rl-51 объединяет несколько объектных файлов (модулей) в один. Для объединения нескольких модулей в исполняемую программу имена всех модулей передаются в редактор связей в качестве параметров при запуске этой программы. Пример вызова редактора связей из командной строки DOS для объединения трёх модулей:

rl51.exe progr.obj, modul1.obj, modul2.obj

В результате работы редактора связей в этом примере будет создан исполняемый модуль с именем progr.

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

Наименьшая вероятность ошибиться при описании переменных и подпрограмм у программиста, который писал исходный текст модуля, к подпрограммам и переменным которого нужно обращаться из других модулей. Поэтому правила хорошего тона предполагают, что этот программист будет поставлять не только объектный модуль, но и файл описания своих переменных с атрибутом EXTERNAL. Такие файлы называются файлами заголовками и обычно записываются с расширением *.h.

Естественно, так как процесс трансляции разбит на два этапа, то ошибки могут возникать не только на этапе трансляции модулей, но и при связывании модулей в исполняемую программу. Наиболее распространённые ошибки - это забыть включить имя объектного модуля в строку вызова редактора связей, забыть объявить переменную или подпрограмму как PUBLIC или использовать одни и те же адреса для переменных или констант в различных модулях. Сообщения об этих ошибках выводятся в файл с расширением *.m51

  1. Принцип построения многопроцессорных систем на основе микроконтроллеров МК-51.+

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

IP-ядро Core8051 процессора имеет интерфейс для подключения к шине AMBA APB. Эта периферийная шина поддерживает только одного мастера на шине. Поэтому построение многопроцессорных систем на шине АРВ невозможно. Шина AHB поддерживает несколько мастеров в системе, но ядро Core8051s не имеет интерфейса к этой шине. Чтобы решить проблему соединения нескольких процессоров 8051s, используется IP-модуль моста для подключения процессора 8051s к шине AHB – Fcore8051s_AHB_Cache. Этот мост обеспечивает процессорам, подключенным к шине AHB, возможность обмена данными друг с другом, а также с общей памятью – через контроллер памяти, подключенный к этой же шине. Модуль Fcore8051s_AHB_Cache реализован на базе двухпортового ОЗУ.

Рассмотрим пример многопроцессорной системы на базе процессоров 8051s с общей памятью программ и дан-ных (рис.3). В подобной системе процессоры являются равнозначными. Процессоры работают асинхронно, но в каждый момент времени доступ на шину АНВ имеет только один процессор. У каждого процессора есть своя периферийная шина АРВ и набор контроллеров, а память программ и данных у процессоров общая.

Рис.3. Пример архитектуры многопроцессорной схемы на базе процессоров 8051

 

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

Развитая высокопроизводительная шина (Advanced High-performance Bus - AHB)

Шина AHB используется в высокопроизводительных системах класса "система-на-кристалле" и соответствует современным требованиям предъявляемым процессом синтеза приборов с уровнем интеграции система-на-кристалле.

MBA шина периферии Развитая шина периферии (Advanced Peripheral Bus - APB)

AMBA шина периферии предназначена для организации интерфейса с встроенными периферийными устройствами общего назначения, такими как таймеры, контроллеры прерываний, UART, порты I/O и т.п., и дополнительными периферийными устройствами. С основной системной шиной шина периферии соединяется мостом, обеспечивающим разгрузку системной шины и снижающим общее потребление системы.

В соответствии с новой спецификацией AMBA Rev 2.0 Specification шина отвечает современным требованиям последовательности синтеза приборов класса "система-на-кристалле".