Директивы ассемблера, “шапка” программы

“Шапка” программы начинается с подключения специального файла с расширением INC, в виде строчки #include , где include – директива подключения дополнительного файла. Эти файлы для каждого типа микроконтроллера хранятся в папке программы MPLAB. В этих файлах адресам регистров специального назначения присвоены их названия, а также названия битов, это сделано для удобного написания программы. Если этот файл не подключать, то придется вручную присваивать соответствующие названия, иначе MPLAB выдаст ошибки.

Далее идет строчка с указанием типа микроконтроллера в виде директивы LIST p=16F628A. После нее строчка __CONFIG 3F01h ( __CONFIG – директива установки битов конфигурации), здесь двухбайтным шестнадцатеричным числом 3F01h (значение слова конфигурации) настраиваются биты конфигурации микроконтроллера (выбор кварцевого генератора, сторожевой таймер, защита памяти программ и др.). Для лучшей наглядности при настройке битов можно прописать значение слова конфигурации в двоичной форме __CONFIG b’11111100000001′.

Теперь необходимо присвоить названия адресам регистров ОЗУ, которые будут использоваться в программе. Делается это для удобного написания программы. Присвоение название осуществляется директивой equ (определение константы), например, var equ 0020h. Записи var в этом случае будет соответствовать число 0020h, которое является адресом регистра ОЗУ в памяти данных, кстати, в файле P16F628A.INC названия регистрам специального назначения присвоены таким же образом.

Я также использую директиву #define (определение текстовой последовательности для замены), чтобы присвоить названия линиям порта микроконтроллера. Например, строка #define led PORTВ,0 означает что, запись led будет заменяться на PORTB,0. Составляя текст программы не надо везде писать PORTB,0, а пишем просто led.

Все вышесказанное относится к “шапке” программы, после которой следует сам текст программы. Директивой org (определение начального адреса) задают начальный адрес в памяти программ, после которого будет располагаться код программы. Строка org 0000h означает что, код программы расположиться, начиная с 0-го адреса памяти программ. Подпрограмма обработчика прерываний должна располагаться, начиная с адреса 0004h, поэтому в начале подпрограммы необходимо написать строку org 0004h, при этом до этой строки надо написать org 0000h и команду перехода GOTO на основную программу, иначе исполнение основной программы начнется с подпрограммы обработчика прерываний. Если прерывания не задействованы, можно не пользоваться директивой org, программа автоматически расположиться с нулевого адреса памяти программ. Вообще с помощью этой директивы можно расположить требуемый участок кода в любую область памяти программ.

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

Как видно здесь нет ничего сложного, далее остается только написать текст программы.

У этой записи 14 комментариев

  1. Вместо
    Sec equ 0020h ;присвоение названий регистрам ОЗУ
    Sec0 equ 0021h
    Sec1 equ 0022h
    var equ 0023h
    T1L equ 0024h
    T1H equ 0025h
    shet equ 0026h
    W_temp equ 0079h
    STATUS_temp equ 007Ah
    Я пишу всегда вот так.
    Значительно удобнее.
    Ассемблер сам все расставит как нужно.
    ;***** Распределение памяти
    cblock 0x20 ;начало памяти данных
    Sec
    Sec0
    Sec1
    var
    T1L
    T1H
    shet
    W_temp
    STATUS_temp
    ENDC

    1. Немного дополню
      Для контроля количества переменных полезно заканчивать объявление блока таким комментарием:

      ENDC ;—– завершаем объявление переменных Bank0
      ; Итого 42 переменных из 48 возможных

      При добавлении/удалении просто правим цифру и нет необходимости их считать.

  2. Спасибо. С #define, equ и cblock все понятно. Напишите, пожалуйста как заменить серию команд одним макросом. Гугл не дал толкового объяснения.

    1. ;=========================
      ; МАКРОСЫ
      ;=========================
      bank0 macro
      bcf STATUS, RP0
      endm

      bank1 macro
      bsf STATUS, RP0
      endm

      1. Это макросы переключения банков
        Просто пишешь потом
        bank0 или
        bank1
        И все.

        1. Или можно просто использовать встроенные в ассемблер макрокоманды
          Например:
          banksel CURVA – переключение на банк, в котором находится регистр CURVA

  3. Спасибо, Александр.

  4. Лично я не жаблюсь на комменты и внешние файлы, гораздо удобнее разбить большую программу на 20-30-40 мелких файлов и редактировать в многооконном редакторе, чем уныло листать вверх-вниз.
    Вот, например, шапка текущей разработки:

    ; Управление усилителем с аудиопроцессором PT2348
    ; с ЖКИ индикатором 1602
    ; микроконтроллер PIC16F76
    ; Чипы на I2C: DS3231, AT24C16, PT2348
    ; Чипы на UART: ESP8266
    ; 16 МГц
    ;==============================================
    ; Объявляем подключаемые файлы
    ;==============================================
    list p=16F76 ; Определяем тип микроконтроллера
    #include ; Подключаем файл, определяющий параметры и набор РОН
    ;==============================================
    ; Объявляем конфигурацию
    ;==============================================
    ; установка битов конфигурации
    ;_BODEN_OFF & – разрешён сброс по снижению напряжения питания
    ;_CP_OFF & – Биты защиты памяти программ отключены, прочитать записанную программу можно
    ;_PWRTE_ON & – разрешена задержка запуска по включению питания
    ;_WDT_ON & – сторожевой таймер включен
    ;_HS_OSC – HS генератор
    __CONFIG _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_ON & _HS_OSC
    ;==============================================
    ; Объявляем константы
    ;==============================================
    #include ; Подключаем файл с распиновкой
    #include ; Подключаем файл с константами
    ;==============================================
    ; Объявляем макросы
    ;==============================================
    ;==============================================
    ; Объявляем переменные
    ;==============================================
    #include ; Подключаем файл с переменными
    ;==============================================

    1. Почему-то в листинге сожрало всё, что заключено в угловые скобки 🙂
      дополнять не буду, так как в данном случае для понимания это несущественно

  5. Следует избегать записей, как у автора статьи, типа “__CONFIG 3F18h ;установка битов конфигурации”
    Это именно плохой тон, так как такая запись является абсолютно нечитаемой и бесполезной при переносе на другой МК, обычно ею пользуются те, кто всё делает на одном-двух МК типа не к ночи помянутого PIC16F628A.
    Впрочем, ещё раз посмотрел листинг и увидел именно PIC16F628A. И почему я не удивлён?

    1. Добрый день. Пожалуйста, объясните где в программе должен располагается текст макроса, т.е. откуда программа его берет. По возможности, покажите на каком-то реальном примере.

  6. Объясните где в программе должен располагается макрос, т.е. откуда основная программа его берет

Имя (обязательно)Email (обязательно)Веб-сайт

Добавить комментарий