- •Перечень сокращений
- •Предисловие
- •Введение
- •Часть 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 Комментарии к алгоритму и программе
- •Алфавитный указатель управляющих регистров
- •Список литературы
- •Содержание
unsigned int B=10;
double D; |
|
... |
|
D=(int)(A*B); |
// D=-10 |
И то же с примером 1: |
|
int A=75, B=10; |
|
double C; |
|
... |
|
C=(double)A/B; |
// C=7.5 |
C=A/(double)B; |
// C=7.5 |
2.2.7 Массивы
Массив — это совокупность однотипных элементов, которые идентифицируются по индексу или нескольким индексам.
Одномерные массивы объявляются следующим образом
Тип Имя[Размерность]={Значениие1, ... ,ЗначениеN};
Массивы могут быть многомерными. Рассмотрим синтаксис для двумерных массивов.
Тип Имя[Размерность1][Размерность2]=
{{Знач.11, ... ,Знач.1N}, ... ,{Знач.M1, ... ,Знач.MN}};
Начальные значения при объявлении присваивать не обязательно. В то же время, если присваивание выполняется, можно не указывать размерность, поставив две скобки подряд «[]». Тогда размерность автоматически определяется числом элементов в фигурных скобках.
Обращение к элементам массива производится с указанием индексов в квадратных скобках
A[5]
B[m][n]
В Си индексация элементов массива всегда начинается только с нуля. Индекс является смещением относительно базового адреса.
Часто применяется компактная запись, сочетающая обращение к элементу массива с изменением индекса:
A[k++]=...
...=B[m][++n]
В первом случае выборка элемента массива из памяти предшествует инкременту индекса, во втором используется уже инкрементированный индекс.
2.2.8 Строки символов
Строка представляет собой одномерный массив элементов типа char, последний из которых всегда равен нулю (обозначает конец строки). Строковые константы записываются в двойных кавычках. Ниже приведены эквивалентные примеры
char S[7]="Превед";
char S[7]={'П','р','е','в','е','д',0};
107
Обратим внимание на то, что в основной программе строковую константу нельзя присвоить строковой переменной, также как нельзя одной командой присвоить значение массиву. Это допустимо только в разделе объявления переменных. Вместе с тем строковые константы, заключенные в кавычки могут быть параметрами функций.
Для символов, которые невозможно набрать с клавиатуры, предусмотрено специальное обозначение: «\xКод». Код используется шестнадцатеричный. Например
"I \x01 ARM7" |
// Дает "I ♥ ARM7" |
2.2.9 Структуры
Структура, в отличие от массива, — это совокупность разнотипных данных, называемых полями, идентифицируемых по имени. Среди полей могут быть и массивы. Объявление структуры имеет вид
struct
{
Объявление1 ;
...
ОбъявлениеN ; } Имя ;
При обращении к элементам структуры ее имя отделяется от имени поля точкой, например
Structure1.Field2=...
Может быть задано начальное значение, например:
struct
{
int Header; int CRC;
char Data[8];
} Frame={0x12345678,0,{1,2,3,4,5,6,7,8}};
2.2.10 Объединения
Объединения дают возможность обращаться к одной и той же области памяти, как к данным разных типов.
union
{
Объявление1 ;
...
ОбъявлениеN ; } Имя ;
Обычно (но не обязательно) все элементы объединения имеют одну и ту же длину. Приведем пример записи области памяти как массива четырех байтов и чтения той же области уже как числа с плавающей точкой, состоящего из этих байтов.
108
union
{
float F; char C[4];
} Buffer;
...
for (k=0; k<4; k++) Buffer.С[k]=...;
...=Buffer.F;
2.2.11 Указатели
Указатель представляет собой 32-разрядную величину, хранящую адрес переменной произвольного типа. При объявлении указателя после типа данных ставится символ «*», например,
float* F;
Фактически с помощью указателей в Си реализуется косвенная адресация. Присваивание указателю числовой константы недопустимо, в принципе возможно и осуществляется так.
Имя_указателя = ( Тип* ) Значение;
Например, в нашем случае
F=(float*)0x40000010;
Однако это изменит не данные, а адрес, на который ссылается указатель. При программировании для ARM7 распределение памяти, как правило, полностью доверяется компилятору. В таком случае с уверенностью сказать, что конкретный адрес памяти свободен, — невозможно. Поэтому инициализация (присваивание значения) указателя обычно выполняется так
F=&D;
Здесь D — имя переменной, а & оператор взятия адреса (таблица 2.2.1). Такая команда приведет к тому, что указатель F будет ссылаться на переменную D.
Для обращения к самим данным используется такой синтаксис
*F=23; |
// |
Запись |
по адресу, хранящемуся в F |
...=*F; |
// |
Чтение |
адреса, хранящегося в F |
Здесь * — оператор обращения по адресу (таблица 2.2.1).
Внашем примере следующие операции будут идентичны.
*F=...; D=...;
Всущности, массивы тоже являются указателями на нулевой элемент (базовый адрес). Поэтому наряду с традиционным обращением к массиву
M[2]=100;
вполне допустимо
*(M+2)=100;
2.2.12 Ветвление
Конструкция ветвления имеет следующую структуру
109
if ( Выражение )
{
... ; // Блок операторов 1
}
else
{
... ; // Блок операторов 2
}
Здесь Выражение — любое арифметическое выражение целого типа. Если это Выражение имеет ненулевое значение, выполняется блок операторов 1, иначе — блок операторов 2. Такую форму записи можно назвать полной. Сокращенная форма записи не содержит ветви else.
Если блок операторов состоит лишь из одной команды, то операторные скобки { } можно опустить.
Пример 1
if ((A>0) && B) // Выполнить операторы 1–2, если
{ |
// A>0 и B≠0 |
|
Оператор 1 ; |
|
Оператор 2 ; |
}
Else // Иначе выполнить оператор 3
Оператор 3 ;
Отметим, что в Си допустимо совмещать вычисления и проверку условия. Приведем несколько примеров.
Пример 2.
if (--k==0) |
// |
Декремент k, если результат |
{ |
// равен нулю, то выполнять операторы |
|
Операторы ; |
|
|
} |
|
|
Пример 3. |
|
|
if (k++>100) // Если k>100, то выполнять операторы |
||
{ |
// После проверки увеличить k на 1 |
|
Операторы ; |
|
|
} |
|
|
Пример 4. |
|
|
if (A|=B) |
// Присвоить A поразрядное ИЛИ A и B |
|
{ |
// Выполнять операторы, если результат ≠0 |
|
Операторы ; |
|
|
} |
|
|
2.2.13 Множественное ветвление
Конструкция множественного ветвления имеет следующую структуру
switch ( Выражение )
110