Введение в программирование микроконтроллеров Scenix SX

Глава 1. Вводная часть.

Начнем

Если Вы не на ты с компьютерным железом, это может показаться черной магией. Как могут маленькие микросхемки выполнять задачи практически любой сложности. Однако микроконтроллер работает очень просто. Эта простота значит, что ты - программист - должен очень постараться, чтобы создать эти сложные устройства. Для программирования необходимо логическое мышление и внимание к деталям.

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

В микроконтроллерах Scenix SX используется гарвардская архитектура. Это значит, что инструкции и данные хранятся в разных областях памяти. Такая архитектура обычна для контроллеров (хотя многие компьютеры используют архитектуру Фон Неймана, в которой данные и инструкции хранятся вместе).

Предположим, у Вас новая работа на заводе, производящем радиоприемники. Начальник дает Вам следующие инструкции:

  1. Положить пустую коробку перед началом конвейерной линии.
  2. Включить большой красный тумблер для запуска конвейерной линии.
  3. Ждать готовых радиоприемников сходящих с конвейера, и упаковывать их в коробку. После каждого радио нажимать на счетчик.
  4. Если счетчик больше 10, Выключить тумблер для остановки конвейера.
  5. Заполненную коробку отодвинуть, а на ее место поставить пустую.
  6. Сбросить счетчик.
  7. Перейти к шагу 2

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

Проблема 1

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

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

Самый распространенный способ программирования микроконтроллеров - использование языка "ассемблер". Это самый короткий путь, при котором краткое название инструкции преобразуется в нули и единицы. Вы можете использовать такие инструкции, как ADD (прибавить) или JMP (jump, переход). В старые времена Вы бы вручную переводили такие инструкции в единицы и нули. Теперь существуют программы, называемые ассемблерами, которые делают это преобразование за вас. Еще это называется кросс-ассемблированием - использованием компьютера для ассемблирования (преобразования названий инструкций в единицы и нули) кода другого компьютера. Краткие названия инструкций называются мнемоникой.

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

Зачем программировать на ассемблере, если для микроконтроллеров доступны Бэйсик и Си? Ответ - эффективность. Микроконтроллеры имеют ограниченный объем памяти программ. К тому же вам необходимо, чтобы все работало как можно быстрее. Программа составленная на языке высокого уровня будет требовать гораздо больше памяти, чем хорошо составленная программа на ассемблере. И работать она будет гораздо медленнее.

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

Проблема 2

Что делать с единицами и нулями после того как они получены. Каким-то образом мы должны переместить эти единицы и нули в компьютер. Старые микропроцессоры использовали микросхему внешней памяти, а современные процессоры содержат память внутри себя. Эту память Вы программируете специальным устройством, известным как программатор. Некоторые микроконтроллеры необходимо облучать ультрафиолетовой лампой для очистки памяти, а микроконтроллеры SX можно перепрограммировать сразу же, поэтому не нужно ждать пока специальная лампа очистит память.

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

Выбираем язык

В этом курсе для программирования SX мы будем использовать ассемблер. Однако, если Вы хорошо знаете Бэйсик или Си, Вы найдете дополнительные примеры на этих языках, что поможет вам понять ассемблер.


Рис.1.1. Окно SXKey.

Среда разработки

На рисунке 1.1 изображено главное окно SX-Key. Оно выглядит как окно обычного текстового редактора. Вы можете вводить код на ассемблере в окно. Когда Вы захотите проверить или выполнить свою программу, используйте меню 'Run'. Для проверки кода на простые ошибки, выберите команду меню Run|Assemble. Также можно выполнить программу выбрав команду меню Run|Run (если микроконтроллер подсоединен к аппаратному обеспечению SX-Key).

Примечание: Команды ассемблера проверяются только на синтаксические ошибки. Логические ошибки Вы должны найти сами (с помощью отладчика).

То ли это?

Настоящая мощь SX-Key не в набирании кода. Впечатляющая часть начинается когда ваш код не работает. Тогда вы можете использовать команду Run|Debug.

Отладчик (debugger) (см. рисунок I.2) позволяет вам смотреть выполнение вашей программы SX-ом по одному шагу и изучать его внутреннее устройство. Если вы используете SX-Blitz, вы можете только программировать. SX – Blitz не поддерживает отладку.

Цикл разработки

Как вы могли представить, такие мощные инструментальные средства очень упрощают программирование. Однако вам все еще нужен план. Вот одно старое высказывание: «Люди не планируют провал, они проваливают план». Это особенно верно в программировании.

Выше вы читали, что программы считывают вход, обрабатывают считанное и производят вывод. Это не плохое место для начала при разработке вашего программного обеспечения. Комплексные проекты могут требовать более стогую методику разработки, но во многих случаях этот простой подход достаточен. Тем не менее, вблизи каждой программы (главным образом для микроконтроллеров) будем следовать этой модели. Определение ваших входов, выходов и обработки – это приличный первый шаг по направлению к осуществлению вашей разработки.

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

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

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

Системы счисления

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

Двоичное число состоит из битов (разрядов). Правый бит имеет значимость 1. Каждый следующий бит (с права налево) имеет вдвое большую значимость, чем предыдущий:

Значимость 128 64 32 16 8 4 2 1
Бит 7 6 5 4 3 2 1 0
Двоичное число 0 0 0 1 0 1 1 0

Переведем двоичное 10110 в десятичное число. Для этого нужно просто сложить значимости битов, равных единице: 2+4+16=22.

И наоборот, из десятичной системы в двоичную. Для этого отнимаем от числа самую большую значимость, которая меньше или равна десятичному числу. Бит с этой значимостью установим в единицу. Повторяем эту процедуру, пока десятичное число не станет равным 0. Пример:

22-16=6, бит 4 = 1.
6-4=2, бит 2 = 1.
2-2=0, бит 1 = 1.
Результат: 10110.

Когда Вы говорите 138 (десятичных), Вы подразумеваете:

1х100+3х10+8х1

Диапазон десятичных цифр от 0 до 9.

Другие основания систем счисления

Так как почти все люди используют десятичную систему, вы временами должны ее использовать. Но во много раз проще использовать другие системы счисления, которые проще преобразовывать в двоичную систему. Наиболее распространенное альтернативное основание – 16, или шестнадцатеричная система.

Шестнадцатеричная система использует 16 цифр – от 0 до 9 и от A до F. Вы можете найти значения в таблице I.1. Обратите внимание, что для преобразования между двоичным и шестнадцатеричным видами числа вы можете просто использовать таблицу. Например, шестнадцатеричное F3 будет двоичным 11110011.

В шестнадцатеричной системе каждая цифра имеет значимость в шестнадцать раз больше, чем предыдущая. Поэтому F3 будет:

15*16+3*1=243

А 64 шестнадцатеричных будет:

6*16+4*1=100.

Шестнадц.Десятичн.Двоичные
000000
110001
220010
330011
440100
550101
660110
770111
881000
991001
A101010
B111011
C121100
D131101
E141110
F151111

Совет: Многие калькуляторы, включая программу CALC в Windows, могут преобразовывать системы счисления автоматически.

Что это за число?

С этими разными системами можно запутаться. Ассемблер SX-Key не может магически угадывать, какую систему вы используете. Поэтому необходимо пояснять, в какой системе записано число.

Для определения используемой системы числу нужен специальный префикс. Числа, начинающиеся на $ - это шестнадцатеричные числа. Двоичные числа начинаются с символа %. Основной системой счисления является десятичная, поэтому в ней числа можно записывать без префикса.

Примечание: Не все ассемблеры используют такое соглашение. Например некоторые ассемблеры для определения типа числа используют суффиксы. Другие используют свои префиксы.

Размер числа

Сколько требуется бит для хранения числа? В SX одно слово данных занимает 8 бит. Эта единица также называется байтом. Проблема в том, что байт может содержать число только от 0 до 255. Что делать, если Вам необходимо работать с большими числами? Или с отрицательными? В этом случае придется воспользоваться специальной методикой, обсуждаемой в главе 6.

Помните при преобразовании, биты нумеруются с права налево. Правый бит имеет номер 0. Левый бит - 7. Бит 7 является восьмым битом потому, что счет ведется с нуля.

Между прочим, хотя в SX данные 8-битные, инструкции у него 12-битные. Поскольку Гарвардская архитектура разделяет код и данные, то это не проблема.

Подключение железа

Разумеется, наша конечная цель - программирование микроконтроллера SX.

Процессор SX особенно быстрый. Он может работать на скоростях до 100 МГц и выполнять почти все инструкции за один цикл (10 нс на инструкцию). В реальном проекте Вы должны использовать кварцевый или керамический резонатор с частотой не менее 4 МГц. В SX-Key возможно управление частотой генератора (меню Run|Clock).

SX выпускается в 18-выводном корпусе и 28-выводном варианте. 18-выводное устройство имеет 12 линий ввода/вывода, 28-выводное - 20 линий ввода/вывода. Обе микросхемы имеют 2K памяти программ, и около 136 байтов памяти данных. Существует еще 20-выводный контроллер в корпусе для поверхностного монтажа. Он аналогичен 18-выводному устройству. Когда Вы записываете 1 в выход, на нем появляется 5В. Если вы запишете 0 в этот вывод, он выведет 0В. При вводе, напряжение на входе выше порога (около 1.4В) читается как 1, а ниже порога - как 0. Вы можете настраивать любую линию ввода/вывода как вход или как выход прямо во время выполнения программы.

Выбор комплектующих будет часто зависеть от требуемого количества линий ввода/вывода. Например, если Вы хотите использовать 4 вывода для управления ЖК-индикатором и 8 выводов для подключения клавиатуры, подойдет и 18-выводный SX, но выводов для чего-либо еще не останется.

Глава 2. Ваша первая программа.

Теперь Вы вероятно готовы начать проект. У вас должен быть компьютер с программой SX-Key, программатор и экспериментальная плата с микроконтроллером SX. По крайней мере к двум выводам подключим по светодиоду (рис.2.1). Если вы усердны, подключите 8 светодиодов к порту B (на вывод по светодиоду). Можно сэкономить время, используя светодиоды со встроенными ограничительными резисторами. Тогда внешний резистор не понадобится. Светодиод загорится, когда на его линию будет выведен 0.



Для начала наберем программу в редакторе SX-Key, перекачаем ее в процессор SX, и запустим его.

Первый шаг.

Если вы еще не установили программное обеспечение "SX-Key", сделайте это сейчас. Вначале окно будет чистым; в него вы можете набрать (загрузить с диска) свою программу.

Что вводить? Это проблема! Пока-что введите простую программу, расположенную ниже по тексту. Помните что каждая строка (кроме содержащей start_point) начинается с табуляции. Это обычное дело в ассемблере - метки в первом столбце, команды правее на одну табуляцию.

            device pic16c55,oscxt5
            device turbo,stackx_optionx
            reset  start_point
            freq   50000000 ; 50 мГц.

            org 0

start_point mov    !rb,#0   ; Линии порта b делаем выходами.
            mov    rb,#0    ; Выводим на все выходы 0.
            sleep           ; Засыпаем.

По умолчанию SX-Key не чувствителен к регистру, но вы можете изменить это.

Во время ввода полезно время от времени сохранять вашу программу. Если виндоус заглючит, вы будете счастливы что сохранились. Безусловно вам необходимо сохранять работу перед запуском кода в SX.

Когда вы закончите вводить программу, выберите меню Run|Assemble. Если вы ввели все безошибочно, то увидите в строке состояния надпись "Assembly Successful". Иначе вы увидите ошибку, а курсор переместится на строку, содержащую ошибку. Исправьте ошибку и попробуйте еще раз.

Загружай.

Как только ваша программа ассемблируется без ошибок, вы сможете загрузить ее в микросхему SX. Наиболее очевидный способ сделать это - использовать команду меню Run|Program. Эта команда ассемблирует программу снова, и если ошибок нет, загружает машинный код в микросхему SX (при наличии соответствующего аппаратного обеспечения).

При запуске микросхемы подключенные к порту B светодиоды включатся. Не впечатляет конечно, но это только начало. Теперь вы знаете, что ваша схема работает и ваша программа составлена правильно.

Если вы понимаете что делает программа, вас сильно удивит следующее: почему светодиоды горят, если на выводах ноль? Такое управление может показаться неинтуитивным, но на практике используется часто. Хотя SX может быть как приемником, так и источником значительного тока, многие микросхемы могут принимать больше, чем выдавать. Из-за этого разработчики часто подсоединяют светодиоды и другие нагрузки так, чтобы они включались при логическом уровне НОЛЬ.

Ну и чево?

На первый взгляд не выразительно. Добавьте строку кода над командой "sleep":

            mov    rb,#$AA  ; Делаем каждый второй выход равным 1.

Когда вы запустите новую программу, вы увидите: некоторые светодиоды светятся, а некоторые нет. Так и должно работать? Сперва программа зажигает все светодиоды. Затем некоторые из них отключает. Почему вы не видите момент, когда включены все светодиоды, до того как половина из них выключится? Ответом будет время выполнения инструкции в чипе SX: 20 наносекунд! Даже самый зоркий глаз не заметит включения светодиодов на 20 нс.

Однако если выполнять инструкции по одной, можно увидеть всё. Пошаговое выполнение - одна из возможностей отладчика. До того, как вы погрузились в отладчик, давайте взглянем на то что происходит внутри этой простой программы.

Внутри программы.

Самый простейший способ понять что эта программа делает - исследовать каждую строку. Заодно вы увидите некоторые ключевые понятия, с которыми будете иметь дело в каждой программе. Первые две строки начинаются с ключевого слова device. Это не инструкция SX. Это директива ассемблера. Большинство ключевых слов имеют эквивалентное значение в машинном языке. Тем не менее директивы не не создают машинный код, они просто дают инструкции ассемблеру. В этом случае мы даем ассемблеру понять, что мы пишем программу, в котой SX должен настроить себя так, чтобы выглядеть как PIC16C55 (более старый процессор) с поддержкой очень быстрого генератора (oscxt5). Вторая строка говорит ассемблеру, что мы хотим использовать несколько специальных режимов, которые поддерживает SX. Ассемблер будет использовать эту информацию для "прожигания" конфигурации SX. Память конфигурации управляет установками железа и не является частью основной программы. Обычно у вас появляется желание поменять директиву pic16c55 на sx28l (для 28-выводных устройств) или sx18l (для 18-выводных микросхем). Однако, пока не научились работать с банками, лучше потерпеть эмуляцию 16c55.

Следующая строка содержит директиву reset. Она информирует ассемблер о том, с какого места запустится программа. Вы можете подумать, что логично запускать программу с начала, но в дальнейшем вы увидите что так делается не всегда. Имя start_point после директивы является созданной вами меткой. Эта метка определяет место в программе и может быть любой.

Примечание: Метки и другие идентификаторы могут содержать до 32 символов. Первый символ должен быть буквой или символом подчеркивания. Другие символы могут быть буквами, символами подчеркивания, и цифрами. В качестве идентификаторов нельзя использовать зарезервированные слова (например sleep и reset).

Следующая строка определяет частоту тактирования в Герцах. Это не влияет на чип SX, но зато помогает отладчику определить используемую вами частоту. Если вы не используете эту директиву, то по умолчанию частота равна 50 МГц. Вы также можете поменять частоту используя меню Run|Clock. Ассемблер допускает использование подчеркивания в любом числе для удобочитаемости (например freq 50_000_000).

Следующая строка содержит последнюю директиву, org. Эта директива приказывает ассемблеру генерировать код начиная с конкретного адреса. Если вы хотите начать с нуля, то напишите org 0.

Следующие три строки (четыре, если вы добавили строку, выключающую часть светодиодов) являются реальной программой. Первая строка программы начинается с метки start_point. Это то место, на которое ссылается директива reset. Помните, что метка должна идти первой в строке. Далее в строке может располагаться инструкция.

Регистры.

Память данных SX состоит из небольшого количества регистров, каждый размером с байт. Несмотря на то, что в SX имеется более 100 регистов, ваша программа может работать сразу лишь с 32 из них. В следующей главе вы научитесь переключать банки регистров, что позволит работать со всеми регистрами, однако сейчас будем считать, что имеется только 32 регистра. Регистры с адресами от $08 по $1F доступны для хранения ваших данных. Регистры от $00 по $07 - специальные, они управляют микросхемой SX во время работы вашей программы.

Например, регистр $05 соответствует порту A. Когда вы читаете значение из регистра $05 (обозначаемого в ассемблере как регистр ra), вы считываете цифровые сигналы, присутствующие на входных выводах порта A. Если вы записываете в регистр ra число, вы защелкиваете биты этого числа в выходных линиях порта A.

Вы также можете использовать $06 (rb) или $07 (rc). Для 18-выводного устройства (которое не имеет порта C) вы можете использовать регистр $07 для хранения данных.

Напрашивается следующая проблема: Откуда вы знаете какие выводы - входы, а какие - выходы. Сначала все выходы установлены на вход. Ваша программа может изменить направление выводов в любое время с помощью записи специального значения в регистр направления порта. Для доступа к этому регистру вы пишете восклицательный знак перед именем регистра. Запись бита со значением 0 в регистр направления делает соответствующий бит выходом. Запись бита со значением 1 делает его входом.

Следующие три строки программы. Первая строка использует инструкцию mov (move, перемещать). Эта инструкция перемещает ноль в регистр направления порта B (!RB). Заметьте, что 0 имеет символ # впереди себя. Это означает, что число является константой. Без решетки (#) инструкция переместит содержимое регистра 0 в !rb. Вы можете указать префикс (или суффикс) после #, например #$FF - шестнадцатеричная константа, а #%1011 - двоичная константа.

Вторая строка использует ту же инструкцию, однако теперь регистр назначения - rb вместо !rb. Это означает вывод данных в порт. Так как все выводы являются выходами (после предыдущей команды), каждый вывод будет иметь уровень 0 Вольт. Это заставляет светодиод гореть.

Если вы добавили еще одну строку кода, она записывает $AA в порт. Это то же самое, что и %10101010, то есть чередует горящие светодиоды. Последняя строка, sleep, переводит процессор в режим пониженного потребления электроэнергии (режим спячки). Обычно режим спячки используется не так. Большинство микроконтроллеров не останавливаются абсолютно. Далее вы увидите, что использовать режим спячки удобно в ожидании какого-нибудь внешнего события или окончания временного периода, которые разбудят процессор. В нашей программе процессор засыпает навсегда - что-то навроде выключения микроконтроллера.

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

Совет: Другое применение комментариев - временное удаление строки из вашей программы. Просто поместите точку с запятой в начало строки, которую хотите "удалить", затем вы можете восстановить ее удалением точки с запятой.

Если вы программируете на PBasic, то программа будет в таком стиле:

DIRL = $FF
OUTL = $00
END

Заметьте, что PBasic использует регистр направления также как SX. Однако значение битов противоположное. В программе Basic Stamp бит направления содержащий 0 устанавливает вывод на вход, а 1 устанавливает на выход.

-------------



Hosted by uCoz