Встраиваемые системы. Проектирование приложений на микроконтроллерах семейства 68HC12/HCS12 с применением языка С
Шрифт:
Каждый регистр специальных функций имеет свой собственный адрес в карте памяти МК. При программировании на ассемблере изменение значений регистров специальных функций и считывание их состояния может быть произведено командами загрузки и пересылки данных, такими как LDAA, STAA, MOV, а также командами битовых операций BSET, BCLR. Для того чтобы избавить программиста от запоминания физических адресов регистров специальных функций, следует использовать псевдокоманду операции присваивания EQU языка Ассемблер. Эта псевдокоманда назначит символьному имени регистра, которое одинаково для всех моделей МК семейства 68HC12/HCS12, абсолютный адрес. И при записи исходного текста программы можно
При написании программы на Си с последующим использованием пакета ICC12 компании ImageCraft (см. гл. 3) для этих же целей следует использовать оператор присваивания «=». При программировании на Си установление соответствия между символьными именами регистров специальных функций и их абсолютными адресами в памяти МК наиболее часто производится с использованием директивы препроцессора #define. Для того чтобы освободить программиста от непроизводительного труда, каждая интегрированная среда разработки ПО для МК снабжена файлами заголовков (header file), которые содержат в себе полный набор директив #define для всех регистров специальных функций конкретной модели микроконтроллера. Этот файл включается в исходный текст прикладной программы директивой «include». После этого программист может обращаться к любому регистру специальных функций МК, называя символьное имя регистра. Более того, некоторые заголовочные файлы содержат определения для наиболее часто употребимых битов в составе регистров специальных функций МК, что позволяет устанавливать и сбрасывать эти биты в ходе программы, также используя их символьные имена. Применяя заголовочные файлы при программировании, необходимо помнить, что используемое в тексте программы символьное имя какого либо регистра должно в точности совпадать с именем, назначенным для него в заголовочном файле. Однако последнее не всегда совпадает с именем, приведенном в техническом описании МК.
Рассмотрим пример записи в заголовочном файле:
Разберем, что означает эта запись. Как было отмечено в гл. 3, директива #define используется препроцессором компилятора языка Си для присвоения численных значений символьным константам программы, или, как в нашем случае, определения абсолютного адреса для ячейки памяти или регистра с названным именем. После записи приведенной выше строки препроцессор будет заменять имя ATDCTL2 на указанное в директиве абсолютное значение.
Каково это значение? Оно определено в круглых скобках как сумма символьной константы IO_BASE и шестнадцатеричного числа 0x62. Константа IO_BASE — это начальный адрес блока регистров специальных функций в выбранной модели МК. Для МК B32 начальный адрес блока регистров равен 0x0000. Тогда адрес регистра ATDCTL2 будет равен 0x0062. Использованная форма записи адреса (IO_BASE + 0x62) не случайна, поскольку аппаратные средства 68HC12 позволяют программно изменять начальный адрес блока регистров (см. 4.5.1), сохраняя при этом порядок расположения регистров в памяти.
Каково назначение остальных символов рассматриваемой записи? Переменной ATDCTL2 назначается формат представления данных unsigned char, т.е 8-разрядный без знака. Определение volatile, которое следует за объявление формата, информирует компилятор о том, что изменение значения переменной ATDCTL2 может происходить не только в результате
Пример.
Регистр ATDCTL2, расположенный в памяти МК по адресу 0x0062, управляет работой модуля аналого-цифрового преобразователя ATD. Бит 7 этого регистра разрешает (1) или запрещает (0) работу модуля. Этот бит, обозначенный в техническом описании как ATPU (ATD Powerup Bit), устанавливается в 0 в состоянии сброса МК. Для включения модуля ATD в работу необходимо программно установить этот бит в 1. На языке Ассемблера это действие может быть произведено следующим фрагментом программы:
Первые две строки программы содержат директивы присвоения EQU языка Ассемблер, которые информируют программу о том, что вместо имени ATDCTL2 в кодах программы следует использовать значение $0062, а вместо ATD_INI — $80 или 10000000 в двоичном коде. Команда LDAA использует непосредственную адресацию, в результате ее выполнения число $80 загрузится в аккумулятор ACC. Команда STAA с прямой адресацией пересылает содержимое ACC в ячейку с адресом ATDCTL2. В результате, код в регистре управления ATDCTL2 будет равен 10000000, т.е. установленный в 1 бит 7 вызовет включение модуля АЦП. На языке Си аналогичное действие выполняет следующий программный фрагмент:
Как видите, Вам не пришлось указывать в программе физический адрес регистра ATDCTL2, т.к. он уже определен в заголовочном файле 912b32.h.
4.5.1. Виртуальный адрес блока регистров
Все регистры специальных функций МК семейства 68HC12/HCS12 объединены в блок, который занимает 512 ячеек памяти в адресном пространстве МК. Регистры располагаются в памяти, начиная с некоторого начального адреса, который принято в программном коде обозначать как IO_BASE. Адреса регистров следуют последовательно друг за другом, поэтому адрес каждого регистра можно представить, как (IO_BASE + код смещения). Численное значение кода смещения каждого регистра определено в карте памяти конкретной модели МК в составе семейства 68HC12/HCS12 и может быть получено из технического описания этого МК. Так в примере предыдущего параграфа код смещения регистра ATDCTL2 в составе МК B32 был равен $0062.