- •Перечень сокращений
- •Предисловие
- •Введение
- •Часть 1. Архитектура и аппаратные средства микроконтроллера LPC214x
- •1.1 Общие сведения о микроконтроллерах LPC214x
- •1.2 Программистская модель процессорного ядра ARM7TDMI
- •1.2.1 Режимы работы ядра ARM7
- •1.2.2 Система регистров
- •1.2.3 Слово состояния программы
- •1.2.4 Организация памяти
- •1.3 Система команд
- •1.3.1 Команды арифметической и логической обработки
- •1.3.2 Команды умножения
- •1.3.3 Команды регистровой пересылки
- •1.3.4 Команды загрузки и сохранения регистров
- •1.3.5 Команды пакетного обмена с памятью
- •1.3.6 Команды передачи управления
- •1.3.7 Команды обращения к слову состояния программы
- •1.4 Методы адресации
- •1.4.1 Непосредственная адресация
- •1.4.2 Регистровая адресация
- •1.4.3 Косвенная адресация
- •1.4.4 Индексная адресация
- •1.5 Процедура начальной загрузки и режимы отображения памяти
- •1.6 Обработка исключительных ситуаций
- •1.7 Система тактирования
- •1.7.1 Выбор тактовой частоты микроконтроллера
- •1.7.2 Настройка тактирования периферийных устройств
- •1.8 Модуль ускорения памяти
- •1.9 Внешние выводы микроконтроллера
- •1.9.1 Служебные контакты
- •1.9.2 Программно-управляемые линии ввода-вывода
- •1.9.3 Альтернативные функции линий ввода вывода
- •1.10 Цифровые порты ввода-вывода
- •1.10.1 Управление портом через низкоскоростную шину
- •1.10.2 Управление портом через высокоскоростную шину
- •1.11 Система прерываний
- •1.11.1 Назначение системы прерываний
- •1.11.2 Процесс обработки прерываний IRQ
- •1.11.3 Процесс обработки быстрых прерываний FIQ
- •1.11.4 Регистры управления системой прерываний
- •1.11.5 Порядок настройки прерывания IRQ
- •1.11.6 Порядок настройки быстрого прерывания FIQ
- •1.11.7 Процедура обработки прерывания
- •1.11.8 Задержка обработки прерывания
- •1.12 Внешние прерывания
- •1.12.1 Регистры управления блоком внешних прерываний
- •1.12.2 Порядок настройки блока внешних прерываний
- •1.13 Таймеры-счетчики
- •1.13.1 Режим таймера и схема совпадения
- •1.13.2 Режим счетчика
- •1.13.3 Схема захвата
- •1.13.4 Управляющие регистры
- •1.13.5 Формирование интервалов времени через систему прерываний
- •1.13.6 Измерение периода и длительности импульса с помощью устройства захвата
- •1.13.7 Подсчет числа импульсов в единицу времени
- •1.14 Широтно-импульсный модулятор
- •1.14.1 Основы функционирования
- •1.14.2 Дополнительные возможности
- •1.14.3 Регистры управления ШИМ
- •1.14.4 Порядок настройки ШИМ
- •1.15 Аналого-цифровые преобразователи
- •1.15.1 Краткие сведения о встроенных АЦП
- •1.15.2 Общие рекомендации по использованию АЦП
- •1.15.3 Управляющие регистры
- •1.15.4 Порядок настройки АЦП
- •1.15.5 Программный запуск аналого-цифрового преобразователя
- •1.15.6 Запуск аналого-цифрового преобразователя по таймеру
- •1.15.7 Программный опрос готовности АЦП
- •1.15.8 Опрос готовности АЦП по прерыванию
- •1.15.9 Считывание и масштабирование результата АЦП
- •1.16 Цифро-аналоговый преобразователь
- •1.16.1 Регистр управления ЦАП
- •1.16.2 Рекомендации по применению ЦАП
- •1.17 Последовательный синхронный приемо-передатчик SPI
- •1.17.1 Назначение и основы функционирования интерфейса SPI
- •1.17.2 Управляющие регистры
- •1.17.3 Передача и прием данных в режиме ведущего
- •1.17.4 Передача и прием данных в режиме ведомого
- •1.18 Последовательный синхронный приемо-передатчик I2С
- •1.18.1 Назначение и основы функционирования интерфейса I2С
- •1.18.2 Управляющие регистры
- •1.18.3 Настройка модуля I2C
- •1.18.4 Типовые циклы обмена данными по шине I2C
- •1.19 Последовательный асинхронный приемопередатчик UART
- •1.19.1 Назначение и основы функционирования порта UART
- •1.19.2 Управляющие регистры
- •1.19.3 Настройка порта UART
- •1.19.4 Прием байта с опросом флага
- •1.19.5 Передача байта с опросом флага
- •1.19.6 Прием и передача данных с использованием прерываний
- •1.19.7 Прием и передача пакетов данных
- •1.19.8 Диагностика ошибок
- •1.19.9 Автоматическая настройка скорости
- •1.20 Часы реального времени
- •1.20.1 Основные возможности часов реального времени
- •1.20.2 Управляющие регистры
- •1.20.3 Рекомендации по применению
- •1.21 Управление питанием и идентификация источников сброса
- •1.21.1 Краткие сведения о мониторе питания
- •1.21.2 Управляющие регистры
- •Часть 2. Разработка и отладка программ с помощью современных инструментальных средств
- •2.1 Форматы представления чисел
- •2.1.1 Основные коды представления целых чисел
- •2.1.2 Форматы представление целых чисел, приятные в языке Си
- •2.1.3 Форматы чисел c плавающей точкой стандарта IEEE754
- •2.2 Основы программирования на языке Си
- •2.2.1 Структура программы
- •2.2.2 Числовые константы
- •2.2.3 Переменные и именованные константы
- •2.2.4 Оператор присваивания, выражения и операции
- •2.2.5 Условный оператор
- •2.2.6 Приведение и преобразование типов
- •2.2.7 Массивы
- •2.2.8 Строки символов
- •2.2.9 Структуры
- •2.2.10 Объединения
- •2.2.11 Указатели
- •2.2.12 Ветвление
- •2.2.13 Множественное ветвление
- •2.2.14 Цикл со счетчиком
- •2.2.15 Циклы с предусловием и постусловием
- •2.2.16 Функции
- •2.2.17 Некоторые директивы компилятора
- •2.2.18 Библиотека математических функций MATH.h
- •2.2.19 Функция создания форматированных строк SNPRINTF
- •2.2.20 Ассемблер в Си-программах
- •2.3 Интегрированная среда разработки Keil µVision 4
- •2.3.1 Создание проекта
- •2.3.2 Создание файла программы
- •2.3.3 Настройка проекта
- •2.3.4 Набор текста программы
- •2.3.5 Компиляция программы
- •2.3.6 Отладка программы
- •2.3.7 Основные отладочные инструменты среды Keil µVision 4
- •2.3.8 Управление распределением памяти
- •2.4 Методика отладки программ
- •2.4.1 Быстрый поиск ошибок
- •2.4.2 Ввод и вывод дискретных сигналов
- •2.4.3 Таймер-счетчик. Формирование интервалов времени
- •2.4.4 Таймер-счетчик. Формирование внешних сигналов совпадения
- •2.4.5 Таймер-счетчик. Счетчик внешних событий
- •2.4.6 Таймер-счетчик. Устройство захвата
- •2.4.7 Широтно-импульсный модулятор
- •2.4.8 Аналого-цифровой преобразователь
- •2.4.9 Цифро-аналоговый преобразователь
- •2.4.10 Приемопередатчик SPI
- •2.4.11 Приемопередатчик I2C
- •2.4.12 Приемопередатчик UART
- •2.4.13 Часы реального времени
- •2.5 О программировании ARM7 на ассемблере
- •2.5.1 Основные правила записи программ на ассемблере
- •2.5.2 Псевдокоманды
- •2.5.3 Директивы ассемблера
- •2.5.4 Макросы
- •2.5.5 Пример простой программы
- •2.6 Распространенные средства разработки и отладки
- •2.6.1 Демонстрационные платы EA-EDU-001 и EA-EDU-011
- •2.6.2 Внутрисхемный отладчик J-Link
- •2.6.3 Утилиты программирования ПЗУ LPC Flash Utility и FlashMagic
- •2.6.4 Программа-терминал 232Analyzer
- •2.6.5 Низкоуровневый редактор диска DMDE
- •Часть 3. Решение типовых задач локального управления
- •3.1 Формирование временной задержки с помощью цикла
- •3.1.1 Задание
- •3.1.2 Общие рекомендации
- •3.1.3 Алгоритм программы
- •3.1.4 Отладка
- •3.1.5 Дополнительные сведения о формировании временной задержки
- •3.2 Формирование дискретного сигнала с помощью таймера
- •3.2.1 Задание
- •3.2.2 Общие рекомендации
- •3.2.3 Алгоритм программы
- •3.3 Опрос дискретного датчика или кнопки
- •3.3.1 Задание
- •3.3.2 Общие рекомендации
- •3.3.3 Алгоритм программы
- •3.3.4 Отладка
- •3.4 Опрос состояния механических контактов с подавлением дребезга
- •3.4.1 Задание
- •3.4.2 Общие рекомендации
- •3.4.3 Алгоритм программы
- •3.4.4 Отладка
- •3.5 Опрос клавиатуры с автоповтором
- •3.5.1 Задание
- •3.5.2 Общие рекомендации
- •3.5.3 Алгоритм программы
- •3.5.4 Отладка
- •3.6 Формирование импульсного управляющего сигнала с помощью модуля ШИМ
- •3.6.1 Задание
- •3.6.2 Общие сведения
- •3.6.3 Алгоритм программы
- •3.6.4 Отладка
- •3.6.5 Синхронизация внешним сигналом
- •3.7 Формирование сигналов специальной формы с помощью ЦАП
- •3.7.1 Задание
- •3.7.2 Основы
- •3.7.3 Алгоритм программы
- •3.7.4 Повышение точности генерирования частоты
- •3.7.5 Выбор числа дискрет
- •3.8 Управление двухфазным шаговым двигателем
- •3.8.1 Задание
- •3.8.2 Общие сведения
- •3.8.3 Алгоритм программы
- •3.9 Применение ШИМ для формирования низкочастотных аналоговых сигналов
- •3.9.1 Задание
- •3.9.2 Основные сведения
- •3.9.3 Алгоритм основной программы
- •3.9.4 Алгоритм процедуры обработки прерывания
- •3.10 Управление символьным жидкокристаллическим индикатором
- •3.10.1 Задание
- •3.10.2 Управление модулем жидкокристаллической индикации
- •3.10.3 Разработка функции управления ЖКИ с ожиданием готовности
- •3.10.4 Функция вывода строки символов
- •3.10.5 Разработка функции инициализации модуля ЖКИ
- •3.10.6 Разработка тестовой программы
- •3.10.7 Управление ЖКИ с опросом флага готовности
- •3.10.8 Программирование произвольных символов
- •3.11 Управление матричным светодиодным индикатором
- •3.11.1 Задание
- •3.11.2 Основные рекомендации
- •3.11.3 Алгоритм основной программы
- •3.11.4 Алгоритм процедуры обработки прерывания
- •3.11.5 Реализация движения строки
- •3.12 Управление матричным жидкокристаллическим дисплеем
- •3.12.1 Управление дисплеем на основе контроллера PCF8833
- •3.12.2 Построение простейших геометрических фигур
- •3.13 Измерение постоянного напряжения
- •3.13.1 Задание
- •3.13.2 Основные рекомендации
- •3.13.3 Алгоритм основной программы
- •3.13.4 Алгоритм процедуры обработки прерывания от АЦП
- •3.13.5 АЦП с циклическим опросом нескольких каналов
- •3.13.6 Автоматический выбор пределов измерения
- •3.14 Измерение параметров уровня переменного напряжения
- •3.14.1 Задание
- •3.14.2 Основные рекомендации
- •3.14.3 Алгоритм основной программы
- •3.14.4 Алгоритм процедуры обработки прерывания
- •3.15 Измерение ускорения с помощью трехосевого акселерометра
- •3.16 Измерение интервалов времени с помощью таймера
- •3.16.1 Задание
- •3.16.2 Общие рекомендации
- •3.16.3 Алгоритм основной программы
- •3.16.4 Алгоритм процедуры обработки прерывания
- •3.16.5 Повышение разрешающей способности путем усреднения
- •3.16.6 Введение поправок
- •3.17 Измерение частоты с помощью счетчика
- •3.17.1 Задание
- •3.17.2 Основные рекомендации
- •3.17.3 Алгоритм программы
- •3.17.4 Повышение точности измерений
- •3.18 Опрос цифрового датчика температуры. Интерфейс I2C
- •3.18.1 Задание
- •3.18.2 Общие рекомендации
- •3.18.3 Алгоритм программы
- •3.20 Обмен данными с электрически перепрограммируемым ПЗУ
- •3.20.1 Задание
- •3.20.2 Общие сведения о микросхемах EEPROM
- •3.20.3 Адресация в микросхемах EEPROM
- •3.20.4 Порядок чтения EEPROM
- •3.20.5 Порядок записи EEPROM
- •3.20.6 Разработка программы чтения EEPROM
- •3.20.7 Разработка функции записи блока данных в EEPROM
- •3.21 Интерфейс RS-232. Прием и передача простых команд
- •3.21.1 Задание
- •3.21.2 Алгоритм программы
- •3.21.3 Автоматическая настройка скорости
- •3.22.1 Задание
- •3.22.2 Основные рекомендации
- •3.22.3 Алгоритм программы
- •3.23 Интерфейс RS-232. Прием пакета переменной длины
- •3.23.1 Задание
- •3.23.2 Основы реализации
- •3.23.3 Алгоритм программы
- •3.24 Обмен данными с картой памяти Secure Digital
- •3.24.1 Задание
- •3.24.2 Общие сведения о карах FLASH-памяти SD/MMC
- •3.24.3 Команды SD/MMC
- •3.24.4 Процедура инициализации карты
- •3.24.5 Чтение и запись данных
- •3.24.6 Обработка ошибок
- •3.24.7 Комментарии к алгоритму и программе
- •Алфавитный указатель управляющих регистров
- •Список литературы
- •Содержание
Часть 2. Разработка и отладка программ с помощью современных инструментальных средств
2.1 Форматы представления чисел
2.1.1 Основные коды представления целых чисел
В памяти вычислительной машины информация представлена в двоичной форме. Диапазон хранимых в памяти чисел определяется разрядностью , то есть числом двоичных разрядов (битов), отводимых для записи числа. Часто разрядность бывает кратной 8 битам, то есть 8, 16, 32 или 64 двоичных разряда.
Как и в привычной десятичной системе счисления, разряды нумеруются справа налево, с нуля до . Вес каждого разряда определяется его номером, как число два, возведенное в степень номера разряда. Правый нулевой разряд называют младшим, так как его вес , левый ()-ый разряд называют старшим, так как он имеет наибольший вес . Значение числа в двоичном коде можно рассчитать по формуле:
. (2.1.1)
Способы представления целых чисел различаются в зависимости от кодирования знака («+» или «–»).
Прямой код. Для хранения знака выделяют старший разряд, называемый знаковым. Остальные разряды называют значащими. Знаковый разряд положительного числа всегда равен нулю, отрицательного — единице. Количество значащих разрядов при этом сокращается на 1, а наибольшее число, которое можно записать в разрядной сетке, оказывается примерно вдвое меньше и составляет . Формула меняется:
. (2.1.2)
Несмотря на простоту для понимания, реализация вычислений в прямом коде затруднена, поэтому такой код практически никогда не применяется. Вычислительные машины используют для представления отрицательных чисел дополнительный код.
В дополнительном коде, как и в прямом, старший разряд используется для хранения знака, но знак кодируется иначе:
. (2.1.3)
Число состоит из двух частей: отрицательной, кодируемой всего одним разрядом (), и положительной, кодируемой всеми остальными разрядами. Если знаковый разряд равен нулю, отрицательная часть отсутствует и число становится положительным. Для положительных чисел прямой и обратный код совпадают. По модулю отрицательная часть, по крайней мере, на единицу больше положительного, так как, очевидно,
.
Поэтому если знаковый разряд равен единице, то число отрицательно. Дополнительный код имеет несколько преимуществ перед прямым: 1) Только в дополнительном коде выполняется очевидное равенство
96
,
что позволяет применять общие правила для сложения положительных и отрицательных чисел.
2) В дополнительном коде существует единственное представление нуля. Для сравнения, в прямом коде можно записать как , так и . Однозначность нуля освобождает одну кодовую комбинацию, которая по формуле (2.1.3) относится к области отрицательных чисел. Поэтому в дополнительном коде всегда диапазон представления отрицательных чисел на единицу больше, чем положительных. Наибольшее по модулю отрицательное число всегда четное и равно . Наибольшее положительное число всегда нечетное и равно .
Смена знака числа в дополнительном коде производится по формуле
. (2.1.4)
То есть инвертируются все разряды числа и к результату прибавляется единица. Эту формулу можно считать правилом перевода в прямой код и обратно.
Отметим, что правила машинной арифметики для положительных и отрицательных чисел в дополнительном коде абсолютно одинаковы. По одним и тем же правилам вычисления выполняются верно, независимо от того, служит ли старший разряд для хранения знака (знаковый разряд) или это значащий разряд, расширяющий вдвое диапазон представления только положительных чисел.
Программист субъективно интерпретирует старший разряд как знаковый или значащий в зависимости от того интересуют ли его в данной задаче отрицательные числа.
Процессор, как правило, информирует программиста о принадлежности результата двум диапазонам: и . Выход за пределы первого диапазона говорит о переполнении при работе с положительными числами, выход за пределы второго — о переполнении при обработке чисел со знаком. О реализации контроля переполнения в архитектуре ARM7 см. раздел 1.2.3 (биты С и V слова состояния программы CPSR).
Смещенный код очень распространен для кодирования чисел в таких устройствах как аналого-цифровые и цифро-аналоговые преобразователи. Для смещенного кода можно использовать декодирующее выражение
. (1.2.5)
В таком коде 0 — наименьшее отрицательное число, все единицы — наибольшее положительное число, а ноль находится в середине между ними.
Удобство применения именно такого кодирования связано с тем, что в ЦАП и АЦП диапазон напряжения зависит от схемы включения. Возможность работы с двуполярным напряжением и сама полярность напряжения задаются схемотехнически. Поэтому практически удобно независимо от знака наименьшее напряжения представлять наименьшим кодом (все нули), а наибольшее — наибольшим кодом (все единицы).
Код Грея применяется для кодирования угла поворота ротора или фазового угла несущего колебания модулированного сигнала. Любые два
97
смежных числа, записанные в коде Грея, отличаются только одним какимлибо разрядом. Код Грея в отличие от рассмотренных выше является непозиционным, можно сказать, подобно римской системе записи чисел.
Преобразование из обычного позиционного двоичного кода в код Грея и обратно выполняется с помощью операций сдвига и сложения по модулю два. Для наглядности введем обозначение для операции сдвига вправо двоичного кода на разрядов (младший разряд при сдвиге теряется, старший заменяется нулем)
.
Будем применять традиционное обозначение «» не только к разряду, но и к коду, подразумевая при этом, что операция «сложение по модулю два» (она же «исключающее ИЛИ», она же «неравнозначность») выполняется поразрядно. Тогда код Грея получается из позиционного двоичного кода по формуле
. |
(2.1.5) |
Обратное преобразование требует циклического повторения:
или короче
. |
(2.1.6) |
2.1.2 Форматы представление целых чисел, приятные в языке Си
Некоторые весьма существенные моменты, касающиеся целочисленных типов данных, могут отличаться в разных компиляторах. Здесь рассматривается компилятор RealView 4.
Целые положительные числа представляются в памяти в прямом двоичном коде. Числа, занимающие более одного байта, размещаются в памяти в нескольких последовательных байтах. Младший байт получает меньший адрес, старший — больший. Отрицательные числа записываются в дополнительном коде. В таблице 2.1.1 приведены доступные форматы представления целых чисел.
Обратим внимание на то, что тип char без приставки unsigned считается беззнаковым. Восьмиразрядным числам со знаком соответствует тип signed char. В то время как все остальные типы без приставки unsigned хранят знак.
Поскольку ядро ARM7 32-х разрядное, основным типом целочисленных данных является int или long. Причем по той же причине они являются синонимами. Использование 8- или 16-разрядных чисел (соответственно char и short) сократит объем расходуемой оперативной памяти, однако может потребовать большего кода и снизить производительность. Это объясняется тем, что в код программы будут внедрены команды, искусственно ограничивающие разрядность. Использование 64-разрядных чисел (long long) тоже снизит производительность, но уже из-за необходимости «наращивания» разрядности.
98
Таблица 2.1.1 – Форматы представления целых чисел
Тип Си |
Объем |
Диапазон представления чисел |
|
(компилятор RealView 4) |
памяти |
||
|
|||
char и unsigned char |
1 байт |
|
|
signed char |
|
||
|
|
||
unsigned short |
2 байта |
|
|
short |
|
||
|
|
||
unsigned int и |
|
|
|
unsigned long |
4 байта |
|
|
int и long |
|
|
|
unsigned long long |
8 байт |
|
|
long long |
|
||
|
|
Программисту полезно запомнить двоичные и шестнадцатеричные представления всех чисел от 0 до 15, а также некоторых других положительных и отрицательных чисел (см. таблицу 2.1.2).
Таблица 2.1.2 – 2-чные и 16-ричные представления некоторых целых чисел
Двоичный |
Числа без знака |
Числа со знаком |
|||
и |
(прямой код) |
|
(дополнительный код) |
||
16-ричный |
Числовое |
|
Пример |
Числовое |
Пример |
коды |
значение |
|
для |
значение |
для |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.1.3 Форматы чисел c плавающей точкой стандарта IEEE754
Компилятор RealView 4 поддерживает два формата — одинарной (float) и двойной (double) точности (см. таблицу 2.1.3).
Схемы, иллюстрирующие представления чисел в формате float и double, показаны на рисунке 2.1.1.
Таблица 2.1.3 – Форматы представления чисел с плавающей точкой
Тип Си |
Объем |
Диапазон чисел |
Пределы относит. |
Минимальное по |
|
памяти |
погрешности |
модулю число |
|||
|
|
||||
float |
4 байта |
|
|
|
|
double |
8 байт |
|
|
|
99
31 |
30 |
23 |
|
22 |
0 |
S |
|
P |
|
M |
|
Знак |
|
Порядок |
|
Мантисса |
|
|
|
8 разрядов |
|
23 разряда |
|
63 |
62 |
52 |
|
51 |
0 |
S |
|
P |
|
M |
|
Знак |
|
Порядок |
|
Мантисса |
|
|
|
11 разрядов |
|
52 разряда |
|
|
|
|
|
|
|
Рисунок 2.1.1 – Схемы предоставления чисел с плавающей запятой согласно стандарту IEEE754: одинарной (вверху) и двойной (внизу) точности
23-разрядная (для float) и 52-разрядная (для double) мантисса представлена в прямом коде и хранит дробную часть числа. Числа считаются нормализованными кроме исключений, которое будет рассмотрено ниже. Это значит, что целая часть принимается равной единице. Иными словами, децимальная точка находится слева от мантиссы, а еще левее подразумевается единица. Знаковый разряд отделен от мантиссы и помещен в старший разряд всего кода. Для отрицательных чисел .
8-разрядный (для float) и 11-разрядный (для double) порядок записан в смещенном коде, то есть коду «все нули» соответствует максимальное по модулю отрицательное число, «все единицы» — максимальное положительное.
Общее выражение для расчета числа одинарной точности, представленного в формате IEEE754:
;
.
Второе выражение используется для так называемых денормализованных чисел (обозначаемых нулевым порядком ). Мантисса денормализованного числа не имеет единичной целой части. Введение денормализации позволяет расширить динамический диапазон представления чисел.
Общее выражение для расчета числа двойной точности, представленного в формате IEEE754:
;
.
Очевидно, что с помощью приведенных формул невозможно записать ноль. Для нуля потребовалось исключительное обозначение. Еще несколько исключений предназначены для обозначения бесконечности и неопределенности (см. таблицу 2.1.4).
Бесконечность (Infinity) возникает при делении на ноль и в результате выполнения некоторых функций, например, логарифм нуля. Неопределенность (Not a Number) возникает при делении нуля на ноль, бесконечности на бесконечность и в результате таких функций, как корень из отрицательного числа и логарифм отрицательного числа.
100