пятница, 21 июня 2013 г.

Второй урок. Простой код на ассемблере и устройство вкратце. (устаревшее MPLAB 8.91)


<< Назад к оглавлению

Внимание! статья несколько устарела. Теперь будет рассматриваться работа с более современной средой MPLABX


В данном тексте приведены ссылки на книги. "название книги":страница обозначает указатель на определенную страницу книги. "название книги":Гглава - главу. При этом ТО - сокращение для тех. описания контроллера (Datasheet). Например ТО:15 - 15 страница технического описания. ТО:Г3 - третья глава технического описания
 

Пакет MPLAB 8.91. Можно скачать с официального сайта. Новый MPLABX довольно неповоротливый. Можно скачать здесь. Зеркало


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

Итак, что такое контроллер, и как он работает?
Конечно же, это просто черный жучек с ножками. За неимением никаких других членов, он общается с окружающим миром исключительно напряжением на ножках. Что в общем и демонстрировалось в программе в первом уроке. Просто с определенной переодичностью контроллер зажигал
светодиодик.
В расcматриваемых нами контроллерах память разделена. Программа записывается в отдельное пространство, именуемое памятью программы (PROGRAM MEMORY). Переменные и настройки хранятся в памяти данных (DATA MEMORY). Причем, ячейки памяти, выделенные для использования как переменные называются регистрами общего назначения (GENERAL PURPOSE REGISTERS или GPR) и настройки находятся в регистрах специального назначения (SPECIAL FUNCTIONS REGISTERS или SFR). Память данных поделена на 15 блоков и блоки меняются регистром BSR (BLOCK SELECT REGISTER).
Так же существует EEPROM memory - это флеш память, используемая для длительного хранения информации.
Подробнее о памяти контроллера смотри главу 1 ссылка.

Код программы


Для начала мы будем писать на ассемблере.
Если вы написали команду на ассемблере, то это будет ровно одна команда, записанная в контроллер.
Таким образом вы будете отлично знать, что ваш контроллер делает и как. А вот если вы пишете на C, то на каждую строчку, написанную вами могут приходиться сотни команд, выполненных контроллером. Знать-то нужно и то и другое, но ассемблер даст нам понимание того, что и как работает в контроллере.

Ладно, начнем.

Открываем MPLAB жмем project->project wizard,

 выбираем модель контроллера, и в качестве среды - MPASM Toolsuite
Далее. Щелкаем browse. указываем там папку проекта и имя. Никаких файлов пока что не добавляем. Next и finish.
File->new.
Сохраняем его в папку проекта с расширением asm.
Далее щелкаем правой на папке sources и добавляем его в проект..

Переписываем туда программу. Цифирки слева следует убрать. Вот код нашей первой программы:

Листинг source.asm


  #include <p18f2550.inc> ;подключение заголовков
list p=18f2550 ; выбор контроллера
CONFIG FOSC=INTOSCIO_EC ; Выбран внутренний генератор
  CONFIG MCLRE = OFF ; отключаем сигнал сброса
  CONFIG WDT   = OFF ; отключаем сторожевой таймер

DELAYCOUNTER EQU 0x00  ; задаем две переменные для создания задержки (паузы)
DELAYCOUNTER1 EQU 0x01; в программе. Они по адресу 0x00 и 0x01
A EQU 0; под буквой A будем подразумевать, что используется access bank

ORG 0 ; начинаем с 0 адреса памяти программы
  GOTO main ; перейти на метку main
  ORG 28h ; теперь пишем с 28 адреса. (сделано это для работы с прерываниями)
main ;(начинается программа main- просто метка для нашего удобства)


  CLRF BSR,A;       ; - выбираем нулевой блок памяти данных
  CLRF PORTA,A       ; - обнуляем выход на порту а    ;

  CLRF WDTCON,A; выключаем сторожевой таймер
  MOVLW 0x0F       ; записываем 0x0F в аккумулятор
  MOVWF ADCON1,A    ; перебрасываем значение в ADCON1 - настраиваем порт A на цифровой вход/выход
  CLRF TRISA,A ;- настраиваем порт а - только на выход
  
endloop ; это цикл, в который будет без конца гонять наша программа
  BTG LATA,2,A; мигнуть светодиодом 
  CALL delay255; вызвать паузу
  GOTO endloop; вернуться к началу цикла

delay255 ; функция вызова паузы
  SETF DELAYCOUNTER,A; записать 0xFF в счетчик времени
  GOTO delay; перейти к delay
delay 
  SETF DELAYCOUNTER1,A; записать 0xFF во 2й счетчик времени
delaysub1 ;
  DECFSZ DELAYCOUNTER1,F,A; уменьшить 2й счетчик на 1. если >0
  GOTO delaysub1; то вернуться на шаг назад
  DECFSZ DELAYCOUNTER,F,A; иначе - уменьшить 1й счетчик, если >0
  GOTO delay; вернуться на метку delay
  RETLW 0; иначе - выйти из функции

END ;конец программы

Для контроллера pic18f2550
https://yadi.sk/d/1YkpyyJTVLg2V
Для контроллера pic18f4550
https://yadi.sk/d/FxMGleO_VLgp7 - к сожалению не могу сейчас проверить
для копиляции щелкаем project->make или project->build all (F10)
Программа вас спросит. какие у нас настройки, переносимые, или абсолютные. Щелкаем абсолютные. Переносимые - это для того, чтобы нашу программу можно было запускать на разных устройствах. Еще нужен будет линковщик.
после компиляции у нас должен в папке проекта появиться HEX файл. Его можно и нужно прошить в контроллер. Это та же программа, что и в уроке 1.

Пояснения к коду программы



Начнем потихоньку разбирать что там написано

В самом верху указываем то, какой у нас будет контроллер
#include <pic18f2550.inc>
Мы их рлдключаем для того. чтобы вместо того, чтобы всегда и везде мы записывали цифрами. мы могли использовать некоторые уже привычные нам обозначения.
напирмер, без подключения заголовков. команда записи в регистр выбора блока (BSR) -строка 16 нашей программы выглядела бы так
MOVWF 0FE0;

так... Еще директива. 
list p=18f2550
Она просто говорит
компилятору, какой контроллер будем прошивать. 

Дальше уже интереснее. Нам нужно задать управляющее слово. это - настройки контроллера. 
Задает их директива CONFIG 
По поводу всех настроек контроллера обращаемся так же к техническому описанию. ТО:288


Конфигурационные биты


CONFIG FOSC=INTOSCIO_EC
Эта настройка говорит о том, что мы будем использовать внутренний генератор импульсов. Он - внутри контроллера. Читаем в ТО:25

CONFIG MCLRE = OFF
Здесь мы отключаем сигнал сброса. То есть контроллер будет включаться сразу с подачей на него питания.

CONFIG WDT = OFF
Отключаем сторожевой таймер. Просто. чтобы не "запариваться". Он служит защитой от зависания контроллера. Читаем в ТО:299

Более подробно конфигурационные биты рассмотрены во 2-й главе к этому уроку. ссылка

Тело программы


DELAYCOUNTER EQU 0x00
Эта директива (EQU) ставит в соответствие к DELAYCOUNTER 0x00
То есть мы пишем DELAYCOUNTER, а программа думает "0x00"
Вообще мы будем использовать DELAYCOUNTER как переменную. а 0x00 - просто адрес, где она хранится в общих регистрах.
Кстати. Забыл сказать. 0x00 - это просто число. Так мы записываем числа в 16ричной системе счисления.
то есть 0x6B = 107

Мы используем для нашей программы память, входящую в access RAM, поэтому мы вольны использовать ячейки памяти от 0x00 до 0x5F. А ячейки от 0x60 до 0xFF - это регистры общего назначения.

ORG 0
Этим мы указываем компилятору, чтобы он писал все последующие команды последовательно с адреса 0.
GOTO main
ORG 28h
main
Переходим на метку main. И начиная с 0x28 адреса пишем программу дальше. Метка main - адрес 0x28
Обратите внимание, мы оставили свободное место между адресом программы 0x1 и 0x28. Зачем? Если мы будем в последствии использовать прерывания, то в случае. если прерывание будет требовать на время приостановить программу. оно начнет выполнять команды по адресу 0x8 или 0x18. и это место нужно будет заполнить программой обработки прерывания.

Все последующие команды смотри в главе 3. Команды ассемблера. ссылка

MOVWF ADCON1
Когда мы записываем значение в регистр ADCON1. мы меняем настройки АЦП. По поводу 
использования встроенных устройств контроллера смотри главу 4. ссылка


Пожалуйста, помогите сделать статью лучше. Увидели непонятность, неточность или  ошибку, сообщите в комментарии, или напишите мне. Спасибо. Jasuramme@mail.ru

2 комментария: