Академический Документы
Профессиональный Документы
Культура Документы
398
В 858
Рецензенты:
докт. техн. наук, проф. А.Б. Красовский (МГТУ им. Н.Э. Баумана);
канд. техн. наук, доц. Т.В. Ремизевич (МЭИ) (ТУ)
Авторы:
А.С. Анучин, Д.И. Алямкин, А.В. Дроздов, В.Ф. Козаченко, А.С. Тарасов
ISBN 978-5-383-00471-5
Авторы
5
Глава 1
УСТРОЙСТВО И ФУНКЦИОНАЛЬНЫЕ ВОЗМОЖНОСТИ
TM
ОЦЕНОЧНОЙ1 ПЛАТЫ eZdsp F2812
ДЛЯ РАЗРАБОТКИ И ОТЛАДКИ ПРОГРАММНОГО
ОБЕСПЕЧЕНИЯ В ИНТЕГРИРОВАННОЙ СРЕДЕ
CODE COMPOSER STUDIO. ВВЕДЕНИЕ В СРЕДУ CCS.
ТЕХНОЛОГИЯ РАСПРЕДЕЛЕНИЯ ПАМЯТИ
eZdspТМ F2812
аналоговых входов
Порт расширения
Параллельный
Аналого-цифровой
порт
преобразователь
параллельный порт
JTAG-интерфейс/
Контроллер
JTAG
Статическое
XZCS6AND7n ОЗУ
внешний
64К*16
JTAG
Микро-
контроллер
Порт расширения
TMS320F2812
ввода/вывода
цифрового
Дискретные
порты
Тактовый ввода/
XTAL1/OSCIN
генератор вывода
TM
Рис. 1.1. Блок-схема оценочной платы eZdsp F2812
8
TM
Рис. 1.2. Конструкция оценочной платы eZdsp F2812
Практическая работа
Соединитель Назначение
P1 JTAG-интерфейс для отладки с помощью стандартного внутрисхемного эмулятора
P2 Разъем расширения памяти и периферии
P3 Параллельный порт контроллера JTAG-интерфейса для отладки от компьютера
через стандартный параллельный порт
P4/P8/P7 Интерфейс сопряжения со встроенными периферийными устройствами
P5/P9 Интерфейс аналогового ввода/вывода
P6 Разъем подключения источника питания
JTAG-интерфейс, P1
Отладочная плата, изображенная на рис. 1.3, имеет 14-выводной JTAG-
интерфейс P1 для подключения внутрисхемного эмулятора и выполнения
профессиональной отладки программного обеспечения без каких-либо огра-
ничений. Спецификация сигналов на разъеме — стандартная для всех сиг-
нальных процессоров Texas Instruments и приведена в табл. 1.2. Отсутствую-
щий шестой вывод выполняет функцию ключа.
P1
13 11 9 7 5 3 1 1
14 12 10 8 4 2 2
JTAG
10
Табл и ц а 1.2
Спецификация выводов JTAG-интерфейса (разъем P1)
Вывод 13 11 9 7 5 3 1
Сигнал EMU0 TCK TCK-RET TDO PD (+5V) TDI TMS
Вывод 14 12 10 8 6 4 2
Сигнал EMU1 GND GND GND Нет вывода GND TRST-
P2
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 41 43 45 47 49 51 54 56 58 60
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 42 44 46 48 50 52 53 55 57 59
Та бл и ца 1.3
Спецификация сигналов разъема расширения P2
Вывод 1 2 3 4 5 6 7 8 9 10
Сигнал +5V +5V XD0 XD1 XD2 XD3 XD4 XD5 XD6 XD7
Вывод 11 12 13 14 15 16 17 18 19 20
Сигнал XD8 XD9 XD10 XD11 XD12 XD13 XD14 XD15 XA0 XA1
Вывод 21 22 23 24 25 26 27 28 29 30
Сигнал XA2 XA3 XA4 XA5 XA6 XA7 XA8 XA9 XA10 XA11
Вывод 31 32 33 34 35 36 37 38 39 40
Сигнал XA12 XA13 XA14 XA15 GND GND XZCS0AND1# XZCS2# XREADY 10K
Вывод 41 42 43 44 45 46 47 48 49 50
Сигнал XR#W 10K Pullup XWE XRD# +3.3V XNMI/INT13 XRS#/RS# Не подкл. GND GGND
Вывод 51 52 53 54 55 56 57 58 59 60
Сигнал GND GND A16 A17 A18 XHOLD# XHOLDA# Не подкл. Не подкл. Не подкл.
11
Параллельный порт/JTAG-интерфейс, P3
TM
Оценочная плата eZdsp F2812 имеет обычный параллельный порт для
подключения к персональному компьютеру (стандарты ECP, EPP и SPP8 дву-
направленной передачи данных). Со стороны оценочной платы параллель-
ный интерфейс преобразуется в JTAG-интерфейс, обеспечивая доступ к про-
цессору со стороны компьютера при отладке. Со стороны компьютера
необходимо установить соответствующий драйвер, который будет позволять
интегрированной среде Code Composer Studio загружать и отлаживать про-
граммы в реальном времени, используя параллельный интерфейс. Драйвер
поставляется вместе с отладочной платой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 P4
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 P8
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
1 2 3 4 5 6 7 8 9 10 P7
12
ввода/вывода, организации межпроцессорных коммуникаций, подключения
дополнительных периферийных устройств (ЦАП, АЦП и т.д.);
• последовательного коммуникационного интерфейса A (SCITXDA,
SCIRXDA) для поддержки стандартных последовательных каналов связи
(RS-232, RS-422, RS-485);
• контроллера промышленной шины CAN (CANTXA, CANRXA), пред-
назначенного для организации локальных промышленных сетей на базе
CAN-интерфейса, построения распределенных мультимикропроцессорных
систем, расширения ввода/вывода.
Кроме того, на этот разъем выведен сигнал XCLKOUT внутреннего так-
тового генератора процессора, позволяющий не только убедиться в работо-
TM
способности платы eZdsp F2812, но и тактировать внешние устройства.
Табли ц а 1 . 4
Спецификация сигналов на разъемах P4 и P8
P4 P4 P8 P8 P8 P8
Вывод Сигнал Вывод Сигнал Вывод Сигнал
1 +5 V 1 +5 V 2 +5 V
2 XINT2/ADCSOC 3 SCITXDA 4 SCIRXDA
3 MCLKXA 5 XINT1#/XBIO# 6 CAP1/QEP1
4 MCLKRA 7 CAP2/QEP2 8 CAP3/QEPI1
5 MFSXA 9 PWM1 10 PWM2
6 MFSRA 11 PWM3 12 PWM4
7 MDXA 13 PWM5 14 PWM6
8 MDRA 15 T1PWM/T1CMP 16 T2PWM/T2CMP
9 NC 17 TDIRA 18 TCLKINA
10 GND 19 GND 20 GND
11 CAP5/QEP4 21 NC 22 XINT1N/XBIO#
12 CAP6/QEPI2 23 SPISIMOA 24 SPISOMIA
13 T3PWM/T3CMP 25 SPICLKA 26 SPISTEA
14 T4PWM/T4CMP 27 CANTXA 28 CANRXA
15 TDIRB 29 XCLKOUT 30 PWM7
16 TCLKINB 31 PWM8 32 PWM9
17 XF/XPLLDIS# 33 PWM10 34 PWM11
18 SCITXDB 35 PWM12 36 CAP4/QEP3
19 SCIRXDB 37 T1CTRIP/PDPINTA# 38 T3CTRIP/PDPINTB#
20 GND 39 GND 40 GND
13
На разъем P4 выведены сигналы менее часто используемых периферий-
ных устройств:
• многоканального последовательного буферизированного порта
(MCLKXA, MCLKRA, MFSXA, MFSRA, MDXA, MDRA), обеспечивающего
как синхронную, так и асинхронную передачу и предназначенного для рас-
ширения ввода/вывода и организации межпроцессорных коммуникаций;
• модуля захвата второго менеджера событий B (CAP5/QEP4,
CAP6/QEPI2);
• второго последовательного коммуникационного интерфейса B
(SCITXDB, SCIRXDB);
• дополнительных ШИМ-генераторов (модулей сравнения), реализован-
ных на базе таймеров 3 и 4 (T3PWM/T3CMP и T4PWM/T4CMP);
• второго таймера/счетчика в режиме внешнего тактирования
(TCLKINB, TDIRB).
Кроме того, на этот разъем выведен сигнал XF — битового флага, управ-
ляемого непосредственно программой пользователя.
На разъем P7 (табл. 1.5) выведен ряд специальных входов менеджеров
событий A и B, которые могут использоваться в качестве сигналов блоки-
ровки выходов ШИМ-генераторов: либо при приёме сигнала аварии в сило-
вом преобразователе, либо при приёме сигнала превышения выходным
током заданного порогового значения (функция автоматического токоограни-
чения). При этом сигналы C1TRIP#, C2TRIP#, C3TRIP# могут блокировать
соответственно стойки 1, 2 и 3 первого инвертора, а сигналы С4TRIP#,
C5TRIP#, C6TRIP# — стойки 4, 5, 6 второго инвертора.
Возможен также независимый приём сигналов аварий или блокировки
ШИМ для всех четырех дополнительных каналов ШИМ-генератора, реали-
зованных на базе таймеров T1, T2, T3, T4 — сигналы T1CTRIP—T4CTRIP.
Это обеспечивает идентификацию аварии вплоть до конкретного силового
ключа.
Кроме того, имеется возможность сборки по «монтажному ИЛИ» всех
аварийных сигналов в один сигнал PDPINTA# или PDPINTB# и одновремен-
ной блокировки сразу всех ШИМ-выходов менеджера событий А или B соот-
ветственно.
Табл и ц а 1.5
Спецификация сигналов на разъеме P7
Вывод 1 2 3 4 5
Сигнал С1TRIP# C2TRIP# C3TRIP# T2CTRIP#/EVASOC# C4TRIP#
Вывод 6 7 8 9 10
Сигнал C5TRIP# C6TRIP# T4CTRIP#/EVBSOC# NC GND
14
Аналоговый интерфейс, P5/P9
Для сопряжения с источниками аналоговых сигналов используется
30-выводной аналоговый интерфейс. Схема расположения выводов на разъ-
емах P5/P9 представлена на рис. 1.6.
Встроенный в микроконтроллеры аналого-цифровой преобразователь
(ADC) является 12-разрядным последовательным АЦП с устройством
выборки-хранения и двумя входными 8-канальными мультиплексорами А и
В, входы которых выведены на разъемы P9 (ADCINA0-7) и P5 (ADCINB0-7),
представленные в табл. 1.6.
Общее число аналоговых входов — 16. Формат ввода аналоговых сигналов
0—3 В. Дополнительно на разъем выведены сигналы встроенных в аналого-
цифровой преобразователь опорных источников питания ADCREFP (2 В),
ADCREFM (1 В) и сигналы аналоговой земли (GND). Все входы АЦП явля-
ются «голыми» — они не содержат ни входных фильтров низкой частоты для
защиты от помех, ни схем преобразования уровней, ни схем защиты от пере-
полюсовки и превышения допустимого входного напряжения. Соблюдайте
осторожность при подключениях!
ANALOG
P5
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
1 3 5 7 9 11 13 15 17 19
P9
Табли ц а 1 . 6
Спецификация сигналов на разъемах P5, P9
P5 P9 P9
Сигнал Сигнал Сигнал
Вывод Вывод Вывод
1 ADCINB0 1 GND 2 ADCINA0
2 ADCINB1 3 GND 4 ADCINA1
3 ADCINB2 5 GND 6 ADCINA2
4 ADCINB3 7 GND 8 ADCINA3
5 ADCINB4 9 GND 10 ADCINA4
6 ADCINB5 11 GND 12 ADCINA5
7 ADCINB6 13 GND 14 ADCINA6
8 ADCINB7 15 GND 16 ADCINA7
9 ADCREFM 17 GND 18 VREFLO
10 ADCREFP 19 GND 20 NC
15
Контрольные вопросы
1. К каким точкам на плате можно подключить осциллограф, чтобы проверить, рабо-
тает ли центральный процессор, а именно генерируется ли выходная тактовая частота?
2. К каким точкам на плате нужно подключить осциллограф, чтобы проверить пра-
вильность формирования программой пользователя выходного битового сигнала XF?
3. Можно ли подключить к оценочной плате переменный резистор и сигнал с его
движка подать на вход АЦП? В каком диапазоне напряжений сможете менять уровень
входного аналогового сигнала?
16
Сигнал (PLL) защелкивается при сбросе системы и далее может исполь-
зоваться как битовый выход XF. Фазосдвигающая логика обеспечивает
умножение частоты внешнего тактового генератора на программно заданный
коэффициент масштабирования.
Четыре других переключателя JP7, JP8, JP11 и JP12 задают режим работы
процессора при включении питания — режим начальной загрузки.
Микроконтроллеры ‘C28 имеют встроенное, запрограммированное на
заводе-изготовителе ПЗУ, в котором находится программа начальной
загрузки процессора (boot-loading software). Эта программа автоматически
выполняется сразу после сброса процессора (включения питания) и тести-
рует состояние нескольких выводов процессора (битовых портов
ввода/вывода GPIO), чтобы определить, какой режим начальной загрузки
аппаратно установил пользователь. Состояние этих выводов связано с
положением переключателей JP7, JP8, JP11, JP12 на оценочной плате, что
позволяет задать один из нескольких возможных режимов начальной
загрузки. Выбор режима представлен в табл. 1.7.
Табл и ц а 1.7
Выбор режима начальной загрузки переключателями JP7, JP8, JP11, JP12
17
Так, пользователь может задать режим выполнения программы, уже запи-
санной ранее во флэш-память (режим FLASH), например, с помощью внут-
рисхемного эмулятора по интерфейсу JTAG. В этом случае собственно
загрузка программы не производится и управление сразу передается про-
грамме пользователя. Можно задать и режим выполнения программы, ранее
загруженной в оперативную память микроконтроллера (режим H0). Эта
опция используется по умолчанию при выполнении практических работ.
Имеются и другие варианты, в частности можно передать управление загруз-
чику программы из компьютера в микроконтроллер по последовательному
коммуникационному интерфейсу RS-232 (режим SCI_BOOT).
Дополнительно загрузочное ПЗУ микроконтроллера содержит таблицы
стандартных функций, таких как SIN, COS, предназначенные для ускорения
математических вычислений.
Практическая работа
1. Проверьте состояние всех переключателей на оценочной плате. Убеди-
тесь, что оно соответствует положению по умолчанию.
Контрольные вопросы
1. Какой режим начальной загрузки выберете для «перепрошивки» рабочей про-
граммы во флэш-память микропроцессорной системы управления преобразователем час-
тоты после отладки в ОЗУ, если система управления имеет выход на интерфейс RS-232, а
внутрисхемный эмулятор недоступен?
2. Понадобится ли для этой операции специальное программное обеспечение на ком-
пьютере?
3. В какое положение необходимо будет установить переключатели режима управле-
ния начальной загрузкой после завершения «перепрошивки», чтобы запустить модифи-
цированную рабочую программу в реальном времени?
19
Окончание табл. 1.8
Замечания
1. Размеры блоков памяти фиксированы и не могут изменяться пользова-
телем.
2. Области памяти, помеченные как резервные, зарезервированы для
будущих применений. Приложения пользователя не должны обращаться к
этим областям памяти.
20
Порядок доступа к памяти
Вся память делится на внутреннюю (встроенную на кристалл микроконт-
роллера) и внешнюю (расширенную) память. При обращении к памяти реа-
лизуется логика единого непрерывного адресного пространства, в котором
одну часть адресов занимает встроенная память, а другую — расширенная.
В том случае, когда адресные зоны областей встроенной и расширенной
памяти перекрываются (например, зона 0x3F F000 — 0x3F FFFF), для иден-
тификации конкретной области памяти используется текущее состояние
входа MP/MC# микроконтроллера. В режиме микропроцессора (MP/MC# = 1)
обеспечивается доступ к внешней памяти, а в режиме микроконтроллера
(MP/MC# = 0) — к внутренней памяти. Управление состоянием входа
MP/MC# реализуется с помощью переключателя JP1. Например, области
загрузочного постоянного запоминающего устройства (ПЗУ) и внешней
памяти в зоне 7 не могут использоваться одновременно. В режиме микрокон-
троллера (MP/MC#=0) обращение будет автоматически производиться к
встроенному загрузочному ПЗУ, а в режиме микропроцессора (MP/MC#=1) —
к зоне 7 внешней памяти.
С одной стороны, в микроконтроллерах ‘C28xx память унифицирована —
она может использоваться (за одним исключением) и как память данных, и
как память программ. Так, в ОЗУ обычно находятся переменные пользова-
теля (память данных), а в ПЗУ или во флэш-памяти — программы пользова-
теля. Однако оперативное запоминающее устройство можно использовать и
в качестве кодовой памяти, загружая в него программу, подлежащую
отладке, и передавая управление этой программе. Эта операция выполняется
в ходе практических работ. С другой стороны, в процессе загрузки флэш-
памяти программа «загрузчик» рассматривает флэш-память как память дан-
ных, обеспечивая пересылку новых данных — выполняет программирование
флэш-памяти. Сама программа «загрузчик» при этом будет располагаться в
кодовом ОЗУ процессора, и никаких специальных устройств — программа-
торов для этой операции не требуется.
Как видно из табл. 1.8, исключениями являются области памяти данных,
отведенные под регистры встроенных периферийных устройств. Регистры
периферийных устройств отображены на память данных — каждый из них
имеет свой адрес в памяти данных, по которому к нему можно обратиться.
Эти области памяти называются периферийными фреймами 1, 2 и 3 и не
могут использоваться в качестве памяти программ.
Унификация памяти существенно облегчает программирование, особенно
на языке высокого уровня, так как пользователь может наиболее рацио-
нально разделить память на память программ и данных в соответствии с кон-
кретной задачей. Разделение выполняется с помощью компоновщика.
Термины «защищен» (периферийные фреймы 1 и 2) и «защищена» (зона
расширенной памяти 1) относятся к конвейеру команд и означают, что аппа-
ратно исключается ситуация, когда данные из периферийного регистра/
памяти считываются текущей командой еще до того, как предыдущая
команда смогла их модифицировать. На практике это означает, что операции
с регистрами периферийных устройств памятью будут выполняться в стро-
гом соответствии с порядком, заданным программой пользователя.
21
Флэш-память и однократно-программируемое
постоянное запоминающее устройство
Область флэш-памяти, представленная в табл. 1.9, разбита на отдельные
сектора по 8 или по 16К слов каждый. Последние восемь слов флэш-памяти
отведены для программирования кода секретности (8×16=128 бит). Если
код секретности используется, то в область памяти 0x3F 7F80 — 0x3F 7FF5
должны быть записаны нули (ключ задания режима секретности). Два слова
непосредственно перед кодом секретности предназначены для программиро-
вания команды передачи управления на точку входа в программу, которая
может быть либо собственно программой пользователя, либо процедурой
начальной загрузки процессора, расположенной во флэш-памяти.
Табл и ц а 1.9
Таблица адресов секторов флэш-памяти
Диапазон
Сектор программ и данных, объем
адресов
0x3D 8000
Сектор J, 8К×16
0x3D 9FFF
0x3D A000
Сектор I, 8К×16
0x3D BFFF
0x3D C000
Сектор H, 16К×16
0x3D FFFF
0x3E 0000
Сектор G, 16К×16
0x3E 3FFF
0x3E 4000
Сектор F, 16К×16
0x3E 7FFF
0x3E 8000
Сектор E, 16К×16
0x3E BFFF
0x3E C000
Сектор D, 16К×16
0x3E FFFF
0x3F 0000
Сектор C, 16К×16
0x3F 3FFF
0x3F 4000
Сектор B, 8К×16
0x3F 5FFF
0x3F 6000 Сектор A, 8К×16
0x3F 7F80 Эта область памяти должна быть запрограммирована нулями (0x0000), если исполь-
0x3F 7FF5 зуется Модуль Секретности Кода (Code Security Module), в противном случае может
содержать любой код
0x3F 7FF6 Точка входа загрузчика во флэш-памяти (или ПЗУ)
0x3F 7FF7 Boot-to-Flash (or ROM) Entry Point
Здесь должна быть запрограммирована команда перехода на программу загрузчика
(branch instruction)
0x3F 7FF8 Код секретности (128 бит) — Security Password
0x3F 7FFF Биты кода секретности не должны быть все нулевыми
22
В процессорах ‘F2811, ‘F2812 общий объем флэш-памяти равен 128К сло-
вам: четыре сектора 8К×16 и шесть секторов 16К×16. В процессорах ‘F2810
— 64К слова: два банка по 8К×8 и три банка по 16К×16.
Все микроконтроллеры семейства ‘28x дополнительно имеют одно-
кратно-программируемое ПЗУ объемом 1К×16, расположенное в диапазоне
адресов 0x3D 7800 — 0x3D 7BFF. Операция записи в это ПЗУ может быть
выполнена только один раз.
Пользователь имеет возможность индивидуально стирать, программиро-
вать и верифицировать любой сектор флэш-памяти, оставляя информацию
в других секторах нетронутой. Однако нельзя использовать какой-либо сек-
тор флэш-памяти или однократно-программируемое ПЗУ для работы с дру-
гим сектором флэш-памяти. Это означает, что программа загрузки флэш-
памяти должна выполняться исключительно из кодового ОЗУ.
Флэш-память и однократно-программируемая память отображены одно-
временно и на память программ, и на память данных. Поэтому их можно
использовать для хранения как программного кода, так и данных, например
таблиц функций и коэффициентов.
В процессорах ‘C28 число тактов ожидания для работы с флэш-памятью и
однократно-программируемым ПЗУ может программироваться в приложе-
нии пользователя. Эффективная производительность флэш-памяти может
быть повышена за счет разрешения работы специального конвейера флэш-
памяти. Это можно сделать в регистре опций флэш-памяти (flash option
register). Точное значение производительности процессора при работе с
флэш-памятью зависит от конкретной задачи, а также от числа установленных
тактов ожидания и режима работы конвейера флэш-памяти. Режим конвейер-
ного доступа не используется при работе с однократно-программируемым ПЗУ.
Все микроконтроллеры семейства ‘28xx выпускаются в двух исполнениях:
‘F28xx с флэш-памятью и ‘C28xx с масочно-программируемым на заводе-
изготовителе ПЗУ того же объема. В процессе разработки новых изделий и в
мелкосерийном производстве используются микроконтроллеры ‘F28xx, а в
крупносерийном производстве — ‘C28xx (с уже не требующей отладки про-
граммой, «прошитой» в ПЗУ).
Расширенная память
Микроконтроллер TMS320F2812 автоматически формирует сигналы
выборки кристалла при обращении к расширенной памяти или периферии —
сигналы селектирования внешних устройств (CS#). Каждый сигнал соот-
ветствует определенной зоне адресов внешней расширенной памяти/перифе-
рии (XZ). Интерфейс внешней памяти поддерживает пять независимых зон
внешней памяти. Одна из них имеет свой собственный сигнал выборки
кристалла, а четыре другие — попарно общие сигналы «чип-селекта». Для
каждой зоны пользователь может запрограммировать свое собственное
число тактов ожидания (wait states), а также режим работы с сигналом готов-
ности памяти или без него. Это облегчает организацию интерфейса с вне-
шней памятью. Расширение периферии через XINTF поддерживается только
при отображении периферийных устройств на внешнюю память.
На плате eZdspTM F2812 один из сигналов выборки кристалла
XZCS6AND7# уже подключен к внешнему ОЗУ, а два других сигнала
(ZXCS0AND1# и XZCS2#) выведены на разъем расширения. Это позволяет
при необходимости еще больше расширить объем используемой памяти или
периферии.
При доступе к внешней статической памяти, установленной на плате,
микроконтроллер автоматически формирует строб XZCS6AND7#. Общий
объем этой зоны памяти 0,5М слова, начиная с адреса 0x10 0000 по адрес
0x18 0000. Реально используется только 64К слова в диапазоне адресов от
0x10 0000 до 0x10 FFFF.
Таблица
векторов Объем и место размещения Условие выбора
прерываний
М0 Vector 32×32-разрядных слова в начальной области VMAP = 0
ОЗУ 00 0000 — 00 003F (банк М0)
PIE Vector 256×16-разрядных слов в области ОЗУ пери- VMAP = 0, ENPIE = 1
ферийных устройств 00 0D00 — 00 0DFF
BROM Vector 32×32-разрядных слова в конечной области VMAP = 1, ENPIE = 0, MP/MC# = 0
загрузочного ПЗУ 3F FFC0 — 3F FFFF (в режиме микроконтроллера)
XINTF Vector 32×32-разрядных слова в конечной области VMAP = 1, ENPIE = 0, MP/MC# = 1
внешнего ОЗУ 3F FFC0 — 3F FFFF (в режиме микропроцессора)
Контрольные вопросы
Исходный файл
Исходный файл
на Ассемблере
на СИ (.с)
(.asm)
Библиотека
Компилятор
макросов и
С/С++
описаний на С
Файл
на Ассемблере
(.asm) Библиотека
макросов
на Ассемблере
Транслятор
с Ассемблера
Перемещаемый
Стандартные Объектные
объектный Файл объектные библиотеки
файл (.obj) листинга (.lst) библиотеки пользователя
Файл
управления
компоновкой Компоновщик
(lnk.cmd)
Code
Абсолютный Composer
объектный
файл(.out)
Файл карты Studio
загрузки (.map)
Файлы Средства
Загрузчик/
ввода данных графического
Отладчик
отображения
Файлы
Симулятор
вывода данных
SIM
Аппаратная часть
27
3) исходные файлы программных модулей на языке С/С++ (.c) обрабаты-
ваются компилятором с языка С/С++. Создаются промежуточные выходные
файлы на Ассемблере (.asm), которые в свою очередь обрабатываются транс-
лятором с Ассемблера с созданием выходных объектных файлов в перемеща-
емом объектном коде (.obj). Компилятор имеет встроенные средства оптими-
зации выходного кода;
4) специальная утилита внутреннего листинга связывает исходную про-
грамму на С/С++ с выходной программой на Ассемблере, чтобы разработчик
мог понять, как они коррелируют друг с другом, и при необходимости
выполнить «ручную оптимизацию»;
5) для стандартизации процесса разработки программного обеспечения
используется «Общий формат объектных файлов» Common Object File
Format (COFF) как для программ, написанных на Ассемблере, так и для про-
грамм, написанных на С/С++. Такой подход позволяет разрабатывать часть
программных модулей проекта (критичных ко времени выполнения и объ-
ему требуемой памяти) на Ассемблере, а часть — на С/С++;
6) вышеописанный процесс может повторяться для любого числа исход-
ных модулей;
7) ряд уже отлаженных программных модулей в перемещаемом объект-
ном коде может быть объединен в пользовательскую библиотеку объектных
модулей, содержащую набор часто вызываемых пользовательских функций;
8) могут использоваться также стандартные объектные библиотеки,
поставляемые производителями систем разработки ПО, например, для
вычислений в формате с плавающей точкой;
9) множество программных модулей в перемещаемом объектном коде
(.obj), в том числе нужные файлы из объектных библиотек, объединяются в
одну выходную программу в абсолютном объектном коде (.out) с помощью
компоновщика;
10) компоновщик эффективно распределяет ресурсы памяти, доступные
в конкретном микропроцессорном устройстве, для каждого модуля проекта.
При этом используется специальный командный файл управления компонов-
кой (lnk.cmd), который не только описывает структуру имеющихся ресурсов
памяти программ и данных на целевой плате (банки памяти), но и задает
правила размещения в этих банках различных секций программных модулей;
11) выходом процесса компоновки является абсолютный объектный файл
(.out), который может быть загружен и выполнен на целевой плате с DSP-
процессором в реальном масштабе времени. Дополнительно может генери-
роваться файл с картой загрузки (.map), в котором содержится информация о
том, в какие банки памяти и конкретно по каким адресам размещены все сек-
ции проекта;
12) в состав интегрированной среды CCS входит также загрузчик и
отладчик программ, с помощью которого можно выполнить рабочую про-
грамму по шагам, с точками останова или в реальном времени;
13) дополнительные возможности включают в себя: средства наблюдения
за состоянием регистров процессора и переменных в памяти; модификации
значений переменных «на лету»; утилиту подключения файлов ввода и
28
вывода данных для тестирования программ; встроенные средства графиче-
ского отображения и анализа информации, например получения фазового
портрета или частотного спектра сигнала;
14) еще более мощные возможности могут быть добавлены самим про-
граммистом с использованием специальной технологии расширения функций
интегрированной среды CCS;
15) гарантируется аппаратная совместимость со всеми оценочными (типа
eZdsp) и более мощными отладочными (EVM) платами, выпускаемыми фир-
мой Texas Instruments в помощь разработчикам, а также возможность
отладки с любыми платами, созданными пользователями, через стандарт-
ный внутрисхемный эмулятор XDS (главное средство профессиональной
отладки);
16) в состав CCS входит также программно-логическая модель процессора
(симулятор), допускающая загрузку и отладку программ без использования
каких-либо дополнительных аппаратных средств — только с использова-
нием компьютера. Это позволяет отлаживать часть программных модулей
удаленно, в том числе в домашних условиях.
Таким образом, интегрированная среда CCS поддерживает написание
модульного программного кода и позволяет работать над проектом несколь-
ким программистам одновременно, сокращая срок разработки приложения.
Отладка и обновление кода становятся быстрее. Новые проекты могут быть
разработаны с меньшими сроками, так как в них могут использоваться уже
отлаженные модули из предыдущих проектов. При использовании С/С++ код
становится аппаратно-независимым, что позволяет программисту модуля не
думать о распределении памяти. Эта работа будет сделана на этапе компо-
новки проекта. При изменении любого из модулей производится новая
сборка проекта и вопросы распределения памяти решаются заново, чтобы
исключить вероятность возникновения конфликтов.
Секция
.text
Секция
.data
Память целевой платы
Секция Память
.bss программ
(флэш-память)
Память
Объектный программ
файл 2 (ЭППЗУ)
Секция Память
.text данных
(ОЗУ)
Секция
.data
Секция
.bss
int x = 2;
int y = 7;
void main (void)
{
long z;
z = x + y;
}
31
Комментарии для начинающих:
1) любая программа на языке С/С++ состоит из одной или более функций.
Главная, или основная, функция программы называется main (). Имя главной
функции не может быть изменено программистом и всегда должно быть
main (). Круглые скобки после имени main указывают на то, что имя main
принадлежит функции;
2) тип void (пустой тип) перед именем главной функции указывает на то,
что главная функция не возвращает никакого значения;
3) тип void (пустой тип) вместо списка параметров в объявлении главной
функции main (void) означает, что главная функция не принимает аргументов;
4) тело любой функции, в том числе главной функции main, состоит из
составного оператора { }, причем открывающая фигурная скобка { соот-
ветствует началу составного оператора (begin), а закрывающая фигурная
скобка } — концу составного оператора (end);
5) в теле любой функции могут содержаться два блока: описания перемен-
ных и выполнения;
6) блок описания переменных включает операторы описания типов пере-
менных. Они имеют следующий синтаксис:
<Тип переменной> <Имя_переменной_1, Имя_переменной_2 [,…]>;
В примере, приведенном на с. 31 оператор описания типа переменной
имеет вид:
long z;
Он описывает переменную z как длинное целое число (типа long);
7) блок выполнения в программе содержит только оператор присваива-
ния: z = x + y;
8) переменные, описанные в самом начале программы перед главной фун-
кцией main(), являются глобальными переменными, а переменные, описан-
ные в теле функции, — локальными переменными. Локальные переменные
обычно размещаются в стеке;
9) в операторах объявления типов переменных допускается «попутная»
инициализация переменных. Она выполняется с помощью обычных операто-
ров присваивания:
int x = 2;
int y = 7;
Эти два оператора определяют переменные x и y как целые числа со зна-
ком в дополнительном коде (типа int) и инициализируют их значениями 2 и 7
соответственно.
С помощью языка С/С++ допускается одновременное описание несколь-
ких переменных одного и того же типа одним оператором:
int x =2, y = 7;
Не рекомендуется в одном операторе описания типов переменных смеши-
вать инициализированные и неинициализированные переменные.
Проанализировав эту программу, можно заметить, что она одновременно
содержит код и разные типы данных, которые могут быть как глобальными,
так и локальными переменными. В языке С/С++ секции определяются
неявно, т.е., в отличие от Ассемблера, специальных директив объявления
32
секций нет. Это упрощает программирование, так как функцию создания
нужных секций автоматически берет на себя компилятор. Однако механиз-
мом размещения секций в памяти целевого устройства по-прежнему управ-
ляет пользователь. Из этого правила есть одно исключение — имеются спе-
циальные директивы препроцессора (pragma), которые используются для
явного объявления секций данных, выделяемых под переменные типа
«структура» для резервирования памяти данных под регистры периферий-
ных устройств (рис. 1.10).
Для размещения программного кода в С/С++ используется кодовая секция
.text (как на Ассемблере), для размещения локальных переменных — секция
стека .stack, для размещения глобальных переменных — секция глобальных
переменных .ebss, а для размещения констант, предназначенных для началь-
ной инициализации переменных, — секция констант инициализации .cinit
(см. рис. 1.10).
Кодовые секции должны отображаться на память программ, а секции с
глобальными и локальными переменными — на память данных. Название
каждой секции, как и в Ассемблере, начинается с точки:
• секция глобальных переменных .ebss;
• секция констант для инициализации глобальных переменных .cinit;
• секция локальных переменных, расположенных в стеке, .stack;
• кодовая секция с выполняемыми инструкциями процессора .text.
Как и переменные на языке С/С++, секции могут быть инициализирован-
ными и неинициализированными. Список секций, которые могут создаваться
компилятором С/С++, с краткими комментариями назначения секций, пред-
ставлен в табл. 1.11.
Секция Секция
глобальных констант для
переменных инициализации
Global Vars переменных Init Vals
.ebss .cinit
int x = 2;
int y = 7; Секция
локальных
переменных
void main (void) Local Vars
.stack
{
long z;
z = x + y;
}
Кодовая секция .text
33
Таблица 1.11
Секции, создаваемые компилятором языка С/С++
Отображается Возможное
Имя
Описание назначения на страницу место
секции
памяти размещения
Инициализированные секции
.text Исполняемый программный код Программ ПЗУ или ОЗУ
Page 0 (при отладке)
.cinit Константы для начальной инициализации глобаль- Программ ПЗУ или ОЗУ
ных и статических переменных Page 0 (при отладке)
.pinit Таблицы инициализации глобальных конструкто- Программ ПЗУ или ОЗУ
ров языка С++ Page 0 (при отладке)
.switch Таблицы векторов переходов для операторов пере- Программ ПЗУ или ОЗУ
ключения switch Page 0
(для опции —mt)
Данных
Page 1
.econst Переменные и массивы, жестко установленные как Данных ПЗУ или ОЗУ
константы, например const int k = 3; Page 1 (при отладке)
Неинициализированные секции
.ebss Глобальные и статические переменные Данных ОЗУ
Page 1
.stack Область системного стека, локальные переменные Данных ОЗУ
Page 1
(Младшие 64К)
.esysmem Системная память для функций динамического рас- Данных ОЗУ
пределения памяти Page 1
Секция
.text
Замечания
1. Объекты, которые декларируются в языке СИ как удаленные (far), или
объекты, предназначенные для использования в расширенной памяти (large
memory), должны размещаться в секциях .ebss/.econst. Напротив, близкие
объекты (near objects) могут размещаться в секциях .bss/.const. За размеще-
нием объектов по секциям следит сам компоновщик проекта.
2. Окружение реального времени языка С/С++ поддерживает динамичес-
кое распределение памяти (system heap — «кучи» системы) в начальной
области памяти данных с помощью функции malloc и динамическое распре-
деление памяти в любой области памяти данных с помощью функции
far_malloc. Для реализации этих задач служат секции .sysmem и .esysmem.
MEMORY
{
M0SARAM: origin = 0x000000, length = 0x0400
M1SARAM: origin = 0x000400, length = 0x0400
}
MEMORY
{
PAGE 0:/* Память программ */
FLASH:origin = 0x3D8000, length = 0x20000
PAGE 1:/* Память данных */
M0SARAM: origin = 0x000000, length = 0x0400
M1SARAM: origin = 0x000400, length = 0x0400
}
Дополнительные рекомендации:
1) обязательно указывайте после имени страницы памяти и имени сег-
мента памяти двоеточие;
2) используйте комментарии, как это принято в языке С/С++: начало ком-
ментария /*, конец комментария */. Использование комментариев с операто-
ром // недопустимо;
3) располагайте вложенные записи «лесенкой», что сделает описание
областей памяти целевой платы более наглядным.
Размещение секций
Директива SECTIONS определяет, в какие физические области памяти
целевой платы будут размещены те или иные секции программы. Например,
для размещения секций .text и .cinit во флэш-память, секции .ebss в банк M0
встроенного ОЗУ, а секции .stack — в банк M1 встроенного ОЗУ нужно дать
следующие указания компоновщику:
38
SECTIONS
{
.text:> FLASH PAGE 0
.ebss:> M0SARAM PAGE 1
.cinit:> FLASH PAGE 0
.stack:> M1SARAM PAGE 1
}
MEMORY
{
PAGE 0:/* Память программ */
FLASH: origin = 0x3D8000, length = 0x20000
PAGE 1:/* Память данных */
M0SARAM: origin = 0x000000, length = 0x0400
M1SARAM: origin = 0x000400, length = 0x0400
}
SECTIONS
{
.text:>FLASH PAGE 0
.ebss:>M0SARAM PAGE 1
.cinit:>FLASH PAGE 0
.stack:>M1SARAM PAGE 1
}
Практическая работа
Контрольные вопросы
1. Каково назначение отдельных банков встроенной памяти микроконтроллера?
2. Чем отличается секционирование программы на Ассемблере от секционирования
на языке высокого уровня С/С++?
3. Зачем нужен общий формат объектных файлов, создаваемый Ассемблером и
С/С++?
4. Может ли секция, отображенная на страницу Page 0 (память программ), реально
размещаться в ОЗУ?
5. Может ли секция, отображенная на страницу Page 1 (память данных), реально раз-
мещаться во флэш-памяти?
40
Глава 2
Рис. 2.1. Общий вид окна интегрированной среды CCS при запуске
41
Проект — это набор всех файлов, требуемых для создания исполняемого
выходного файла (.out), который может быть загружен и выполнен на целе-
вой плате. В состав проекта могут входить:
исходные файлы на Ассемблере и на языке С/С++;
файлы с описанием макросов на Ассемблере и на языке С/С++, так назы-
ваемые подключаемые файлы;
файлы в перемещаемом объектном коде, входящие в стандартные библио-
теки или библиотеки пользователя;
командные файлы управления компоновкой.
Важнейшей особенностью проекта является то, что отсутствует необхо-
димость в копировании файлов из разных мест в один каталог. Проект содер-
жит лишь ссылки на фактическое расположение файлов. Это позволяет
любому числу пользователей из любого числа проектов ссылаться на одни и
те же библиотечные файлы, файлы управления компоновкой, не засоряя ком-
пьютер множеством копий одних и тех же модулей.
Работа в среде CCS начинается либо с создания нового проекта путем
выбора пункта меню Project → New, либо с открытия уже существующего
проекта выбором пункта меню Project → Open (рис. 2.2). Работая над про-
ектом, можно постепенно добавлять файлы в проект (подключать файлы к
проекту) с помощью команды Project → Add files to Project. Пользуясь тем же
меню, в конце работы можно сохранить проект Project → Save и закрыть его
Project → Close. Как обычно, при закрытии проекта можно сохранить нара-
ботки или отказаться от сохранения, если накопленная информация не нужна.
Создание нового проекта по команде Project → New выполняется с помо-
щью диалогового окна, изображенного на рис. 2.3, которое позволяет ввести
имя проекта в поле Project Name и задать директорию размещения проекта
в поле Location. Как и во многих других приложениях под Windows, кнопка
«…» позволят вызвать на экран окно «Обзора папок», в котором можно
выбрать нужную директорию из имеющихся или создать новый каталог.
Если указанные в диалоговом окне каталоги и подкаталоги не существуют,
то они будут автоматически созданы. Это одно из удобств, которое предо-
ставляет интегрированная среда.
При вводе имени проекта одновременно в соответствии с вводимым име-
нем меняется название подкаталога последнего уровня, в котором будет раз-
мещен проект. Таким образом, имя проекта будет строго соответствовать
названию каталога для размещения файлов проекта.
42
В диалоговом окне создания нового проекта есть две дополнительные
опции: тип проекта Project Type и целевой микроконтроллер Target. Первая
опция имеет два возможных значения:
• Executable (.out) — создание выходного исполняемого файла в абсо-
лютном объектном коде. Применяется для загрузки и отладки выходного
файла проекта в целевом устройстве;
• Library (.lib) — создание выходного библиотечного файла в перемеща-
емом объектном коде. Применяется для объединения в библиотеку пользова-
теля нескольких уже отлаженных файлов типовых функций. При выборе
этого значения CCS, по существу, работает в качестве программы «библиоте-
каря», интегрируя его возможности.
Вторая опция может иметь три значения, в зависимости от типа целевого
микроконтроллера из семейства ‘C2000, для которого выполняется разра-
ботка программного обеспечения: TMS320C24XX, TMS320C27XX,
TMS320C28XX. Воспользуемся последним значением.
После закрытия диалогового окна создадим файл с расширением .pjt,
который будет содержать все параметры компилятора с языка высокого
уровня С/С++, Ассемблера и компоновщика для процесса сборки проекта.
Вначале эти параметры устанавливаются по умолчанию, а затем в процессе
работы над проектом могут редактироваться. Как уже упоминалось, назва-
ния каталога проекта и собственно файла проекта будут одинаковыми. В
примере, представленном на рис. 2.3, каталог LAB2 будет содержать файл
проекта LAB2.pjt.
При создании нового проекта внутри каталога проекта будет создана
директория Debug (Отладка), в которую в последующем будут записываться
непосредственно исполняемые файлы, полученные в процессе трансляции и
компоновки. Как только новый проект будет создан, появляются как бы вир-
туальные папки, которые могут заполняться в процессе работы над проек-
том, в том числе папка с исходными файлами (Source), с библиотечными
файлами (Libraries), с подключаемыми файлами (Include) и т.п., приведен-
ные на рис. 2.4.
43
Виртуальной папка называется потому, что она может не содержать фай-
лов, а лишь ссылки на их фактическое место расположения. Вначале эти
папки пусты, о чем свидетельствует отсутствие слева от имени папки значка
«+». Если этот значок есть, то папка имеет какое-то содержимое. Щелкнув на
значке «+» кнопкой мыши, можете раскрыть содержимое виртуальной
папки.
Подключить файл к проекту не означает физически скопировать его в
один из каталогов проекта. Как увидите, это касается не только библиотеч-
ных файлов, но и исходных файлов. Конечно, можно создать исходный файл
непосредственно в каталоге Source. Однако, чтобы среда CCS «увидела»
этот файл, его все равно придется подключить к проекту с помощью
команды Project → Add files to Project.
Практическая работа
1. Создайте новый проект для выполнения практической работы № 2.
Выберите в качестве названия проекта имя LAB2 и разместите проект в
каталоге C:\C28X\LABS\LAB2.
2. Проанализируйте содержимое созданного каталога LAB2 и подкатало-
гов, например, с помощью стандартной программы Windows «Проводник».
3. Сохраните проект. Закройте CCS.
4. Вновь запустите среду CCS. Откройте уже созданный проект.
Рис. 2.5. Вызов встроенного редактора для создания файла с исходной программой
44
Рис. 2.6. Первая программа на С/С++
Практическая работа
1. Вызовите встроенный текстовый редактор.
2. В появившемся окне Untitled1, пользуясь стандартными приемами
редактирования, введите текст исходной программы на языке С/С++ (см. гл. 1).
3. Сохраните работу в каталоге LAB2. Убедитесь в том, что программа
выглядит так, как показано на рис. 2.6.
4. Дайте объяснения цветовому выделению фрагментов текста, которые
выполняет встроенный текстовый редактор.
Практическая работа
1. Создайте командный файл компоновщика lab2.cmd, пользуясь возмож-
ностями встроенного текстового редактора. Один из возможных вариантов
файла показан на рис. 2.7.
2. Сохраните файл в каталоге проекта LAB2.
Рис. 2.7. Файл управления компоновкой для отладки программ в кодовом ОЗУ
46
Замечание
В общем случае среди секций, отображаемых на память программ, может
быть и секция .reset. Она является частью библиотеки реального времени
выполнения rts2800_ml.lib. Если после описания размещения этой секции
напечатать TYPE=DSECT, то компоновщик будет игнорировать ее —
не будет размещать.
47
библиотечные файлы в перемещаемом объектном коде (*.l) или отде-
льные, уже оттранслированные ранее, объектные файлы (*.o);
командные файлы управления компоновкой (*.cmd), а также ряд допол-
нительных файлов, в частности файлов данных, используемых при отладке
(*.dat).
При работе с программой на языке С потребуется подключение библио-
теки функций реального времени выполнения, обычно находящейся в ката-
логе C:\ti\c2000\cgtools\lib\rts2800_ml.lib. С ее помощью выполняются
предварительная инициализация процессора, загрузка начальных значений
переменных (предустановка), а также ряд других функций.
Как только какой-то файл подключается к проекту, слева от списка вирту-
альных каталогов проекта, напротив соответствующей папки, появится знак
«+». Так, при добавлении исходного файла знак «+» появится слева от папки
Source, а при добавлении библиотечного файла — слева от папки Libraries.
Щелкнув на виртуальном каталоге мышкой, увидите подключенные к
проекту файлы. Если ошиблись и подключили не тот файл, установите кур-
сор на имя этого файла и вызовите правой кнопкой мыши контекстно-зави-
симое меню. В этом меню есть команда Remote from Project (удалить из
проекта). Выбрав ее, отключите файл.
Если после операции подключения файлов к проекту щелкнуть мышкой
на значке «+» слева от Project в окне проекта, то появится дерево проекта,
содержащее все подключенные к проекту файлы. На рис. 2.10 показано
дерево проекта после подключения к проекту исходного файла с программой
на языке С lab2.c, командного файла управления компоновкой LAB2.cmd и
библиотеки реального времени выполнения rts2800_ml.lib.
Дерево проекта очень удобно для быстрого редактирования исходных
файлов. Можно всего лишь дважды щелкнуть мышкой на имени этого файла
и сразу попасть в режим редактирования или, щелкнув один раз, вызвать
контекстно-зависимое меню, а затем из него — текстовый редактор.
48
Практическая работа
1. Добавьте к проекту LAB2 созданный исходный файл с программой на
языке С lab2.c. Убедитесь, что файл появился в дереве проекта. Отключите
его от проекта с помощью контекстно-зависимого меню и затем подключите
вновь.
2. Добавьте в проект файл управления компоновкой LAB2.cmd. Имя
этого файла появилось в дереве каталогов и файлов проекта. Теперь имеете
возможность открывать и редактировать с помощью встроенного текстового
редактора уже два файла lab2.c и LAB2.cmd. Проверьте эти возможности.
3. Добавьте к проекту библиотеку функций реального времени выполне-
ния, находящуюся в каталоге “C:\ti\c2000\cgtools\lib\rts2800_ml.lib”.
49
Чтобы облегчить процесс настройки опций сборки проекта, CCS предла-
гает графический пользовательский интерфейс настройки опций. На
начальном этапе работы нас вполне удовлетворят установки по умолчанию.
Сейчас исследуем некоторые из них. Если выбрать в меню Project → Build
Options… (Проект → Опции сборки…), то на экране появится окно, приве-
денное на рис. 2.13, с набором опций компилятора (Compiler) по умолчанию
для категории Basic (Основные).
Как видно, для отладочной конфигурации Debug предполагается:
работа центрального процессора в режиме истинного ‘C28xx с использо-
ванием всех преимуществ системы команд этого процессора (процессор
может работать и в других режимах, в частности совместимости с ‘C24xx и
‘C27xx);
полная символьная отладка;
отсутствие каких-либо методов оптимизации программного кода.
В верхней части окна показано, как выглядит установленный список
опций в командной строке вызова компилятора. К счастью, этот набор вво-
дится автоматически самой интегрированной средой CCS и ручного
набора не требуется.
Переключимся на закладку опций компоновщика (Linker), изображенных
на рис. 2.14. Видно, что по умолчанию Code Composer Studio будет создавать
два типа выходных файлов .out и .map. Файл с расширением .out содержит
исполняемый код, загружаемый в DSP-микроконтроллер, а файл .map —
отчет компоновщика по распределению и использованию памяти в целевой
плате. Оба выходных файла будут размещаться в подкаталоге Debug теку-
щего проекта. Опция модели автоинициализации (Autoinit Model) установ-
лена в состояние Run-time Autoinitialization (автоинициализация в реаль-
ном масштабе времени).
Одной из важнейших опций является опция размера стека (Stack Size).
Значение 0x200 в шестнадцатеричной системе счисления соответствует
50
Рис. 2.14. Опции компоновщика по умолчанию
емкости стека в 512 слов. Этого достаточно для большинства простых проек-
тов. Можно, например, увеличить размер стека вдвое, а затем закрыть окно
опций сборки проекта, нажав клавишу ОК. Сделанные изменения будут
сохранены.
Практическая работа
1. Исследуйте различные категории опций компилятора, но пока не
меняйте их.
2. В опциях компоновщика увеличьте вдвое размер стека до 1 К слова.
Сохраните настройки.
51
Табл и ц а 2.1
Назначение клавиш управления компиляцией и сборкой проекта
52
Рис. 2.17. Установка опции автоматической загрузки программы после сборки
Практическая работа
1. Выполните компиляцию исходного файла lab2.c. Убедитесь в том, что
ошибок нет.
53
Рис. 2.18. Сообщение об ошибке компиляции
MEMORY CONFIGURATION
name origin length used attr fill
---------------------- -------- -------- -------- ---- --------
PAGE 0: H0SARAM 003f8000 00002000 000000c7 RWIX
PAGE 1: M0SARAM 00000000 00000400 00000200 RWIX
M1SARAM 00000400 00000400 00000086 RWIX
Практическая работа
1. Средствами операционной системы, например, с помощью «Провод-
ника» исследуйте содержимое каталога LAB2. Есть ли там автоматически
созданный подкаталог Debug (Отладка)? Содержатся ли в нем следующие
файлы: LAB2.obj — выходной объектный файл в перемещаемом объектном
58
коде, созданный компилятором; LAB2.out — исполняемый выходной файл в
неперемещаемом объектном коде, созданный компоновщиком; LAB2.map —
файл с картой загрузки?
2. Проанализируйте содержимое файла с картой загрузки. Правильно ли
распределена память микроконтроллера? Соответствует ли это распределе-
ние содержимому командного файла lab2.cmd?
3. Распределены ли секции программы в соответствии с указаниями в
командном файле lab2.cmd?
59
отображения в окне «дампа» памяти содержимого локальной переменной z
из программы lab2.c необходимо в поле адреса (Address:) ввести &z, что на
языке С/С++ означает адрес переменной z (а не ее значение). Помните, что
Code Composer Studio отличает символы, написанные в верхнем и нижнем
регистрах. Если записать в поле адреса &z, то получим сообщение об
ошибке, так как переменная z не определена (имя z в процессорах ‘C28 носит
специальный битовый флаг нулевого результата текущей операции).
В поле Format (Формат) можно задать желаемый стиль отображения
данных, например: Hex — C Style (шестнадцатеричные данные в формате
языка С/С++) или Hex — TI Style (шестнадцатеричные данные в формате
фирмы Texas Instruments, стандартном для микропроцессорной техники).
Если необходимо интерпретировать данные в памяти как 16-разрядные
целые числа со знаком в дополнительном коде, то выберите формат 16-Bit
Signed Int. Имеется возможность отображать содержимое памяти и в стан-
дартном формате числа с плавающей точкой (Use IEEE Float). При этом
подразумевается, что под каждое число такого типа выделены две последо-
вательные ячейки памяти (длинное слово). На рис. 2.23 показаны различные
форматы отображения содержимого области памяти с интересующей нас
локальной переменной z.
В диалоговом окне опций «дампа» памяти в поле Page (Страница) указы-
вается нужная страница памяти (память программ или память данных). Так
как переменная z расположена в ОЗУ, то указывается страница памяти дан-
ных (Data). Нажав кнопку OK, увидите, что окно «дампа» памяти открылось
и начальный адрес указывает на переменную z.
Рис. 2.22. Диалоговое окно опций «дампа» Рис. 2.23. Варианты отображения содержи-
памяти мого памяти
60
В нашем примере переменная z явля-
ется локальной и расположена в стеке, а
ее адрес совпадает с дном стека. Напом-
ним, что сегмент стека разместили в банке
M0 ОЗУ, начиная с адреса 0x0000. Стек в
процессорах ‘C28xx увеличивается в
направлении от младших адресов к стар-
шим.
В процессе отладки программы можно
быстро изменять содержимое памяти по Рис. 2.24. Диалоговое окно редактирова-
любому адресу, используя двойной щел- ния памяти
чок мыши на содержимом нужной ячейки
памяти. При этом открывается диалоговое окно редактирования памяти,
изображенное на рис. 2.24, которое позволяет модернизировать значение не
только в текущей ячейке, но и в других последовательно расположенных за
ней (вверх или вниз) ячейках памяти.
Отредактированное значение автоматически выделяется в окне «дампа»
памяти красным цветом как напоминание программисту о том, что данные
были изменены.
Для удобства интерпретации данных можно менять текущий формат
отображения данных, например от шестнадцатеричной формы представле-
ния переходить к десятичной. Для этого необходимо, находясь в окне
«дампа» памяти (когда окно активно), щелкнуть правой кнопкой мыши для
вызова контекстно-зависимого меню и выбрать команду Properties (Свой-
ства). Появится уже знакомое окно Memory Window Options (Опций окна
памяти), в котором из выпадающего меню следует выбрать желаемый фор-
мат представления данных. Таким образом, в процессе отладки нет необхо-
димости пользоваться дополнительными средствами, например калькулято-
ром, — все операции по переводу чисел из одной системы счисления в
другую будет выполнять интегрированная среда CCS.
Практическая работа
1. Выполните переход на главную программу main(). Убедитесь в том, что
окно исходной программы на С/С++ открылось и программа готова к
отладке.
2. Откройте окно «дампа» памяти данных для наблюдения за значением
переменной z. Поэкспериментируйте с различными форматами представле-
ния данных, пользуясь контекстно-зависимым меню, прокомментируйте
полученные результаты.
3. Попробуйте модифицировать значения в отдельных ячейках памяти
данных и в определенной непрерывной области.
4. Закройте окно «дампа» памяти и откройте его вновь, указав в качестве
начального адреса области памяти текущее содержимое указателя стека SP.
Объясните, почему в этом случае символ & перед SP не ставится? Какая
область памяти отображается в окне? Почему?
61
Следующим типом окна, которое широко используется при отладке про-
грамм на языке С/С++, является окно наблюдаемых переменных (watch
window), изображенное на рис. 2.25. Для того чтобы отобразить в таком окне
значение локальной переменной z, нужно выбрать пункт меню View Watch
Window (Просмотр → Окно наблюдения) и щелкнуть мышкой на закладке
Watch Locals (Наблюдаемые локальные переменные).
Окно Watch Window будет по умолчанию содержать локальные перемен-
ные для текущей выполняемой функции. Напомним, что все локальные пере-
менные располагаются в стеке. В языке С/С++ при вызове любой функции
автоматически выделяется место в стеке под локальные переменные этой
функции. После передачи результатов в вызывающую функцию место в
стеке автоматически высвобождается.
Текущее значение локальной переменной можно изменять и в окне
наблюдаемых переменных, что значительно удобнее, чем в окне «дампа»
памяти. Для этого нужно щелкнуть кнопкой мыши в столбце Value (Значе-
ние) в строке с именем переменной z для активизации режима редактирова-
ния, ввести новое значение переменной и завершить ввод нажатием клавиши
Enter. Можно также изменить формат отображения данных. Для этого
достаточно щелкнуть мышью в позиции Radix (Основание системы счис-
ления) и выбрать требуемую форму представления, приведенную на
рис. 2.26: шестнадцатеричное (hex), десятичное (dec), двоичное (bin) или
восьмеричное число (oct), символ (char), число в формате с плавающей точ-
кой (float), в научном формате высокой точности (scientific), число без знака
(undigned).
Вторая закладка Watch1 в окне наблюдаемых переменных Watch Window
предназначена для добавления глобальных переменных (см. рис. 2.25). Если
выбрать эту закладку и щелкнуть левой кнопкой мыши в пустом контейнере
в колонке Name (Имя), то откроется поле ввода, в котором можно будет
набрать имя интересующей нас переменной, завершив ввод имени нажатием
клавиши Enter. Операцию добавления глобальных переменных можно мно-
гократно повторять. Знак & перед символическим именем глобальной пере-
менной не ставится. В колонке Value (Значение) выводятся текущие значе-
62
Рис. 2.27. Окно наблюдаемых глобальных переменных
Практическая работа
1. Откройте окно локальных переменных Watch Locals. Модифицируйте
значение локальной переменной z. Убедитесь в том, что адекватные измене-
ния происходят и в окне «дампа» памяти.
2. Добавьте в окно наблюдаемых переменных глобальные переменные x и
y. Соответствуют ли их текущие значения начальным значениям, указанным
в программе?
3. Откройте второе окно Watch 1 «дампа» памяти, указав в качестве
начального адреса &y. Проверьте, что значения наблюдаемых переменных в
окне Watch Window такие же, как в окне «дампа» памяти Memory Window,
приведенном на рис. 2.28. Опробуйте механизм редактирования значений
глобальных переменных. Убедитесь, что изменение значения переменной в
одном из окон автоматически приводит к изменению его значения в другом
окне, а модифицированные значения переменных подсвечиваются красным
цветом.
4. Исследуйте файл с картой загрузки lab2.map и убедитесь, что адреса
размещения глобальных переменных x и y действительно 0x0485 и 0x0484.
5. В какой области встроенного ОЗУ компоновщик разместил глобальные
переменные?
63
2.9. ВЫПОЛНЕНИЕ ПРОГРАММЫ ПО ШАГАМ
Выполнение функции main() по шагам осуществляется с помощью горя-
чей клавиши F8 или кнопки Single Step на вертикальной панели инструмен-
тов. Желтая стрелка в окне исходной программы на С/С++ указывает на
текущий активный оператор. Информация в окнах памяти и наблюдаемых
переменных автоматически обновляется, что позволяет проконтролировать
ход выполнения программы и дать заключение о ее работоспособности.
встроенного ОЗУ, отведенного нами под память программ. Для того чтобы
понять ассемблерный код, сгенерированный компилятором, необходимо
знать унифицированный принцип выделения места под локальные перемен-
ные и порядок доступа к ним:
• место под локальные переменные называется фреймом локальных пере-
менных и всегда резервируется в стеке в начале выполнения любой функ-
ции, в том числе функции main;
• резервирование выполняется за счет инкрементирования указателя
стека SP на величину, равную длине фрейма локальных переменных в коли-
честве слов памяти, выделенных под эти переменные. При этом указатель
стека всегда будет показывать на «первую свободную ячейку памяти», не
относящуюся к фрейму локальных переменных;
• доступ к любой локальной переменной внутри фрейма производится с
помощью стековой базовоиндексной предекрементной адресации —
SP[index], где функцию базы выполняет указатель стека SP, а индекс — зада-
ется явно;
• перед выходом из функции место в стеке, выделенное под локальные
переменные, высвобождается. Это делается с помощью декрементирования
указателя стека SP на величину, равную длине фрейма локальных переменных.
Дадим покомандный комментарий к программе на Ассемблере.
1. В программе используется одна локальная переменная z типа long. Поэ-
тому фрейм локальных переменных имеет длину 2 (два слова). Чтобы выде-
лить место под локальную переменную, указатель стека SP нужно дважды
инкрементировать:
65
ADDB SP, #2 ;Сложение содержимого указателя стека
;с байтовой константой 2
;Константа перед сложением расширяется
;слева нулями до слова
Практическая работа
1. Исследуйте работу программы в пошаговом режиме при различных
наборах входных переменных: (x, y) = (2, 5); (32766, 1); (32766, 2); (–1, –2);
(–32767, –1); (–32767, –2).
2. Объясните результат. К сожалению, его нельзя предсказать, глядя на
программу, написанную на языке С/С++. Для сохранения результата специ-
ально выбрали 32-разрядную переменную, чтобы учесть возможные пере-
полнения.
3. Подумайте, как же быть, если необходим 32-разрядный результат с уче-
том возможных переполнений.
Контрольные вопросы
1. Чем отличаются локальные переменные от глобальных и где они размещаются?
2. Зачем необходимо подключать к проекту библиотеку реального времени?
67
Глава 3
68
В этом простом примере переменная i типа целое (int) всего лишь один
раз инкрементируется. Для обозначения операции инкрементирования в
языке Си применяются два подряд набранных символа «плюс» ++, а для
обозначения операции декрементирования — два подряд набранных знака
«минус» – –. Таким образом, оператор i++; эквивалентен оператору i = i + 1;.
В общем случае программа на языке Си состоит из одной или более функ-
ций. Каждая функция создается для решения определенной подзадачи и
может быть вызвана из главной функции. Эти функции могут описываться
как в текущем файле, так и в каком-либо другом файле. Кроме того, ряд
наиболее важных функций может быть предварительно разработан, отлажен
и включен в библиотеку стандартных функций. Библиотеки стандартных
функций обычно поставляются разработчиками компилятора Си или разра-
ботчиками микроконтроллера, а пользовательские библиотеки создаются
программистами для решения своих типовых задач.
Функциям можно давать любые имена по усмотрению разработчика, но
main — это особое имя — главная, основная функция. Выполнение любой
программы всегда начинается с главной функции. Каждая программа на
языке Си должна содержать эту функцию. Из главной программы можно
вызывать другие функции, описанные в текущей программе, а также библио-
течные функции.
Круглые скобки, следующие за именем функции, содержат список аргу-
ментов функции. Если функция не имеет аргументов, как в примере выше, то
скобки все равно нужно указывать (). Все операторы, входящие в тело функ-
ции, заключаются в фигурные скобки { }. Обращение (вызов) функции осу-
ществляется указанием ее имени, вслед за которым следует заключенный в
круглые скобки список аргументов.
В языке Си предполагается, что все переменные должны быть обяза-
тельно описаны до момента их использования. Обычно это делается в начале
функции до первого выполняемого оператора. Если забудете вставить описа-
ние какой-либо переменной, то получите диагностическое сообщение об
ошибке в процессе трансляции программы.
Для ввода комментария в языке Си используются либо два подряд распо-
ложенных символа косой черты // (если комментарий не переходит на дру-
гую строку), либо специальные символы начала /* и конца комментария */.
Все операторы программы на языке Си заканчиваются точкой с запятой.
Мы постепенно будем изучать базовые возможности языка Си.
Типы данных
В языке Си имеется несколько стандартных типов данных: int — целое
число; float — вещественное число в формате с плавающей точкой одинарной
точности; char — символ. Имеется также ряд квалификаторов стандарт-
ных типов: short (короткое), long (длинное), unsigned (беззнаковое),
signed (знаковое). Квалификаторы типа short и long указывают на различные
размеры переменных, а квалификаторы signed и unsigned — на формат
представления — число со знаком в дополнительном коде или число без
знака соответственно.
Перечень скалярных типов данных, поддерживаемых процессором
TMS320x28xx, с указанием длины и способа представления переменной
каждого типа, а также диапазона возможного изменения значений перемен-
ных, представлен в табл. 3.1.
Табл и ц а 3.1
Типы данных языка Си, поддерживаемые компилятором ‘C28xx
Диапазон
Тип Длина Представление
Минимум Максимум
char, signed char 16 бит Код ASCII –32768 32767
символьный, знаковый символьный
unsigned char 16 бит Код ASCII 0 65535
беззнаковый символьный
short 16 бит 2s complement –32768 32767
короткий Дополнительный код
unsigned short 16 бит Binary 0 65535
беззнаковый короткий Двоичный код
int, signed int 16 бит 2s complement –32768 32767
целый, знаковый целый Дополнительный код
unsigned int 16 бит Binary 0 65535
беззнаковый целый Двоичный код
long, signed long 32 бита 2s complement –2 147 483 648 2 147 483 647
длинный, знаковый длинный Дополнительный код
unsigned long 32 бита Binary 0 4 294 967 295
беззнаковый длинный Двоичный код
enum 16 бит 2s complement –32768 32767
перечисление, целый Дополнительный код
float 32 бита Формат IEEE 32 бита 1,17549435e–38 3,4028235e+38
вещественный
double 32 бита Формат IEEE 32 бита 1,17549435e–38 3,4028235e+38
вещественный двойной точности
long double 32 бита Формат IEEE 32 бита 1,17549435e–38 3,4028235e+38
вещественный длинный двойной
точности
pointers 16 бит Binary 0 0xFFFF
указатель Двоичный код
far pointers 22 бита Binary 0 0x3FFFFF
длинный указатель Двоичный код
70
Примеры описаний переменных с различными квалификаторами типа
приведены ниже:
short int a;
long int b;
unsigned int result;
Замечания
75
В примере лист. 3.2 переменной x сначала будет присвоено текущее зна-
чение переменной n (т.е. 5), а затем значение переменной n увеличится на
единицу (операция постинкрементирования). Таким образом, переменная x
будет равна пяти, а переменная n — шести.
Контрольные вопросы
1. Объясните термины «преинкрементирование», «постдекрементирование».
2. Подумайте и скажите, чему будут равны переменные x, y и z после выполнения
кода лист 3.4.
Логические операции
В языке Си следует различать два вида логических операций:
логические операции, которые выполняются над булевыми переменными
с получением булевого результата;
побитовые логические операции, которые могут выполняться одновре-
менно над всеми битами слова с получением результата также в виде слова.
Список логических операций первого типа приведен в табл. 3.3.
В логических выражениях можно использовать любое число условий,
связанных между собой логическими операциями. Таких операций три:
Логическое И (&&), Логическое ИЛИ (||) и Логическое НЕ (!).
Табл и ц а 3.3
Логические операции
76
Выражения, связанные операциями && и ||, вычисляются слева направо,
причем их рассмотрение прекращается сразу же, как только становится ясно,
будет ли результат истиной или ложью:
Старшинство операции && выше, чем ||, и обе они младше операций
отношения и равенства.
Унарная операция отрицания ! преобразует ненулевой или истинный опе-
ранд (true) в 0 (false), а нулевой или ложный операнд (false) в 1 (true).
Рассмотренные логические операции применяются, главным образом,
при вычислении логических выражений, которые в свою очередь применя-
ются в условных операторах и операторах организации циклов.
77
Следует быть внимательным и отличать побитовые логические операции
& и | от логических операций над булевыми переменными && и ||. Напри-
мер, пусть имеем две переменные типа int: a=1 (0001b) и b=2 (0010b).
Результат операции побитового «И» a&b даст нулевое значение, в то время
как результат вычисления логического выражения a&&b окажется равным
единице. Это объясняется тем, что с точки зрения языка Си любое число,
отличное от 0 в логическом выражении, рассматривается как истина (true).
Примеры использования поразрядных операций приведены в Лист. 3.6.
Табл и ц а 3.5
Операции отношения и сравнения
78
Оператор присваивания
В языке Си символом оператора присваивания является знак =. В одном
операторе присваивания можно присвоить одно и то же значение многим
переменным. Для этого используется оператор множественного присваива-
ния, например:
x=z=y=0;
В программах на Си широко используются операторы составного присва-
ивания: вначале над переменной выполняется указанная перед символом =
арифметическая или логическая операция, после чего результат операции
сохраняется в переменной. Составное присваивание выполняется в режиме:
«Чтение старого значения переменной — Модификация — Запись нового
значения». При этом оператор присваивания становится более компактным.
Например, операция увеличения значения переменной x на пять может
выглядеть следующим образом:
x=x+5;
а при использовании оператора составного присваивания:
x+=5;
Варианты составных операций присваивания приведены в табл. 3.6
Обратите внимание, что операции поразрядной конъюнкции И, дизъюнк-
ции ИЛИ и Исключающего ИЛИ задаются с помощью символов &, | и ^
соответственно. В приведенных примерах для четырех младших битов пере-
менной y производятся: очистка, установка и побитовое инвертирование
соответствующих разрядов.
Табл и ц а 3.6
Операции присваивания
79
3.2. ИСПОЛЬЗОВАНИЕ СТАНДАРТНЫХ БИБЛИОТЕК
Практическая работа
1. Найдите в каталоге include заголовочный файл библиотеки стандарт-
ного ввода/вывода stdio.h и попытайтесь проанализировать его содержимое.
2. Есть ли в списке функций ввода/вывода функции для работы с фай-
лами: открыть — fopen, закрыть — fclose, переименовать — rename, уда-
лить — remove и т.д.?
3. Функции ввода/вывода символов и строк, например чтения символа со
стандартного устройства ввода — getchar?
4. Функции форматируемого ввода/вывода, например printf и scanf?
82
%x — аргумент преобразуется в формат беззнакового шестнадцатерич-
ного числа (без лидирующих 0x);
%u — аргумент преобразуется в формат беззнакового десятичного числа;
%c — аргумент рассматривается как отдельный символ;
%s — аргумент является строкой: символы строки печатаются до тех пор,
пока не будет достигнут нулевой символ или не будет напечатано количество
символов, указанное в спецификации точности;
%e — аргумент, рассматриваемый как переменная типа float, преобразу-
ется в десятичную форму в виде экспоненциальной записи
[–]M;NNNNNNE[+–]XX, где число символов после десятичной точки N
определяется указанной точностью. Точность по умолчанию равна 6;
%f — аргумент, рассматриваемый как переменная типа float, преобразу-
ется в десятичную форму в виде [–]MMM.NNNNN, где число символов
после десятичной точки N определяется указанной точностью. Точность по
умолчанию равна 6.
Между символом % и символом преобразования могут находиться так
называемые модификаторы преобразования:
• знак «минус», который указывает на необходимость выравнивания зна-
чения преобразованного аргумента по левому краю его поля. Если этот знак
не указывается, значение автоматически выравнивается по правому краю
поля;
• строка цифр, задающая минимальную ширину поля для вывода значе-
ния. Если преобразованный аргумент имеет меньше символов, чем указан-
ная ширина поля, то он будет дополнен слева (или справа, если было указано
выравнивание по левому краю с помощью знака –) заполняющими симво-
лами до этой ширины. Заполняющим символом обычно является пробел, а
если ширина поля указывается с лидирующим нулем, то этим символом
будет нуль (лидирующий нуль в данном случае не означает восьмеричного
формата представления числа);
• точка, которая отделяет ширину поля от следующей строки цифр,
используемой для задания точности (для типов данных с плавающей точкой);
• точность (строка цифр), которая указывает на максимальное число сим-
волов, выводимых справа от десятичной точки для переменных типа float;
• модификатор длиной l, который указывает, что соответствующий эле-
мент данных имеет тип long, а не int.
Если идущий за символом % символ не является символом преобразова-
ния, то печатается сам этот символ. Следовательно, символ % можно напе-
чатать, указав % %.
Приведем простые примеры. Предположим, что на экран необходимо
вывести текущие значения трех целочисленных переменных i, j, k в виде
обычного десятичного числа и выполнить перевод строки:
printf(“i= %d; j= %d; k= %d;\n”, i, j, k);
Обратите внимание, что формат обращения к функции следующий:
printf(“Управляющая строка”, аргумент1, аргумент2, и
т.д.);
83
При этом управляющая строка представляет собой строку символов в
кавычках — фразу, которая показывает, как и в каком месте должны быть
напечатаны перечисленные вслед за управляющей строкой аргументы.
В качестве аргументов могут использоваться константы, переменные или
выражения. В последнем случае значения выражений вычисляются непо-
средственно перед выводом на экран. Функция printf() использует управля-
ющую строку для определения числа последующих аргументов. Их число
должно строго соответствовать числу вхождений символов % в управляю-
щую строку. Если количество аргументов окажется недостаточным или они
будут иметь несоответствующие типы, то будет выдано сообщение об
ошибке.
Еще один пример. Предположим, что переменная x является переменной
с плавающей точкой и на экран необходимо вывести ее значение в десяти-
чной форме записи в поле размером 10 символов, включая десятичную
точку, и точностью числом десятичных цифр справа от десятичной точки,
равной 4:
84
Окончание лист. 3.8
/* Основная программа */
main() /* Главная функция программы */
{ /* Текст программы — подсчет суммы двух чисел */
a = 10;
b = 5;
result = a + b; /* Подсчет суммы двух чисел */
}
Отладку интересующего нас фрагмента программы удобно выполнять в
бесконечном цикле:
while(1) /* Бесконечный цикл. */
{
result = a + b; /* Расчет суммы двух чисел. */
}
При этом, открыв окно содержимого памяти или окно наблюдаемых пере-
менных, можно менять исходные значения аргументов и в реальном времени
наблюдать за результатом расчета. Результат можно вывести или в окно
наблюдаемых переменных, или в окно Stdout с использованием функции
printf().
Для организации бесконечного цикла применяют оператор while с усло-
вием, равным истине (1).
Практическая работа
1. Выполняя предыдущую практическую работу (см. с. 81), Вы обратили
внимание на существование каталога, специально предназначенного для раз-
мещения проектов пользователей c:\ti\myprojects. В этом каталоге будут
размещаться и Ваши проекты. Создайте подкаталог с именем \username по
нескольким первым буквам вашей фамилии, например \petrov. Для каждой
новой работы организуйте отдельный подкаталог. Например, для текущей
работы создайте подкаталог \lab3. Напоминаем, что формирование каталогов
можно выполнить и автоматически в процессе создания нового проекта (п. 3).
2. Запустите Code Composer Studio. В открывшемся окне менеджера
параллельной отладки выберите либо режим симулятора F2812 Device
Simulator/CPU (программно-логической модели), либо режим эмулятора
F2812 PP Emulator/CPU_1, если целевая отладочная плата eZdsp28 подклю-
чена к параллельному порту компьютера и питание подано (рис. 3.2).
3. Создайте новый проект lab3.pjt с использованием команд меню
Project → New в каталоге ваших проектов.
85
Рис. 3.2. Окно менеджера параллельной отладки
86
6. Выполните процедуру подключения
к проекту командного файла управления
компоновкой Linker Command File
(*.cmd), созданного в предыдущей прак-
тической работе lnk.cmd (из соответству-
ющего каталога без операции копирова-
ния), а также файла библиотеки реального
времени выполнения rts2800_ml.lib.
7. Откройте список содержимого вашего
проекта, щелкая на значки + рядом с
Project, lab3.pjt, Libraries и Source. Убе-
дитесь, что проект содержит все необхо-
димые файлы (рис. 3.4).
Замечание
Если на экране CCS отсутствует окно
менеджера проекта, выберите команду
меню View → Project. Если в данный
Рис. 3.4. Окно «дерева» проекта
момент в окне менеджера проекта
выбрана иконка Bookmarks (Закладки),
щелкните на иконке File внизу плана проекта.
87
Для нормальной работы функции форматированного ввода/вывода потребо-
вался дополнительный объем памяти более 2К слов.
Во втором сообщении указывается, что для размещения динамической
памяти данных (кучи) также не хватило места: секция .system размером
0400h не поместилась в банке статического ОЗУ M0SARAM, выделенном
под стек.
Третье сообщение является следствием первых двух и свидетельствует о
том, что выходной исполняемых файл lab3.out не был создан.
Дело в том, что подключили стандартную библиотечную функцию и не
учли, что такое подключение потребует определенных ресурсов памяти.
Придется изменить командный файл компоновщика. Лучше создать
новый файл с учетом возникших дополнительных потребностей в памяти.
Для ускорения работы можно воспользоваться примером файла, рекомендуе-
мого фирмой TI для целей отладки программ в среде CCS (рис. 3.6). Пере-
именуем этот файл в lab3.cmd и снабдим комментариями на русском языке.
Как видите, мы существенно расширили объем памяти данных за счет
включения двух последовательно расположенных банков L0 и L1 встроен-
ного ОЗУ объемом по 4К слова каждый. Общий объем дополнительной
памяти в объединенном блоке L0L1RAM составляет 8К слов.
Все секции данных для размещения глобальных и статических перемен-
ных .ebss, констант .econst, а также динамически распределяемой памяти
.esystem будем размещать в этом новом блоке памяти L0L1RAM.
Контрольные вопросы
1. Объясните назначение всех секций, описанных в командном файле.
2. Почему секция .cinit должна размещаться в памяти программ?
3. В какую секцию должны попасть переменные a, b, result нашей программы?
Практическая работа
1. Отключите от проекта файл lab2.cmd и подключите к проекту файл
lab3.cmd. Выполните перекомпиляцию и сборку проекта Rebuild All. Убеди-
тесь, что в окне Build теперь отсутствуют сообщения об ошибках. Это окно
после автоматической загрузки программы в память целевой платы имеет
две закладки: Build и Sdtout. Вторая закладка имитирует терминал пользо-
вателя, на который будут выводиться все сообщения из вашей программы по
команде форматированного вывода printf().
2. Убедитесь в том, что в результате трансляции создан выходной испол-
няемый файл lab3.out, а также файл с картой загрузки lab3.map. Место рас-
положения этих файлов по умолчанию — директория \Debug.
3. Откройте файл lab3.map непосредственно из среды CCS (File → Open)
и выпишите адреса размещения переменных a, b, result в памяти данных
(они нам понадобятся в процессе отладки).
4. На основе информации в файле lab3.map проанализируйте распределе-
ние секций нашей программы по банкам памяти микроконтроллера. Соответ-
ствует ли оно командному файлу? Сколько дополнительного места в кодовой
памяти и памяти данных потребовалось для «обслуживающих» программ?
88
а)
б)
Практическая работа
1. Загрузите и выполните программу в пошаговом режиме. Откройте окно
наблюдаемых переменных и следите за ходом процесса.
2. Выполните программу в режиме прогона. Обновляйте значения пере-
менных a и b, контролируйте результат result в окне наблюдаемых перемен-
ных и в окне эмулятора терминала Stdout.
3. Модернизируйте программу для одновременного вывода на терминал
не только результата операции, но и значений операндов. Поэксперименти-
руйте с различными форматами вывода.
Практическая работа
1. Откройте окно наблюдаемых переменных Watch, как Вы это делали в
гл. 2. Добавьте в него переменные a, b и result.
2. Попробуйте установить точку останова, пользуясь меню CCS.
3. Исследуйте второй способ установки и снятия точек останова с помо-
щью кнопки мыши.
4. Проверьте правильность выполнения программы на различных набо-
рах исходных операндов.
5. Модернизируйте программу для исследования других математических
операций, описанных в табл. 3.2. Задайте аргументы функции printf() таким
образом, чтобы на экране одновременно отобразились значения входных
переменных и значения результатов нескольких математических операций,
например, чтобы вывод на экран выглядел следующим образом:
a = 35; b = 4; a + b = 39; a – b = 31; aæb = 140.
91
3.8. ДОПОЛНИТЕЛЬНЫЕ ВОЗМОЖНОСТИ ПО ИЗУЧЕНИЮ
СИСТЕМЫ КОМАНД МИКРОКОНТРОЛЛЕРА ‘C28x
Практическая работа
92
Рис. 3.9. Программа lab3_0.c в CCS в режиме MIX MODE
93
Теперь можно выбрать конкретную команду, руководствуясь содержимым
поля операндов. Команда ADD AL, @6 относится к классу команд, работаю-
щих с 16-разрядным аккумулятором AX. Это обозначение является общим
для обозначения как младшего слова аккумулятора AL, так и старшего слова
AH. Символическое обозначение loc16 применяется для обозначения любого
операнда в памяти данных, адресуемого с применением разрешенного в про-
цессоре способа адресации. В нашем случае это будет прямая страничная
адресация. Итак, выбираем первую команду ADD AX, loc16 и получаем
справку по ее применению (см. рис. 3.10).
Вся справочная информация по командам процессора построена одно-
типно:
• даются возможные варианты синтаксиса команды; приводится оптокод
команды, причем символ A является битовым адресом старшего или млад-
шего слова аккумулятора, а символы LLLL LLLL задают фактически исполь-
зуемый в команде способ адресации операнда; указывается, в каком объект-
ном режиме работы процессора команда может быть использована (символ
X предназначен для любого режима работы); отображается возможность
включения команды в цикл повторения RPT; приводится длительность
выполнения команды в числе циклов CYC;
• описываются операнды команды;
• приводится краткое описание действий, выполняемых командой;
• дается информация о модернизации командой флагов процессора;
• указывается возможность включения команды в цикл повторения;
• приводится простой пример использования команды с комментариями.
Ясно, что наша команда выполняет сложение содержимого 16-разрядного
аккумулятора AL с содержимым прямоадресуемой ячейки памяти данных по
адресу, смещенному относительно начала текущей страницы данных на 6
(короткий адрес операнда на странице), и записывает результат сложения
обратно в аккумулятор AL. По результатам операции сложения вырабатыва-
ются признаки отрицательного N и нулевого результата Z, переноса С и
переполнения V. Флаг С используется для анализа переполнений при работе
с числами без знака, а флаг V — для анализа переполнений при работе с чис-
лами со знаком в дополнительном коде.
Отладочная среда CCS позволяет быстро вывести на экран текущее зна-
чение регистров процессора без необходимости открывания специального
окна содержимого регистров Registers. Для этого, находясь в окне с исход-
ным кодом программы, достаточно лишь установить курсор на символичес-
ком имени регистра процессора, например AL. Его текущее содержимое
будет немедленно выведено на экран в прямоугольной рамке. К сожалению,
эта великолепная возможность не предусмотрена для переменных в памяти.
Более того, установив курсор на метку L1 в команде безусловной пере-
дачи управления SB L1, UNC, получите информацию о фактическом значе-
нии метки L1: L1=0x003F8006. Это означает, что команда короткого безу-
словного относительного перехода вернет управление по адресу
0x003F8006.
94
Таким образом, интегрированная среда CCS предоставляет разработчику
программного обеспечения великолепные возможности по изучению сис-
темы команд процессора и отладке программ как на языке высокого уровня
Си, так и на Ассемблере.
Практическая работа
1. Проанализируйте ассемблерные команды, встречающиеся в программе.
Имейте в виду, что все наши переменные являются глобальными и разме-
щены компоновщиком по следующим адресам: _a: 8086h; _b: 8084h;
_result: 8085h. Для доступа к ним применяется прямая страничная адреса-
ция. Каждая страница имеет длину 64 слова (40h). Таким образом, перемен-
ные размещаются на странице памяти с номером 8084h div 40h = 0202h.
Именно это значение используется для инициализации указателя текущей
страницы данных DP. Короткий прямой адрес переменной _а на текущей
странице памяти равен 6, переменной _b: 4, а переменной _result: 5.
2. Правильно ли мы дали комментарий к ассемблерным командам — лист. 3.7.
3. Откройте окна содержимого регистров ядра процессора View →
→ Registers → Core и статусных регистров View → Registers → Status,
окно наблюдаемых переменных. Выполните программу по шагам, наблюдая
за содержимым аккумулятора, указателя текущей страницы DP, флагов
результатов операций: Z, N, C, V, а также собственно переменных a, b, result.
Объясните результаты для различных наборов переменных, например, ука-
занных в табл. 3.7.
95
4. Убедитесь в том, что среда CCS позволяет быстро получить информа-
цию о текущем состоянии регистров процессора и значениях меток в коман-
дах передачи управления.
5. Исследуйте программу, которую Вы написали для изучения других
арифметических операций в табл. 3.2 с точки зрения реализации ее на
Ассемблере. Выполните отладку.
6. Поэкспериментируйте с различными вариантами записи операторов
присваивания, модернизировав исходную программу (см. табл. 3.3).
Контрольные вопросы
1. В чем преимущества и недостатки рассмотренных в этой работе способов отладки
программного обеспечения с использованием стандартной библиотеки ввода/вывода?
2. Сравните методы отладки программы в пошаговом режиме и с точками останова.
3. Какие действия будут выполнены следующим оператором на языке Си: x += y; ?
4. Как получить информацию о текущем содержимом регистров процессора XAR1,
SP? Укажите минимум две возможности.
96
Глава 4
98
Каждый вариант case может помечаться целой или символьной констан-
той или константным выражением. Не допускается использование одина-
ковых константных выражений. Константные выражения не должны содер-
жать ни переменных, ни вызовов функций, так как вычисляются на этапе
компиляции программы.
Если значение выражения не соответствует ни одной константе в вариан-
тах case, то выполняются операторы, следующие за словом default, т.е. опе-
раторы по умолчанию. Это необязательная часть оператора-переключателя
switch, которая может отсутствовать.
Если значение выражения не соответствует ни одной константе, то ника-
ких действий не выполняется и управление передается следующему опера-
тору программы.
Оператор переключения имеет одну очень важную особенность: ключе-
вое слово case вместе с константой выполняет всего лишь функцию метки,
на которую передается управление для некоторого варианта значения выра-
жения. Поэтому будут выполняться не только операторы для текущего вари-
анта case, но и для всех последующих вариантов. Для выхода из переключа-
теля после выполнения необходимого оператора case служит специальный
оператор прерывания break, который необходимо поставить в конце выполне-
ния последовательности операторов case, как показано в примере лист. 4.6.
Цикл for
При организации любого цикла, тело которого должно быть выполнено
заданное число раз, обязательно необходимы следующие три действия:
1) инициализация счетчика числа циклов;
2) сравнение текущего значения счетчика числа циклов с некоторым гра-
ничным значением для определения момента завершения цикла;
3) инкрементирование (или декрементирование) счетчика числа циклов
при каждом выполнении тела цикла.
В циклах while заботу о сравнении берет на себя условное выражение.
Приращение текущего состояния счетчика числа циклов реализуется либо в
теле цикла отдельной командой (см. лист. 4.10), либо с помощью «попутной»
операции инкрементирования/декрементирования непосредственно при
вычислении условного выражения, приведенного ниже:
101
Единственная операция, которая оказывается при этом вне цикла, — опе-
рация инициализации счетчика числа циклов. Необходимо всегда помнить
об этом. Если не выполнить инициализацию счетчика числа циклов, то
результаты выполнения программы будут непредсказуемыми.
Оператор цикла for позволяет существенно упростить организацию циклов,
так как собирает все три действия, необходимых для организации циклов в
одном месте. Пример использования этого оператора представлен ниже:
102
Контрольные вопросы
1. Начальное значение переменных целого типа x = 2, y = 1, k = 0, n = 9. Чему будет
равно значение переменной y после выполнения следующего цикла:
while (k<n)
{ y = y*x;
k++;
}
2. Какая информация будет выведена на экран в окно Stdout при выполнении следую-
щего цикла:
count = 1;
do
printf(“Значение счетчика count = %d\n”, count);
while (++count<=10)
3. Замените циклы циклами с оператором for. Результат должен быть таким же.
104
Ссылки на указатели могут появляться и в левой части операторов при-
сваивания. Так, первый оператор, приведенный в лист. 4.20, обеспечивает
присваивание переменной x значения, равного нулю. Второе выражение
выполняет по существу инкрементирование переменной х. Такое же дей-
ствие выполняется и с помощью оператора в третьей строке.
Контрольные вопросы
1. Указатели должны быть не только объявлены, но и обязательно проинициализиро-
ваны перед использованием. Что произойдет, если не выполнить инициализацию?
2. При описании типа указателя инициализация указателя может быть попутной.
Выполняется в двух вариантах: 1) с помощью обычного оператора присваивания;
2) посредством указания адреса переменной в скобках сразу после имени указателя.
Каким операторам эквивалентны следующие два оператора?
int *pa = &a;
int *pb (&b);
105
4.4. УКАЗАТЕЛИ И МАССИВЫ
106
Для доступа к i-му элементу массива можно воспользоваться выражением
inp_buffer[i] или указателем *(input+i). Последнее выражение имеет следу-
ющий смысл: доступ к переменной по указателю input, предварительно уве-
личенному на смещение, пропорциональное номеру элемента i. Для элемен-
тов типа int смещение будет равно i, а для элементов типа long — 2*i.
Будьте внимательны. Положение скобок при работе с указателями имеет
большое значение (лист. 4.26).
Практическая работа
Контрольные вопросы
1. Объясните синтаксис оператора for. Почему логическое условие в операторе цикла
записано как i < 10, а не, например, так: i <= 10? Какой индекс будет иметь последний
скопированный элемент массива? Почему?
2. Какие действия выполняются в последнем операторе программы? Замените этот
оператор на более наглядный.
Практическая работа
Контрольные вопросы
1. Какие значения примут указатели ptr_to и ptr_from в конце цикла?
2. Как работает последний оператор программы? К какому элементу массива на
самом деле прибавляется число 5? Проверьте свои соображения.
3. Перепишите программу с использованием цикла for.
112
Как видно из определения функции, теперь в нее передаются не два зна-
чения типа int, а два указателя на переменные типа int. В теле функции вна-
чале вычисляем значение локальной переменной temp_sum, а затем обну-
ляем значения аргументов. Очевидно, что и вызов функции будет теперь
выглядеть иначе:
Практическая работа
Контрольные вопросы
114
Рис. 4.6. Работа функций через указатели
115
Глава 5
Ассемблерный код,
Исходный Си-код
созданный компилятором Си
// Остановить CPU Timer0 MOV AL, *(0:0x0c04)
*TIMER0TCR |= 0x0010; ORB AL, #0x10
MOV *(0:0x0c04), AL
Табл и ц а 5.2
Доступ к регистрам ПУ с использованием структурного подхода
Ассемблерный код,
Исходный Си-код
созданный компилятором Си
// Остановить CPU Timer0 MOVW DP, #0030
CpuTimer0Regs.TCR.bit.TSS = 1; OR @4, #0x0010
120
2) производится предварительная загрузка регистра XAR4 длинной кон-
стантой с последующим копированием содержимого регистра XAR4 по
короткому прямому адресу регистра периода;
3) нужный бит регистра управления таймером очищается с помощью ато-
марной команды «Логического И» с маской.
Как видите, компилятор создает максимально эффективный машинный
код как по объему памяти, так и по времени выполнения.
Преимущества структурного подхода:
• просто работать с индивидуальными разрядами и битовыми полями
исключительно по символическим именам;
• все необходимые маски генерирует сам компилятор;
• в окне Watch Window среды CCS может быть отображено текущее
содержимое как регистра целиком, так и каждого бита или битового поля в
отдельности. Возможна модификация значений битовых полей в процессе
отладки.
Наиболее эффективный генерируемый код — создаваемый с использова-
нием прямой страничной адресации данных и быстрых атомарных инструк-
ций.
Недостатки структурного подхода:
• трудно запомнить имена структур, однако в Code Composer Studio есть
встроенная система помощи Code Maestro, которая по первым буквам имени
выдает необходимые подсказки;
• больше приходится печатать, но можно использовать встроенные
средства авторасширения имен по первым набранным символам (помогает
Code Maestro);
• чтобы эффективно работать, необходимо один раз разобраться с систе-
мой использования готовых файлов, поставляемых Texas Instruments.
Более подробно особенности структурного подхода к программированию
периферии на языке Си рассмотрим ниже.
122
Регистровый файл каждого периферийного устройства описывается в
виде структуры на Си, причем отдельные регистры указываются в структуре
в порядке их фактического расположения в памяти данных, начиная с млад-
шего адреса. Пустые места также описываются с помощью неиспользуемых
резервных переменных. Обычно в качестве типа элементов структуры ука-
зывается тип Uint16 (переопределенный тип unsigned int) или тип Uint32
(переопределенный тип unsigned long). В первом случае регистр 16-разряд-
ный, во втором — 32-разрядный.
Если какой-либо регистр периферийного устройства имеет битовые поля,
то он обязательно описывается в виде структуры битовых полей. В примере
в лист. 5.3 такое описание дано для регистра управления АЦП ADCTRL1.
#include “DSP281x_Device.h”
void InitAdc(void)
{
/* Перезапуск модуля АЦП (обращение к отдельному бито-
вому полю регистра)*/
AdcRegs.ADCTRL1.bit.RESET = 1;
/* Задание режима работы АЦП (обращение целиком ко
всему регистру управления)*/
AdcRegs.ADCTRL1.all = 0x0710;
};
124
Имена всех регистровых файлов периферийных устройств
PeripheralName определены Texas Instruments и могут быть найдены в заго-
ловочных файлах DSP28xx. Они представляют собой комбинацию заглавных
и строчных букв, например CpuTimer0Regs для регистрового файла Тай-
мера 0 центрального процессора. Имена отдельных регистров периферий-
ного устройства RegisterName такие же, как в описании на периферию мик-
роконтроллера, всегда набранные заглавными буквами, например TPR
(Регистр периода таймера). Имена отдельных битовых полей периферийных
регистров FieldName тоже полностью соответствуют документации на мик-
роконтроллер и набираются заглавными буквами, например RESET (Сброс
АЦП).
Практическая работа
1. Найдите и исследуйте главный подключаемый заголовочный файл.
2. Откройте файл с описанием регистров АЦП. Сколько всего регистров
содержит этот файл, каково их назначение? Есть ли среди регистров АЦП
регистр результата аналого-цифрового преобразования? Как производится
доступ к этому регистру? Возможен ли побитовый доступ? Почему?
3. На примере регистрового файла АЦП проследите всю последователь-
ность объявления структур — от структур битовых полей регистров до
структуры регистрового файла АЦП целиком. Где создается конкретный
экземпляр этой структуры?
4. Найдите файл, в котором объявляется специальная секция данных для
АЦП.
126
5.5. ПРОГРАММИРОВАНИЕ ПЕРИФЕРИИ ‘C28xx
С ИСПОЛЬЗОВАНИЕМ ЗАГОЛОВОЧНЫХ ФАЙЛОВ
Бит Бит
Регистр Управление
регистра регистра
GPxQUAL Z-состоянием
GPxMUX GPxDIR
0 1 0 1
MUX MUX
Входной SYSCLKOUT
фильтр
Разрешение
Z-состояния
1 XRS
Внутренняя
привязка
к логическому
0 или 1
Ножка
процессора
Input
to Qual
1 1 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1
Input
from Qual
Практическая работа
а) б)
130
Лист. 5.9. Пример программы управления светодиодом
// бесконечный цикл программы
while(1)
{
// введите ваш код здесь
l_counter++;
//разрешаем запись в регистр
EALLOW;
//используем вывод XF как связанный с периферией
GpioMuxRegs.GPFMUX.bit.XF_GPIOF14 = 1;
// запрещаем запись в регистр
EDIS;
// вставка асемблерной команды — установить xf
asm(" setc xf");
// вставка асемблерной команды — сбросить xf
asm(" clrc xf");
}
Практическая работа
1. Откомпилируйте программу и загрузите ее в микроконтроллер. Выпол-
ните команду Debug Go Main для перехода в начало функции main. Выпол-
няйте программу по шагам, используя команду Step Into (клавиша F8).
Наблюдайте за состоянием светодиода.
2. Вы уже заметили, что процедура инициализации порта ввода/вывода
оказалась внутри цикла while и выполняется многократно. Это не ошибка,
но «плохой стиль программирования» — инициализация должна выпол-
няться только один раз. Модернизируйте программу — выполните инициа-
лизацию порта до начала цикла. Исследуйте работу программы. Убедитесь,
что ничего не изменилось.
3. Остановите программу. Откройте окно статусных регистров процес-
сора и меняйте состояние флага XF в этом окне. Объясните, почему при
неработающей программе состояние выхода порта изменяется?
4. Теперь более сложное задание. Настройте линию микроконтроллера
GPIOF14 в режим порта вывода общего назначения с помощью регистра
131
управления мультиплексором GPFMUX. Задайте направление передачи дан-
ных с помощью регистра GPFDIR. Попробуйте управлять выходом XF через
регистры: GPFDAT; GPFSET, GPFCLEAR; GPFTOGGLE. Составьте три
различные программы и выполните их отладку.
Контрольные вопросы
1. Как установить скважность включения светодиода в вашей программе 25 и 12,5 %?
2. Можно ли регулировать яркость свечения светодиода? Напишите программу, кото-
рая меняла бы значение яркости горения светодиода в диапазоне от 0 до 100 % (задается
отдельной переменной) по усмотрению пользователя.
4
3 3 3
2 2 2
1 1 1
TxCNT 0 0
TxCON.TENABLE
HSPCLK
133
Рис. 5.7. Включение тактирования первого менеджера событий
134
Рис. 5.8. Задание режима работы таймера 1
136
Его можно запустить с помощью кнопки . В этом режиме программа
будет выполняться в режиме прогона до ближайшей точки останова. В
момент останова значения всех наблюдаемых переменных (в том числе в
графических окнах) будут считаны из микроконтроллера в компьютер и
экран среды CCS обновится. После этого выполнение программы автомати-
чески продолжится в режиме прогона до новой точки останова. Таким образом,
обновление информации производится от одной точки останова к другой.
Практическая работа
1. Сделайте необходимые установки для инициализации Таймера 1 и для
его программного запуска. Установите значение в регистре периода 50 000 и
максимальный коэффициент деления входной тактовой частоты. Рассчи-
тайте значение периода таймера в секундах.
2. Наблюдайте за изменением состояния таймера в окне Watch. Соответ-
ствует ли период таймера расчетному периоду?
3. Установите точку останова в программе main с бесконечным циклом и
запустите ее на исполнение с помощью кнопки Animate (Анимация).
Откройте графическое окно для отображения текущего состояния счетчика
таймера в функции времени. Поэкспериментируйте с настройками.
4. Перенастройте таймер 1 для работы с тем же периодом, но в режиме
нереверсивного счета. Объясните полученную осциллограмму.
INT1
INT2
1
MUX CPU
0
INT11
INT12 Глобальное
(Флаг) (Разрешение) разрешение
INTx.1
INTx.2
INTx.3
INTx.4 Периферийные или
INTx
MUX INTx.5 внешние прерывания
INTx.6
INTx.7
INTx.8
(Разрешение) (Флаг)
PIEIER(8:1) PIEIFR(8:1)
Табл и ц а 5.3
Таблица прерываний
139
Порядок обслуживания прерываний
1. Если какое-либо событие в периферийном устройстве генерирует
запрос прерывания, то в одном из регистров этого устройства выставляется
флаг запроса прерывания interrupt flag (IF). Это прерывание может быть
разрешено или запрещено непосредственно внутри периферийного устрой-
ства с помощью соответствующего бита разрешения прерывания IE. Для
каждого запроса прерывания (каждого события) существуют свои флаги IF и
IE. Например, для таймера можно установить разрешение генерации
запроса прерывания по периоду и запретить генерацию запроса прерывания
по переполнению вверх и вниз. Если событие произошло и генерация
запроса прерывания разрешена, то периферийное устройство выставляет
запрос прерывания в контроллер периферийных прерываний PIE (см.
рис. 5.10).
2. Если прерывание запрещено на уровне периферийного устройства, то
флаг запроса прерывания остается установленным до тех пор, пока не будет
очищен программным путем. Если после того, как запрос прерывания в
периферийном устройстве возник (флаг IF установился), разрешить это пре-
рывание, то будет сформирован запрос прерывания в контроллер периферий-
ных прерываний PIE.
3. Флаг запроса прерывания IF, выставленный в регистре соответствую-
щего периферийного устройства, должен быть очищен вручную (програм-
мным путем) в процедуре обслуживания прерывания.
4. Для каждого источника мультиплицированного прерывания в каждой
из 12 групп имеется соответствующий флаг ждущего запроса прерывания
(PIEIFRx.y) и флаг разрешения этого периферийного прерывания
(PIEIERx.y). Дополнительно для каждой группы периферийных прерыва-
ний (INT1 — INT12) имеется свой собственный флаг разрешения группы
прерываний PIEACKx. Активное значение этого флага «логический 0». В
конце процедуры обслуживания периферийного прерывания флаг PIEACKx
должен программно очищаться, чтобы разрешить последующую обработку
прерываний группы.
5. Если на вход контроллера периферийных прерываний поступает запрос
прерывания, то соответствующий флаг «ждущего» запроса прерывания
(PIEIFRx.y) устанавливается. Если соответствующее периферийное преры-
вание разрешено и бит (PIEIERx.y) установлен, то производится тестирова-
ние бита разрешения прерываний для всей группы периферийных прерыва-
ний PIEACKx. Активное значение этого флага низкое. При разрешении
прерываний от группы PIEACKx = 0 контроллер периферийных прерываний
посылает запрос прерывания центральному процессору по линии INTx.
Если PIEACKx = 1 (нет разрешения группы), то контроллер прерываний
будет ждать до тех пор, пока программа не сбросит этот флаг, после чего
сформирует запрос прерывания ЦПУ.
6. Если одновременно несколько периферийных прерываний в группе
ждут обслуживания и для каждого из них установлены флаги «ждущего»
прерывания PIEIFRx.y и разрешения прерывания PIEIERx.y, то будет
140
обслуживаться прерывание с наивысшим приоритетом, т.е. имеющее мень-
ший номер в табл. 5.3. Так, для 1-й группы наивысшим приоритетом обла-
дает прерывание PDPINTA (внешнее по аварии в силовых ключах). Поэтому
если одновременно с ним ждет обслуживания прерывание от АЦП
(ADCINT), то будет обслуживаться прерывание PDPINTA как имеющее
более высокий приоритет.
7. Как только запрос прерывания выставляется на одну из линий запроса
прерывания центрального процессора INTx, то разрешение прерываний от
группы периферийных прерываний, выставившей запрос, аппаратно снима-
ется: PIEACKx = 1. Прием запросов прерываний от этой группы блокиру-
ется.
8. Если запрос прерывания поступает на одну из линий запроса прерыва-
ний центрального процессора INTx, то выставляется соответствующий флаг
«ждущего» запроса прерывания IFR. Это прерывание будет обрабатываться
только в том случае, когда прерывание по соответствующей линии INTx раз-
решено в регистре разрешения прерываний центрального процессора IER, а
также при условии, что флаг глобального маскирования прерываний сбро-
шен INTM = 0.
9. Перед обработкой прерывания автоматически выполняются следую-
щие действия:
• очищаются биты IFRx (флаг ждущего глобального прерывания) и IERx
(флаг разрешения глобального прерывания);
• устанавливается флаг INTM (маскирование всеx прерываний до
момента завершения обслуживания текущего прерывания);
• очищается флаг EALLOW (разрешается доступ по записи к защищен-
ным регистрам);
• «смывается» конвейер команд;
• адрес возврата в фоновую программу сохраняется в стеке;
• выполняется автоматическое сохранение контекста в стеке.
10. Автоматически извлекается вектор нужной процедуры обслужива-
ния прерывания из таблицы векторов прерываний на основе информации из
контроллера периферийных прерываний о запросе, вызвавшем прерывание
(PIEIERx и PIEIFRx). Флаг PIEIFRx автоматически аппаратно очищается.
Выполняется косвенный переход на начало процедуры обслуживания преры-
вания.
11. Выполняются все необходимые действия по обслуживанию прерыва-
ния.
12. Перед выходом из процедуры обслуживания прерывания:
• программно очищается флаг ждущего прерывания IF в соответствую-
щем регистре периферийного устройства (см. п. 1);
• разрешаются периферийные прерывания от группы, вызвавшей преры-
вание, с помощью программной очистки флага PIEACKx (см. п. 7);
• переразрешаются все маскируемые прерывания посредством сброса
флага INTM.
13. Выполняется возврат из подпрограммы в фоновую программу, в про-
цессе которого автоматически восстанавливается контекст.
141
Пример программирования прерывания от таймера
Предположим, что таймер 1 должен генерировать периодические преры-
вания через определенный интервал времени, т.е. выполнять роль интер-
вального таймера. Эта задача возникает при отсчете определенных времен-
ных интервалов (электронные реле времени), при реализации операционных
систем реального времени, при задании нужного интервала квантования ана-
логовых сигналов и т.п.
Один из возможных вариантов программы, реализующей эту функцию,
представлен в лист. 5.11. Листинг содержит достаточно подробные коммен-
тарии, что позволит понять механизм использования шаблонов для описания
таблицы векторов прерываний, последовательность необходимых действий
при инициализации системы прерываний, в процедуре обслуживания преры-
вания и в так называемой фоновой программе. Мы будем использовать пре-
рывание по отрицательному переполнению таймера T1UFINT, которое воз-
никает в момент обнуления счетчика таймера, т.е. в конце каждого периода.
Счетчик числа вызовов обработчика прерывания инкрементируется при каж-
дом вызове.
Замечание
В процессе выхода из процедуры обслуживания прерывания и автомати-
ческого восстановления контекста будет восстановлено и содержимое ста-
тусных регистров. Поэтому сбрасывать флаг INTM программно не обяза-
тельно.
Практическая работа
1. Удалите файл main.c из проекта и добавьте файл main_a.c. Для этого
перейдите в меню Project → Add Files to Project… и в появившемся окне из
папки lab5\src выберите файл main_a.c. Откройте его в среде Code
Composer.
2. Откомпилируйте программу и загрузите ее в память микроконтроллера.
Установите точку останова, как показано на рис. 5.11. Напомним, что это
можно сделать, дважды щелкнув мышью на сером фоне слева от нужной
строки.
142
3. Добавьте переменную isr_ticker в окно просмотра. Для этого перемес-
тите курсор на ее имя и нажмите правую кнопку мыши. Во всплывающем
контекстно-зависимом меню выберите Add to Watch Window.
4. Запустите программу в режиме Animate и последите за изменением
значения переменной.
5. Изучите содержимое файла main_a.c. Соответствует ли эта программа
описанному в теоретической части алгоритму обслуживания прерываний?
Попробуйте понять, как работают готовые функции, поставляемые Texas
Instruments, такие как InitSysCtrl(); InitPieCtrl(); InitPieVectTable().
6. Измените процедуру обслуживания прерывания от таймера 1, напри-
мер исключите команду разрешения обработки всех маскируемых прерыва-
ний перед выходом из процедуры. Объясните последствия.
Контрольные вопросы
1. Какие прерывания называются маскируемыми?
2. Что такое прерывание центрального процессора и периферийное прерывание?
Зачем нужен модуль расширения периферийных прерываний?
3. Можно ли считать, что контроллер прерываний имеет фиксированный приоритет
обслуживания прерываний? Чем определяется этот приоритет?
4. Какие флаги аппаратно сбрасываются при переходе к процедуре обслуживания
прерывания? Зачем это делается?
5. Можно ли внутри процедуры обслуживания текущего прерывания разрешить
обслуживание другого (более приоритетного)? Что нужно сделать для этого?
Практическая работа
1. Рассчитайте значение регистра периода таймера 1 для получения час-
тоты прерываний 5 кГц. Модернизируйте программу, чтобы таймер генери-
ровал второе прерывание по достижению в счетчике таймера значения, рав-
ного значению в регистре периода.
2. Дополните программу второй процедурой обслуживания прерываний
по периоду таймера. Установите в обработчике процедуры обслуживания
прерывания персональный счетчик ее вызовов. Убедитесь в том, что оба
обработчика прерываний вызываются с одинаковой частотой.
3. Можно ли получить частоту генерации прерываний 1 кГц? Это будет
соответствовать «кванту» времени в 1 мс. Модернизируйте программу для
отсчета любой произвольной выдержки времени, заданной в числе [мс] отдель-
ной переменной. После отсчета выдержки времени состояние линии XF мик-
роконтроллера должно изменяться на противоположное и «реле времени»
должно запускаться вновь. Отладьте эту программу в режиме с точками
останова.
144
Рис. 5.15. Установка опций обновления в
режиме реального времени
Практическая работа
146
Глава 6
РАБОТА С БИБЛИОТЕКОЙ IQmath
Двоичные числа
Двоичная система счисления используется в микропроцессорах, так как
каждый ее значащий разряд имеет всего два возможных состояния, что легко
реализуется на транзисторной логике. Двоичная система, как и десятичная,
является позиционной системой счисления. Каждый разряд имеет вес, определя-
ющийся его позицией в числе. Основание двоичной системы счисления — 2,
поэтому весовые коэффициенты являются степенями двойки. Для целой
части числа (слева от двоичной точки) располагаются весовые коэффици-
енты 1, 2, 4, 8 и т.д., а справа, в области дробной части числа, 0,5; 0,25; 0,125
и т.д.
Для перевода числа из двоичной системы в десятичную необходимо
умножить каждый разряд двоичного числа на соответствующий ему весовой
коэффициент и сложить произведения:
011012 = 0æ16 + 1æ8 + 1æ4 + 0æ2 + 1æ1 = 8 + 4 + 1 = 13. (6.1)
Аналогичным способом производится перевод дробных и вещественных
чисел:
111,012 = 1æ4 + 1æ2 + 1æ1 + 0æ0,5 + 1æ0,25 = 7,25. (6.2)
Дополнительный код
Числа в процессорной технике могут быть как беззнаковыми, так и знако-
выми. Для представления знаковых чисел используется дополнительный код:
такое представление отрицательного числа, когда его сумма с соответствую-
щим положительным числом дает нуль в рамках принятого формата числа
(дополняет положительное число до нуля). При этом старший разряд числа
рассматривается как знаковый: 0 — число положительное, 1 — отрицательное.
При получении десятичного эквивалента числа в дополнительном коде (–1)
умножается на двоичное значение старшего (знакового) разряда и его вес:
011012 = –0æ16 + 1æ8 + 1æ4 + 0æ2 + 1æ1 = 13;
111,012 = –1æ4 + 1æ2 + 1æ1 + 0æ0,5 + 1æ0,25 = –0,75.
Выражение (6.1) не изменилось, так как старший знаковый разряд ока-
зался равен 0.
147
Получение дополнительного кода
Дополнительный код числа можно получить, воспользовавшись одним из
приведенных ниже способов:
• вычесть число из нуля (полученный результат той же разрядности
будет дополнением до нуля);
• инвертировать число и прибавить к нему единицу;
• оставить все нули с правой стороны числа неизменными, оставить
неизменной первую единицу, остальные разряды проинвертировать.
Рассмотрим примеры перевода чисел, приведенные на рис. 6.1.
Независимо от способа вычисления получается одинаковый результат.
Наиболее простым и не требующим расчетов является третий способ. В про-
граммных реализациях используется первый или второй способ как подде-
рживаемые системой команд процессора.
0 0 0 0 0 0 0 0, 0 0
– –
0 1 1 0 1 1 1 1, 0 1
1 0 0 1 1 0 0 0, 1 1
0 1 1 0 1 1 1 1, 0 1
Инверсия Инверсия
1 0 0 1 0 0 0 0, 1 0
+ +
0 0 0 0 1 0 0 0, 0 1
1 0 0 1 1 0 0 0, 1 1
0 1 1 0 1 1 1 1, 0 1
Копирование до первой Копирование до первой
Инверсия единицы включительно Инверсия единицы включительно
1 0 0 1 1 0 0 0, 1 1
148
Данные 1 1 0 0 12
Регистр 0 0 0 0 1 1 0 0 12
Данные 1 1 0 0 = –23 + 22 = –4
Загрузка и расширение
знакового разряда
Регистр 1 1 1 1 1 1 0 0 = –27 + 26 + 25 + 24 + 23 + 22 =
= –128 + 64 + 32 + 16 + 8 + 4 =
= –4
Контрольные вопросы
1. Переведите в десятичную систему счисления следующие числа без знака:
110001011,11012; 110010,1101112; 0110,1002; 0,111111112.
2. Переведите в десятичную систему счисления следующие числа со знаком в допол-
нительном коде:
110001011,11012; 110010,1101112; 0110,1002; 1,111111112.
3. Получите тремя возможными способами дополнительный код для следующих чисел:
110001011,11012, 110010,1101112, 0110,1002; 1,111111112.
4. Зависит ли механизм преобразования чисел из 16-разрядного формата в 32-разряд-
ный от того, является ли преобразуемое число целым, дробным или вещественным?
5. Какой диапазон чисел со знаком можно представить в формате 8.24?
149
6.2. ОСОБЕННОСТИ РАБОТЫ С ДВОИЧНЫМИ ЧИСЛАМИ
0 1 0 0 4
* 0 0 1 1 * 3
0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Аккумулятор 0 0 0 0 1 1 0 0 1 2
Память ?
150
Относительные единицы. Форматы
представления чисел в относительных единицах
Для расчета математических моделей, описания алгоритмов системы
управления, измерений электрических и механических величин и цифровой
фильтрации удобно использовать систему относительных единиц. Относи-
тельные единицы получаются делением реальной физической величины на
некоторое базовое значение. Базовые значения можно выбирать по-разному,
однако чаще всего за базовое число принимают номинальное значение физи-
ческой величины.
Если принять за базовый ток номинальный ток двигателя, а за базовое
напряжение — номинальное напряжение двигателя, то в результате перемно-
жения тока на напряжение в относительных единицах будет получаться
мощность, тоже представленная в относительных единицах. Преимущество
такого подхода состоит в том, что всякий раз система работает с числами
вполне определенного диапазона значений. Например, ток в преобразова-
тельной технике редко бывает в несколько раз больше номинального (то же
касается напряжения и мощности).
Рассмотрим пример: необходимо рассчитать относительное значение
мощности при заданных относительных величинах тока и напряжения.
Пусть ток будет равен 1,25, а напряжение 0,75 номинальных значений. Выбе-
рем формат 2.2 для представления тока и напряжения, где два разряда будут
отведены под целую часть числа и два разряда — под дробную (рис. 6.5).
Вычисления производятся, как показано в левой части рис. 6.5. Получен-
ный точный результат P* = U*I* = 1,25æ0,75 = 0,9375 представлен в формате
4.4 с четырьмя целыми и четырьмя дробными разрядами. Общее правило
состоит в том, что при умножении вещественных чисел, представленных в
форматах с фиксированной точкой (m.n) и (p.q), включая знаковый разряд в
целой части, получаем произведение в формате (m+p).(n+q).
Если договориться о том, что произведение сохраняется в исходном фор-
мате множителей, т.е. в формате 2.2, то необходимо отбросить по два разряда
с каждой стороны (см. рис. 6.5). Сразу возникает вопрос: можно ли так
делать? Будет ли результат иметь ту же точность, что и исходные операнды?
Если известно, что в конкретной системе мощность не может быть
больше номинальной (базовой) в 2 раза, то предложенный формат результата
0 1,0 1 1,25 X X, X E
* 0 0,1 1 * 0,75 * X X, X E
0 0 0 0 0 1 0 1 0 0 0 0 E E E E
0 0 0 0 1 0 1 0 0 0 0 Y Y Y E 0
0 0 0 0 0 0 0 0 0 0 Y Y Y E 0 0
0 0 0 0 0 0 0 0 0 Y Y Y E 0 0 0
Аккумулятор 0 0 0 0, 1 1 1 1 0,9375 Z Z Z Z, R E E E
Память 0 0 , 1 1 0,75 Z Z, R E
151
подходит. Иначе необходимо увеличить число разрядов целой части множи-
телей, например выбрать для них формат 3.2 или 4.2.
Второе обстоятельство, вызывающее сомнение в правильности расчетов,
связано с отсечением половины разрядов в дробной части. Действительно,
точное значение результата из 0,9375 превратилось в 0,75.
Для определения погрешности этой операции необходимо рассмотреть
процесс умножения, изображенный в правой части рис. 6.5. Здесь символом
«X» обозначены разряды исходных чисел, символ «E» обозначает младшие
разряды исходных чисел, в которые заложена ошибка округления. При умно-
жении ошибки «E» на любое число «X» или «E» получается ошибка «E», что
видно по первой строчке частичных произведений. При умножении «X» на
«X» получается достоверный разряд частичного произведения «Y». При сло-
жении частичных произведений, в котором участвуют «Y», получаются раз-
ряды достоверного ответа «Z». Первый разряд, в сумму которого попали
ошибки «E», можно отнести к округленному, но не достоверному разряду
«R», а остальные разряды будут содержать слишком большие ошибки и не
будут достоверными вовсе. Получается, что дробная часть результата, сохра-
ненная в памяти, содержит только округленный разряд и разряд ошибки
округления, так что точность ответа в результате отсечения половины дроб-
ных разрядов не ухудшилась.
Рассмотренный пример оперирует с числами малой разрядности. В реаль-
ных системах управления на базе микроконтроллеров ‘C28xx используются,
как минимум, 16-разрядные вещественные числа, например, с четырьмя зна-
ками в целой части. Такие числа имеют формат 4.12. Так как для представле-
ния целой части числа, включая знаковый разряд, выделяются четыре раз-
ряда, то реализуется восьмикратная перегрузочная способность по любой из
переменных, представленных в относительных единицах (относительно
базового значения). Если точности 12 двоичных разрядов после запятой
недостаточно, то можно использовать 32-разрядный формат, например 4.28.
Таким образом, если разрабатываете программное обеспечение системы
управления, то не следует работать с физическими величинами — перехо-
дите к относительным единицам и выбирайте формат представления пере-
менных с фиксированной точкой, например 4.28 или 8.24, который, с одной
стороны, обеспечит нужную перегрузочную способность по переменным
вашего проекта, а с другой — нужную точность вычислений.
Система команд микроконтроллеров ‘C28xx оптимизирована для работы
с числами в формате с фиксированной точкой. Более того, есть средства
автоматического преобразования формата произведения к исходному фор-
мату множителей. Например, при умножении дробных чисел (перегрузочная
способность переменной равна 1) в формате 1.31 результат в формате 2.62
автоматически, сначала за счет сдвига влево на один разряд приводится к
формату 1.63, а затем за счет отбрасывания младших 32 неточных разрядов —
к исходному формату множителей 1.31.
Мощная система команд микроконтроллеров ‘C28xx послужила предпо-
сылкой к созданию специальной библиотеки вычислений с числами в фикси-
рованном формате (i.q), которая получила название IQmath. Эта библиотека
152
поддерживает вычисления с вещественными переменными, представлен-
ными в одинаковом формате (с одним и тем же числом двоичных разрядов
после точки q) и позволяет менять формат чисел при необходимости.
Библиотека IQmath максимально приближена к пользователям, занимаю-
щимся разработкой систем управления реального времени, где скорость
вычислений и точность имеют определяющее значение. Ее использование
предполагает представление переменных в относительных единицах, что
позволяет разрабатывать одно и то же программное обеспечение для объек-
тов различной мощности, например для всей серии преобразователей час-
тоты или серии комплектных электроприводов.
Контрольные вопросы
1. В каком формате будет результат умножения 16-разрядных целых чисел без знака
(исходный формат 16.0)? 32-разрядных целых чисел без знака (исходный формат 32.0)?
2. Докажите на примерах, что при умножении дробных чисел без знака в формате
(0.16) точность произведения остается на уровне точности множителей.
3. По какой из переменных для вентильного моментного электропривода должна
быть установлена максимальная перегрузочная способность (по току, скорости, моменту,
ускорению)? Какая именно? Какой при этом будет формат представления переменных?
31 30 23 22 0
s e e e e e e e e f f f f f f f f f f f f f f f f f f f f f f f
154
тем не менее, могут возникать проблемы при операциях с большими и
малыми числами. Приведем типичный пример.
Необходимо для системы управления преобразователем частоты реализо-
вать интегратор выходной частоты инвертора напряжения в угол вектора
напряжения, а затем вычислить синус и косинус этого угла, структурная
схема преобразования которого приведена на рис. 6.7.
Как показано на схеме, задание частоты преобразуется в угловую частоту,
интегрируется в угол и вычисляются синус и косинус этого угла.
При решении задачи в микроконтроллере все непрерывные уравнения
должны быть преобразованы к разностным уравнениям с учетом интервала
дискретизации (квантования) по времени. В нашем случае задача должна
решаться на каждом периоде широтно-импульсной модуляции ключей
инвертора TШИМ. Обычно эта частота равна 5—10 кГц. Примем для опреде-
ленности, что частота квантования задается интервальным таймером 1 и
равна TШИМ = 5 кГц.
Переведем непрерывное уравнение интегратора в дискретную область:
Y ( p )- 1
----------- = --- ; (6.3)
X(p) p
yp = x; (6.4)
yk – yk – 1
yp = ------------------------- ; (6.5)
T ШИМ
yk – yk – 1
------------------------- = x k ; (6.6)
T ШИМ
yk = yk – 1 + TШИМ xk. (6.7)
Выражая входное воздействие интегратора xk через частоту f и коэффици-
ент 2π и имея в виду, что выходом интегратора является угловое положение
вектора напряжения θk, получаем:
θk = θk – 1 + 2πTШИМ f. (6.8)
f ω0 1 θ sin(θ)
2π — SIN
t
p
cos(θ)
COS
Рис. 6.7. Структурная схема преобразования частоты в угол и синус и косинус угла
155
Таким образом, на каждом периоде ШИМ (с частотой 5000 раз в секунду)
должна вызываться процедура увеличения текущего углового положения
вектора напряжения на некоторую величину, зависящую от частоты f. После
определения нового значения угла должен выполняться расчет синусов и
косинусов угла.
На лист. 6.1 представлена программа, которая состоит из основной (фоновой)
программы и процедуры обслуживания прерывания по периоду таймера 1,
вызываемой с частотой TШИМ = 5 кГц (см. гл. 5). Фоновая программа выпол-
няет инициализацию переменных и содержит пустой (бесконечный) цикл.
Все вычисления выполняются в процедуре обслуживания прерывания.
for(;;)
{
}
}
interrupt void t1pr_isr(void)
{
teta+=2*pi*f*Tpwm;
x=sin(teta);
y=cos(teta);
}
156
Для наблюдения за периодически меняющейся переменной откроем гра-
фическое окно, приведенное на рис. 6.9. На экране появится окно настроек
осциллографа, поля которого нужно проинициализировать, например, в
соответствии с рис. 6.10. В качестве стартового адреса зададим адрес пере-
менной x. В качестве типа переменной укажем 32-bit IEEE floating point
(число в формате с плавающей точкой). После подтверждения настроек и
запуска программы в режиме Анимация с помощью кнопки программа
начнет выполняться, останавливаясь в точке останова, обновляя содержимое
окна осциллографа и окна наблюдения переменных и запускаясь снова. Гра-
фик переменной x будет изменяться по синусоидальному закону, изображен-
ному на рис. 6.11.
Обратите внимание, что вывод точек на график производится «как бы с
частотой 5000 Гц» (при каждом обращении к процедуре обслуживания пре-
рывания), а частота выходного сигнала задана равной 50 Гц. Таким образом,
на одном периоде сигнала выводится ровно 100 значений переменной x. На
самом деле режим «Анимации» не является режимом реального времени.
Процессор прерывается в точке останова для передачи информации с оце-
ночной платы в компьютер. Если этот процесс займет больше времени, чем
период ШИМ, то один или несколько периодов ШИМ могут быть пропущен-
ными. Поэтому на графике по оси времени указано не абсолютное время, а
номер выборки данных.
В программе допущена грубая ошибка, которая незаметна в процессе
прогона, пока угол θ еще мал. Изменив его на большее значение, например
102900 радиан, можно убедиться, что функции синуса и косинуса непра-
вильно вычисляются при больших значениях угла (рис. 6.12).
157
Рис. 6.10. Настройки окна осциллографирования
Практическая работа
31 30 24 23 0
s i i i i i i i f f f f f f f f f f f f f f f f f f f f f f f f
160
I8,Q24 A
*
I16,Q48
I8,Q24 B
>>24
ssssssssssssssssssssssssI16,Q24
I8,Q24
+ I8,Q24 C
I8,Q24 I8,Q24 D
161
Вначале регистр умножителя XT загружается значением переменной a с
использованием прямой страничной адресации (адрес 12 на текущей стра-
нице памяти). Затем производятся операции умножения содержимого регис-
тра XT на значение переменной b (адрес 4 на текущей странице памяти).
Две операции умножения служат для получения младшей и старшей части
64-разрядного произведения, которые записываются в регистры P и ACC
соответственно.
Следующая команда выполняет сдвиг сдвоенного 64-разрядного регистра
(ACC:P) влево на восемь разрядов, в результате чего в старшей части (в
аккумуляторе — ACC) оказывается результат умножения, приведенный к
формату с восемью целыми и 24 дробными разрядами. К нему добавляется
значение переменной c (адрес 18 на текущей странице памяти), затем резуль-
тат сохраняется в переменную d по адресу 14 на текущей странице памяти.
Алгоритм расчета показан на рис. 6.16.
ACC:P I8,Q24 a
*
I16,Q48
I8,Q24 b
<<8
I8,Q48 00000000
I8,Q24 ACC
+ I8,Q24 c
I8,Q24 I8,Q24 d
162
переопределяемой операции *, после которого в круглых скобках указан спи-
сок параметров с их типами. Тело переопределяемой операции описывается,
как обычно, между фигурных скобок { }.
Приведенный код является лишь примером. На самом деле в заголовоч-
ном файле IQmathLibCPP.h содержится более сложное определение с вызо-
вом функции _IQmpy(a,b). Таким образом, в языке Си++, объявив вещест-
венные переменные типа iq с фиксированной точкой, дальше можно
пользоваться обычными операторами, такими как «*», «/» и т.д. Они автома-
тически будут замещаться соответствующими функциями библиотеки
IQmath.
Список функций, содержащихся в библиотеке IQmath, приведен в табл. 6.1
в сравнении с функциями стандартной библиотеки поддержки вычислений с
плавающей точкой.
Табл и ц а 6.1
Основные функции библиотеки IQmath
163
Контрольные вопросы
1. Как Вы понимаете функцию синус угла в относительных единицах?
2. Какие функции необходимо использовать при переходе от декартовой системы
координат к полярной?
3. Как выполнить обратный переход от полярной системы координат к декартовой?
168
одному обороту или 2π в радианах соответствует единица, т.е. синус берется
не от угла, а от оборота. Это очень удобно тем, что в формате Q24 перемен-
ная t может хранить 256 целых оборотов (значение t меняется от
+127,99999994 до –128). Так как число оборотов во всем диапазоне значений
t целое, то и функция синуса от числа оборотов будет непрерывной.
Зная об этой проблеме, разработчики библиотеки IQmath предусмотрели
целый ряд тригонометрических функций для работы с углами в относи-
тельных единицах: _IQsinPU, _IQcosPU и др. Полный перечень этих функ-
ций приведен в табл. 6.1.
Так как в дальнейшем предполагается выводить результаты работы филь-
тра в окно осциллографа с анализом спектра с помощью преобразования
Фурье, то будет удобно, если один период синуса основной гармоники будет
сформирован количеством точек, равным степени двойки. Поэтому новое
приращение для переменной t будет равно 1/256 (лист. 6.9).
б)
Практическая работа
Значение
GLOBAL_Q Вес младшего разряда
максимальное минимальное
Табл и ц а 6.3
Функции преобразования форматов в библиотеке IQmath
174
Практическая работа
1. Измените значение константы GLOBAL_Q, чтобы проект инерционного
фильтра, рассмотренный выше, работал с переменными в формате Q28. Сказы-
вается ли повышение точности представления переменных на работе фильтра?
2. Измените программу цифрового инерционного фильтра, чтобы он имел
2000-кратную перегрузочную способность по входному воздействию. Как
изменятся строки вызова процедуры фильтрации и передачи фильтру пара-
метров в функции main? Как сказывается уменьшение точности представле-
ния переменных на работе фильтра?
3. Проанализируйте код перевода числа формата GLOBAL_Q в формат
переменных модуля цифрового фильтра. Объясните суть производимых пре-
образований.
176
void main(void)
{
fteta=0;
teta=0;
ff=50;
f=_IQ(50);
fTpwm=1.0/5000;
Tpwm=_IQ(0.0002);
fpi=3.1415926535897932384626433832795;
pi=_IQ(3.1415926535897932384626433832795);
a=_IQ(2);
b=_IQ(2.5);
c=_IQ(3.3);
fa=2;
fb=2.5;
fc=3.3;
fd=fa*fb+fc;
d=_IQmpy(a,b)+c;
for(;;)
{
fteta+=2*fpi*ff*fTpwm;
fx=sin(fteta);
fy=cos(fteta);
teta+=_IQmpy(f,Tpwm);
x=_IQsinPU(teta);
y=_IQcosPU(teta);
}
}
177
а) б) в)
Практическая работа
ЭФФЕКТИВНЫЕ СПОСОБЫ
ЦИФРОВОЙ ФИЛЬТРАЦИИ СИГНАЛОВ
Структура КИХ-фильтра
В общем случае цифровой фильтр с конечной импульсной характеристи-
кой (КИХ-фильтр, в зарубежной терминологии — FIR-фильтр) описывается
следующим разностным уравнением:
N
y(n) = ∑ hk x ( n – k )
k=0
(7.1)
N –k
H(z) = ∑ hk z
k=0
. (7.2)
⎧ h , 0 < n < N;
h(n) = ⎨ n (7.3)
⎩ 0, otherwise.
179
Блок-схема фильтра (потоковая диаграмма сигналов) представлена на
рис. 7.1 и соответствует приведенным разностным уравнениям и дискретной
передаточной функции. Реализация такого цифрового фильтра в виде много-
секционной линии задержки по существу канонизирована в цифровой обра-
ботке сигналов (является общепринятым стандартом). Число элементов
задержки в линии задержки равно порядку фильтра.
Выходное управляющее воздействие (результат работы фильтра) пред-
ставляет собой сумму произведений величин, сохраненных в линии
задержки, на соответствующие коэффициенты. Заметьте, что число коэффи-
циентов в фильтре всегда на единицу больше, чем порядок фильтра. Это свя-
зано с тем, что текущая выборка x(n), которая представляет собой входное
воздействие, всегда участвует в процессе вычислений.
Входные и выходные решетчатые функции показаны на рис. 7.2. Здесь x0,
x1 и т.д. — это последовательные выборки входной переменной фильтра.
Если фильтр имеет, например, пятый порядок, то будет всего шесть коэффи-
циентов фильтра h0, h1, h2, h3, h4, h5, которые участвуют в расчете выходного
воздействия:
180
Рис. 7.2. Входные и выходные решетчатые функции
Кольцевые буфера
В системе команд микроконтроллеров ‘C28xx поддерживается несколько
способов адресации кольцевых буферов. Один из них реализуется с помо-
щью так называемой «бит-реверсной адресации» — косвенной адресации с
изменением направления распространения бита переноса. Он используется
во всех сигнальных процессорах Texas Instruments и является своеобразной
«визитной карточкой» процессоров этой фирмы. Некоторая сложность и
182
«ненаглядность» метода заставили разработчиков фирмы предложить дру-
гие, более очевидные по технологии использования методы адресации. В
качестве примера рассмотрим один из них, представленный на рис. 7.4.
Буфер выборок адресуется с использованием специального способа адре-
сации через регистр-указатель XAR6. Признаком такой особой адресации
является символ %, стоящий после имени регистра-указателя: *XAR6 %++.
Указатель, по достижении адреса последней ячейки буфера (верхней границы
буфера) автоматически переходит на первую ячейку буфера. При декремен-
тировании указателя контроль нижней границы кольцевого буфера отсут-
ствует. Это связано с тем, что в большинстве алгоритмов можно обойтись
без реверса направления прохода кольцевого буфера.
Предполагается, что под кольцевой буфер выделяется область памяти
данных, выровненная по числу 256, т.е., начальный адрес кольцевого буфера
может быть любым с восемью младшими битами, равными нулю. Конечный
адрес кольцевого буфера отличается от начального величиной смещения,
заданной в регистре AR1(7:0), точнее в младшем байте регистра AR1. Таким
образом, длина кольцевого буфера ограничивается 256 словами. Примени-
тельно к фильтру с конечной импульсной характеристикой объем кольцевого
буфера позволяет реализовывать фильтры вплоть до 255-го порядка включи-
тельно, что достаточно для большинства приложений.
Загрузка
новой выборки
Начальное состояние x[n] Состояние
кольцевого буфера кольцевого буфера
после прохода после загрузки выборки
XAR6
00000000 x[n – 3] x[n – 4]
Начальный x[n – 2] x[n – 3]
адрес x[n – 1] x[n – 2]
x[n] x[n – 1]
x[n – N] x[n]
Старшая часть
XAR6 x[n – (N – 1)] x[n – N]
указателя адреса
кольцевого буфера x[n – (N – 2)] x[n – (N – 1)]
AR6(31:8)
не меняется
адрес
x[n – 8] x[n – 9]
x[n – 7] x[n – 8]
x[n – 6] x[n – 7]
XAR6 x[n – 5] x[n – 6]
x[n – 4] x[n – 5]
AR1(7:0)
Конечный
адрес
183
Удобно хранить в кольцевом буфере выборки в обратном порядке — начи-
ная с самой «старой» выборки. В таком же порядке нужно записать и коэф-
фициенты фильтра в кодовую память: hN, hN – 1, hN – 2, …, h2, h1, h0, т.е. начиная
с коэффициента при самой «старой» выборке. Вычисления производятся,
начиная с самых «старых» значений выборок, в направлении «новых» значе-
ний с помощью команды умножения с накоплением MAC.
В этом случае перед запуском очередной процедуры фильтрации (нового
прохода фильтра) указатель кольцевого буфера XAR6 будет показывать на
«самую старую» выборку входной переменной x[n – N] (см. рис. 7.4). Она
должна быть заменена «новым» входным значением. Запись входной пере-
менной x[n] нужно выполнить по текущему указателю XAR6 c поставтоинк-
рементированием, используя адресацию кольцевых буферов. При этом ука-
затель будет автоматически показывать на «новое» самое «старое» значение:
для предыдущего прогона фильтра это переменная x[n – (N – 1)], а для оче-
редного прогона фильтра — переменная x[n – N] (см. правую часть рис. 7.4).
Операция умножения с накоплением сопровождается перемещением ука-
зателя XAR7 с автопостинкрементированием по буферу коэффициентов
фильтра в программной памяти и указателя XAR6 с автопостинкрементиро-
ванием и автоматическим контролем верхней границы кольцевого буфера, а
также возвратом к началу буфера при пересечении границы.
После вычисления выходной переменной фильтра указатель буфера коэф-
фициентов будет показывать на следующий после расположения таблицы
коэффициентов адрес («неизвестно куда») и должен быть обязательно пере-
инициализирован (при очередном вызове). Указатель кольцевого буфера вер-
нется на исходную позицию, т.е. будет опять показывать на «самую старую»
выборку, которая и должна быть заменена новым входным значением.
Если в кольцевом буфере расположены 16-разрядные слова, то их общее
количество будет на единицу больше порядка КИХ-фильтра, т.е. N + 1. При
этом в индексный регистр кольцевого буфера AR1(7:0) следует записать
число, равное порядку фильтра N. Например, фильтр пятого порядка имеет
шесть выборок данных, расположенных по адресам 0, 1, 2, 3, 4, 5. Макси-
мально допустимое смещение адреса кольцевого буфера равно пяти, т.е.
порядку фильтра. Если в кольцевом буфере расположены 32-разрядные
слова, то последняя ячейка кольцевого буфера будет иметь адрес 2*N, кото-
рый и должен быть загружен в индексный регистр AR1(7:0). Например, для
фильтра пятого порядка с 32-разрядными коэффициентами индексный
регистр кольцевого буфера загружается числом 5æ2 = 10.
+* +*
+
а)
Линейный буфер Кольцевой буфер
коэффициентов выборок
h5 h2 XAR6 x[n – 5] x[n – 2]
h4 h1 x[n – 4] x[n – 1]
h3 h0 x[n – 3] x[n]
XAR7
б)
1 ⎫
y ( n ) = h 2 x ( n – 2 ) + h 1 x ( n – 1 ) + h 0 x ( n ); ⎪
2
⎪
y ( n ) = h 5 x ( n – 5 ) + h 4 x ( n – 4 ) + h 3 x ( n – 3 ); ⎬ (7.5)
⎪
1 2 ⎪
y ( n ) = y ( n ) + y ( n ). ⎭
185
Обе операции умножения с накоплением должны производиться с учетом
установленного режима сдвига произведения (PM). Последняя операция
суммирования осуществляется без сдвига. После завершения расчета указа-
тель XAR7 на таблицу коэффициентов фильтра должен быть переинициали-
зирован. Указатель кольцевого буфера XAR6 вернется в исходную позицию.
Старшее слово 32-разрядного кольцевого буфера будет содержать самую старую
выборку x[n – 5], которая замещается младшим словом — выборкой x[n – 2].
На освободившееся место необходимо записать новую выборку x[n]. Эта
запись должна сопровождаться инкрементированием указателя кольцевого
буфера. Таким образом, указатель кольцевого буфера будет по-прежнему
показывать на слово с «самой старой» выборкой (с точки зрения нового про-
гона фильтра). Можно начинать новый расчет.
Если порядок фильтра четный, то число коэффициентов будет нечетным.
Самый простой способ работы с таким фильтром состоит в том, чтобы
искусственно повысить порядок фильтра на единицу и сделать самый стар-
ший коэффициент равным 0. Например, для фильтра четвертого порядка
можно выполнить расчет на базе фильтра пятого порядка с коэффициентом
h5 = 0. Никаких других изменений не требуется.
Установка индексного регистра кольцевого буфера AR1[7:0] должна быть
выполнена, как для буфера с 32-разрядными выборками. Общее число 16-
разрядных слов в буфере N + 1. Адрес последнего 16-разрядного слова на
единицу меньше, т.е. N. Адрес последнего двойного слова еще на единицу
меньше, т.е. N – 1.
Рассмотренные принципы организации вычислений графически проил-
люстрированы на рис. 7.5.
Диаграмма последовательной загрузки выборок в предварительно очи-
щенный кольцевой буфер фильтра показана на рис. 7.6.
Прежде чем привести ассемблерный текст функции, выполняющей рас-
чет КИХ-фильтра, необходимо описать соглашения по умолчанию, установ-
ленные разработчиками транслятора с языка высокого уровня С/С++ для вза-
имодействия программ на языке С/С++ и модулей, написанных на
Ассемблере.
Контрольные вопросы
1. Найдите в справочнике по системе команд обычную (не сдвоенную) команду
умножения с накоплением MAC. Опишите алгоритм ее выполнения.
2. Сравните производительность команд MAC и DMAC. Есть ли смысл при реализа-
ции КИХ-фильтров пользоваться более сложной командой DMAC?
3. Какую ассемблерную команду выберите для реализации КИХ-фильтра, работаю-
щего с 32-разрядными коэффициентами и выборками в формате 1.31? Нужна ли в этом
случае младшая часть частичных произведений?
186
Рис. 7.6. Диаграмма последовательной загрузки выборок
187
7.2. ИНТЕРФЕЙС С ПРОГРАММОЙ НА АССЕМБЛЕРЕ,
ВЫЗЫВАЕМОЙ ИЗ СИ-ПРОГРАММЫ
Соглашения по умолчанию
Интерфейс с функцией, написанной на языке Ассемблер, может быть пра-
вильным только в том случае, если строго следовать соглашениям по вызову
функций, а также соглашениям по использованию регистров центрального
процессора. В этом случае из программы на С/С++ гарантируется:
доступ к переменным, определенным в программе на Ассемблере, и
вызов функций, реализованных на Ассемблере;
доступ к переменным и функциям, объявленным в программе на C/C++,
из программы на Ассемблере.
Следуйте строго рекомендациям, приведенным ниже:
• все функции, где бы они ни были написаны: в программе на языке
С/С++ или на языке Ассемблер — должны выполнять установленные согла-
шения;
• модификация специально выделенных регистров центрального процес-
сора, обслуживающих процесс обмена между программными модулями,
должна быть заблокирована. К этим специальным регистрам относятся:
регистры-указатели XAR1, XAR2, XAR3 и указатель стека SP;
• если указатель стека используется нормальным образом (в соответ-
ствии с принятыми соглашениями), то специально заботиться о нем нет
необходимости. Ассемблерная функция свободна в использовании стека.
Она может записывать в стек любое число переменных, но должна следить
за тем, чтобы до возврата из процедуры все записанные переменные были
извлечены из стека. Это и есть обязательное условие корректной работы с
указателем стека SP. Например, если по каким-либо причинам ассемблерной
функции понадобится регистр-указатель XAR1 (в частности, для хранения
смещения верхней границы кольцевого буфера), то его текущее содержимое
до выполнения тела функции необходимо сохранить в стеке, а перед выхо-
дом из функции — извлечь из стека;
• любые другие регистры процессора, кроме специально зарезервиро-
ванных XAR1, XAR2, XAR3, SP, могут свободно использоваться без необхо-
димости сохранения их содержимого;
• если вызываете Си-функцию из программы на языке Ассемблер, то
загрузите аргументы в предназначенные для этого регистры и запишите в
стек оставшиеся аргументы в соответствии с тем, как описано в пункте
«Вызов функции» (см. с. 189). Те же самые соглашения работают и при
вызове функции на языке Си;
• так как при вызове функций на языке Си по умолчанию используется
специальный регистр адреса возврата счетчика команд RPC, то и в проце-
дурах на Ассемблере должны использоваться команды вызова и возврата,
работающие с этим регистром: LCR и LRETR;
188
• переменные типа long и float должны сохраняться в памяти следую-
щим образом: младшее значащее слово по младшему адресу, старшее — по
старшему адресу;
• структуры возвращаются так, как описано на с. 191 в п. 5 «Как отвечает
вызванная функция»;
• модуль на языке Ассемблер не должен использовать секцию .cinit ни
для каких других задач, кроме инициализации глобальных переменных. Нару-
шение таблицы инициализации посредством записи в секцию .cinit другой
информации может вызвать непредсказуемые последствия;
• компилятор С/C++ автоматически добавляет к каждому идентифика-
тору предшествующий ему символ подчеркивания (_). Таким образом,
если хотите обратиться из модуля на языке Ассемблер к какому-либо объ-
екту на языке Си, то должны перед именем этого объекта указать символ
подчеркивания. Например, если на языке С/C++ объект имеет имя x, то из
программы на Ассемблере к нему следует обратиться по имени _x. Это сде-
лано для того, чтобы в программах на Ассемблере и С/С++ можно было
пользоваться одинаковыми идентификаторами без возникновения конфликта
имен;
• любой объект или функция, которые описаны в программе на языке
Ассемблер и которые должны быть доступны или вызываться из программы
на С/С++ должны быть объявлены как глобальные с помощью специальных
директив Ассемблера .global или .def. Эти директивы объявляют соответс-
твующие символические имена «публично доступными», что позволяет ком-
поновщику разрешать все ссылки на них из программы на языке C/C++;
• соответственно доступ из ассемблерной программы к функции на
языке С/С++ или какому-либо объекту должен сопровождаться объявлением
имени этой функции или объекта как внешнего имени с помощью директив
.global или .ref. В этом случае при трансляции ассемблерного файла будет
создана неразрешенная внешняя ссылка, разрешение которой выполнит уже
компоновщик (т.е. назначит фактический адрес).
Вызов функции
Если вызывающая функция производит вызов другой функции, то она
выполняет следующую последовательность действий:
1) содержимое некоторых регистров центрального процессора, которые
содержат значения переменных, не используемых в вызываемой функции,
однако необходимых для последующих расчетов после возврата результата
из вызываемой функции, должно быть сохранено в стеке, если вызываемая
функция может изменить значения этих регистров;
2) если вызываемая функция возвращает структуру, то вызывающая
функция выделяет место в памяти под эту структуру и передает адрес этого
места в вызываемую функцию в качестве первого аргумента. Обратите осо-
бое внимание на это правило, так как оно является базовым при создании
библиотечных функций на Ассемблере;
189
3) аргументы, передаваемые вызываемой функции, размещаются в регис-
трах и, если это необходимо, в стеке. При размещении аргументов в регист-
рах используется следующая схема:
а) если имеется несколько 32-разрядных аргументов (типа long или
float), то первый аргумент помещается в 32-разрядный аккумулятор
ACC(AH/AL). Все другие 32-разрядные аргументы или указатели функ-
ций размещаются в стеке в обратном порядке;
б) аргументы типа указателей (Pointer arguments) размещаются в
регистрах XAR4 и XAR5. Все другие указатели размещаются в стеке;
в) остающиеся 16-разрядные аргументы размещаются в следующей
последовательности, если это возможно: AL, AH, XAR4, XAR5;
4) некоторые оставшиеся аргументы, которые не были размещены в
регистрах, размещаются в стеке в обратном порядке. Таким образом, самый
левый аргумент будет записан в стек самым последним. Все 32-разрядные
аргументы выравниваются в стеке по четным адресам;
5) аргументы типа структуры передаются адресами этих структур. Вызы-
ваемая функция должна сделать локальную копию этой структуры.
Для функций, которые объявлены с пропусками, т.е. функций, которые
вызываются с варьируемым числом аргументов, соглашения несколько
модифицируются. Последний, явно задекларированный аргумент размеща-
ется в стек так, что его адрес в стеке может использоваться как ссылка для
доступа к другим незадекларированным аргументам.
Пример вызова функции, который показывает, где размещаются аргу-
менты, представлен ниже:
func1 (int a, int b, long c);
XAR4 XAR5 AH/AL
func1 (long a, int b, long c);
AH/AL XAR4 stack
vararg (int a, int b, int c,...)
AL AH stack
Вызванная функция возвращает управление вызывающей функции по
команде «длинного» возврата из подпрограммы LRETR. В счетчик команд
записывается значение из регистра RPC (это и есть адрес возврата), далее из
стека в регистр RPC восстанавливается предыдущий адрес возврата.
193
Лист. 7.3. Содержание заголовочного файла fir.h
typedef struct {
long *coeff_ptr; /* Указатель на коэффициенты
фильтра. */
long *dbuffer_ptr; /* Указатель на буфер выбо-
рок. */
int cbindex; /* Верхняя граница кольце-
вого буфера. */
int order; /* Порядок фильтра. */
int input; /* Входное значение (новая
выборка). */
int output; /* Выходное значение филь-
тра. */
void (*init)(void *); /* Указатель на функцию ини-
циализации. */
void (*calc)(void *); /* Указатель на функцию
обработки */
} FIR16;
Для создания нескольких экземпляров модулей цифровой фильтрации
необходимо просто объявить нужное число переменных типа FIR16. Таким
образом, в одной и той же программе могут работать сразу несколько филь-
тров разного порядка, с разными настройками (коэффициентами), каждый из
которых будет иметь свой собственный кольцевой буфер выборок и таблицу
коэффициентов. При этом алгоритм работы всех фильтров унифицируется.
По существу обработчик является общим. Каждый раз он будет работать с
теми параметрами, которые переданы ему при вызове.
Дальше описывается так называемый инициализатор структуры модуля филь-
тра FIR16_DEFAULTS, который обеспечивает инициализацию значений перемен-
ных типа FIR16 и настраивает указатели на нужные функции (лист. 7.4). Вслед за
этим приводится описание прототипов ассемблерных функций (лист. 7.5).
Лист. 7.4. Инициализатор структуры модуля фильтра
#define FIR16_DEFAULTS { (long *)NULL, \
(long *)NULL, \
0, \
50, \
0,\
0,\
(void (*)(void *))FIR16_init,\
(void (*)(void *))FIR16_calc}
Лист. 7.5. Прототипы ассемблерных функций
void FIR16_init(void *);
void FIR16_calc(void *);
В файле содержится также несколько инициализаторов коэффициентов
фильтров для наиболее часто применяемых фильтров: низкочастотного,
высокочастотного и полосового.
194
Для экспериментов предлагаем использовать фильтры 50-го порядка,
у которых число коэффициентов равно 51. Так как алгоритм фильтрации,
реализованный с помощью команды двойного умножения с накоплением,
требует объединения коэффициентов в длинные слова, то порядок фильтра
искусственно увеличивается на единицу и число слов с коэффициентами
оказывается равным (51 + 1)/2 = 26.
Помните, что каждый из коэффициентов представлен в формате 1.15
(в относительных единицах). Два коэффициента объединены в одно длинное
слово и используются в инициализаторе. Как рассчитать коэффициенты цифро-
вого фильтра с помощью специальных компьютерных программ, если задана
частота дискретизации фильтра, его тип и полоса пропускания, показано ниже.
Лист. 7.6. Инициализатор коэффициентов фильтра
#define FIR16_LPF50 {\
1292,4261126,4654326,5440731,6751414,8455303,10749008,\
13501458,16712654,20382597,24445752,28902122,33620635,38601293,\
43713025,48890297,54002037,59048247,63832319,68288718,\
72351908,75956353,79036519,81461331,83230791,84279361}
195
Лист. 7.7. Пример работы с КИХ-фильтром
/*======================================
* Работа 7.
* Пример использования фильтра FIR16.
*=====================================*/
#include "IQMathLib.h"
#include "fir.h"
#define FIR_ORDER 50 /*Порядок фильтра. */
// Создание экземпляра модуля цифровой фильтрации fir
FIR16 fir= FIR16_DEFAULTS;
/* Определение буфера выборок для фильтра 50-го порядка и
размещение в секции "firldb". */
#pragma DATA_SECTION(dbuffer,"firldb");
long dbuffer[(FIR_ORDER+2)/2];
/* Определение массива постоянных коэффициентов
и его инициализация. */
long coeff[(FIR_ORDER+2)/2]= FIR16_LPF50;
/* Определяем переменные.*/
float SigInFreq = 100.0; // Частота входного сигнала, Гц.
float FiltPer = 0.0001; // Время дискретизации фильтра, с.
long l_counter = 0; // Счетчик для контроля работы программы.
int sin_value = 0; // Значение синуса.
int sin_filter = 0; // Значения отфильтрованного сигнала.
/* Начало основной программы. */
void main()
{ /* Инициализация модуля фильтра. */
fir.order=FIR_ORDER; // Настраиваем порядок фильтра.
fir.dbuffer_ptr= dbuffer;
//Передаем адрес буфера выборок.
fir.coeff_ptr=coeff;
//Передаем адрес массива коэффициентов.
fir.init(&fir); //Вызываем функцию инициализации.
/*Основной цикл программы.*/
while(1)
{
l_counter++; // Инкрементируем счетчик.
// Определение шага дискретизации угла.
Teta+= _IQ16mpy(_IQ16(SigInFreq),_IQ16(FiltPer));
// Т.к. значение sin имеет формат 16.16, то
// входной сигнал приводим к формату 1.15.
sin_value =_IQ16sinPU(Teta)>>1;
fir.input = sin_value;
//Передаем новое значение на вход фильтра
fir.calc(&fir); //Вызываем функцию подсчета.
sin_filter = fir.output;
//Передаем значение в программу.
}
}
196
Практическая работа
1. Самостоятельно получите осциллограммы работы фильтра низкой час-
тоты, представленные на рис. 7.9.
а)
б)
в)
Рис. 7.9. Работа фильтра:
а—в — на частоте 50, 100 и 200 Гц соответственно
197
2. В каких единицах измеряется время на осциллограммах? Соответ-
ствует ли период входного и выходного сигнала заданной частоте?
3. Убедитесь, что амплитуда и угол отставания отфильтрованного сигнала
от входного соответствуют расчетным АЧХ и ФЧХ фильтра (см. рис. 7.8).
4. Измените код программы таким образом, чтобы получить входной
синусоидальный сигнал с шумом. Исследуйте степень подавления шума на
разных частотах.
Практическая работа
б)
Контрольные вопросы
1. Приведите конкретные примеры из области привода и силовой электроники необ-
ходимости использования различных типов цифровых фильтров.
2. Можно ли одновременно в приложении использовать несколько фильтров низкой
частоты с различной полосой пропускания? Будут ли они иметь общую программу-обра-
ботчик? Общий буфер выборок?
3. Почему буфер выборок располагается в специально выделенной для этого секции
данных, а все остальные переменные — в общей памяти данных?
200
7.5. ФИЛЬТРЫ 16- И 32-РАЗРЯДНЫЕ
С БЕСКОНЕЧНОЙ ИМПУЛЬСНОЙ ХАРАКТЕРИСТИКОЙ
Общая информация о рациональной структуре фильтра.
Биквадратные секции
В общем случае фильтр с бесконечной импульсной характеристикой IIR,
представленный на рис. 7.13, описывается следующим разностным уравнением:
N N
y(n) = – ∑ a k y ( n – k ) + k∑
k=0 =0
bk x ( n – k ) (7.6)
z–1 z–1
d1(n – 1) d2(n – 1)
z–1 z–1
d1(n – 2) d2 (n – 2)
201
Рассмотрим принцип реализации биквадратного фильтра более подробно
на примере одной секции второго порядка.
Разностное уравнение для БИХ-фильтра второго порядка имеет вид
y(n) = b0x(n) + b1x(n – 1) + b2x(n – 2) – a1y(n – 1) – a2 y(n – 2). (7.8)
Выполняя дискретное преобразование Лапласса, получаем следующую
дискретную передаточную функцию:
–1 –2
y [ z ] b0 + b1 z + b2 z
H [ z ] = ---------- = ----------------------------------------------- . (7.9)
x[z] 1 + a1 z + a2 z
–1 –2
⎛ ⎞
–
1
1 – 2
( –1
= H 1 [ z ]H 2 [ z ] = ⎜ ---------------------------------------------⎟ b 0 + b 1 z + b 2 z
–2
. ) (7.10)
⎝1 + a z + a z ⎠
1 2
x(n) y(n)
b0 +
z–1 z–1
x(n – 1) b1 –a1 y(n – 1)
z–1 z–1
x(n – 2) b2 –a2 y(n – 2)
а)
z–1
d(n – 1)
–a1 b1
z–1
d(n – 2)
–a2 b2
б)
202
Первая передаточная функция соответствует рекурсивному фильтру (РФ),
описываемому разностным уравнением:
d(n) = x(n) – a1d(n – 1) – a2d(n – 2), (7.11)
coeff_ptr
a21 Младший адрес dk(n – 1)
a11 dk(n – 2)
b21
b11
d2(n – 1)
b01
d2(n – 2)
a22
d1(n – 1)
a12 dbuffer_ptr
d1(n – 2)
b22
b12
b02
a2k
a1k
b2k
b1k
сива коэффициентов a2k, a1k, b2k, b1k, b0k, где k — номер биквадратной сек-
ции. Каждая секция имеет в буфере выборок две ячейки для хранения пере-
менных dk(n – 1) и dk(n – 2). После выборки этих переменных в процессе
расчета фильтра должны выполняться операции копирования: dk(n – 1) →
→ dk(n – 2); dk(n) → dk(n – 1).
Отличие 32-разрядного фильтра от 16-разрядного состоит только в раз-
рядности коэффициентов и переменных. Коэффициенты и переменные
буфера выборок являются длинными словами. Младшее слово располагается
по меньшему адресу.
204
Исследование модуля фильтра
с бесконечной импульсной характеристикой (IIR)
Модуль реализует каскадный биквадратный фильтр с бесконечной
импульсной характеристикой (IIR filter) на основе 16- и 32-разрядной линии
задержки.
Откройте рабочее пространство lab7/debug/iir.wks. Скомпилируйте про-
ект и загрузите его в микроконтроллер (рис. 7.16).
205
Окончание лист. 7.8
int qfmat; /* Q формат коэффициентов Q0. */
int output; /* Выход фильтра Q14. */
}IIR5BIQ16;
//Определение структуры модуля фильтра IIR5BIQ32.
typedef struct {
void (*init)(void *); //Указатель на функцию инициализации.
void (*calc)(void *); //Указатель на адрес вызова функции.
long *coeff_ptr; // Указатель на коэффициенты фильтра.
long *dbuffer_ptr; // Указатель на буфер задержки.
int nbiq; /* Число биквадратных секций фильтра Q0. */
int input; /* Последняя входная выборка данных Q15. */
long isf; /* Коэффициент масштабирования входа. */
long output32; /* Выход фильтра в формате Q30. */
int output16; /* Выход фильтра в формате Q14. */
int qfmat; /* Q формат коэффициентов Q0. */
}IIR5BIQ32;
Определение модуля создается как специальный тип данных. Это удобно
для организации интерфейса с модулем фильтра IIR16. Для того чтобы
создать множество экземпляров модуля, необходимо просто объявить нуж-
ное число переменных типа IIR5BIQ16. Таким образом, в одной и той же
программе могут работать сразу несколько программ фильтрации.
Описание констант приведено ниже:
Лист. 7.9. Инициализатор структуры модулей фильтров
#define IIR5BIQ16_DEFAULTS { (void (*)(void
*))IIR5BIQ16_init,\
(void (*)(void *))IIR5BIQ16_calc,\
(int *)NULL, \
(int *)NULL, \
0, \
0, \
0, \
0, \
0}
#define IIR5BIQ32_DEFAULTS { (void (*)(void
*))IIR5BIQ32_init,\
(void (*)(void *))IIR5BIQ32_calc, \
(long *)NULL, \
(long *)NULL, \
0, \
0, \
0, \
0, \
0, \
0}
206
IIR5BIQ16_DEFAULTS и IIR5BIQ32_DEFAULTS — структуры сим-
вольных констант для инициализации модулей IIR5BIQ16 è IIR5BIQ32.
Описываются прототипы функций для инициализации фильтра IIR и для
вычисления выходного значения фильтра:
207
Окончание лист. 7.12
int sin_filter = 0; //Значение выходного отфильтрован-
ного сигнала.
/* Начало основной программы. */
void main(void)
{/* Инициализация модуля фильтра. */
iir.dbuffer_ptr=dbuffer;
iir.coeff_ptr=(int *)coeff;
iir.qfmat=IIR16_LPF_QFMAT;
iir.nbiq=IIR16_LPF_NBIQ;
iir.isf=IIR16_LPF_ISF;
iir.init(&iir);
/* Основной цикл программы. */
while(1)
{
l_counter++; // Инкрементируем счетчик.
//Определение приращения электрического угла
Teta+= _IQ16mpy(_IQ16(SigInFreq),_IQ16(FiltPer));
//Так как выходное значение функции sin имеет
//формат 16.16, приводим входной сигнал к формату 1.15
sin_value =_IQ16sinPU(Teta)>>1;
iir.input = sin_value;
iir.calc(&iir);
sin_filter = iir.output;
}
} /* Конец программы. */
Практическая работа
1. Исследуйте приложение MatLab для генерации коэффициентов IIR-
фильтров.
2. Пользуясь описанной в предыдущей главе технологией, убедитесь в
правильности работы IIR-фильтра низкой частоты.
Контрольные вопросы
1. К какому из типов фильтров (КИХ, БИХ) можно отнести простейшие ПИ-, ПИД-,
ПИИ-регуляторы?
2. Какова последовательность работы с библиотечными функциями цифровой филь-
трации, написанными на Ассемблере?
208
Глава 8
Udc
le_зад
ПИ
Силовой
Модуль
трехфазный
ШИМ
инвертор
la_зад
ПИ
le
la
ДПТ
209
образом, на базе классического инвертора напряжения создается сразу два
преобразователя для двухзонной (с ослаблением поля и без) четырехквад-
рантной системы управления ДПТ, которая применяется обычно в станоч-
ных электроприводах.
Система управления реализуется на сигнальном микроконтроллере и
обеспечивает формирование ШИМ-сигналов управления четырьмя ключами
ПЯ и одним ключом ПВ на базе многоканального ШИМ-генератора менед-
жера событий. Несущая частота ШИМ высокая — до 5—10 кГц. Обратные
связи по току якоря (далее индекс «а») и току возбуждения (далее индекс
«е») реализуются с помощью гальванически развязанных датчиков тока типа
«ЛЕМ», выходные сигналы которых вводятся в контроллер через АЦП. Регу-
ляторы токов программно реализованные.
На схеме не показаны датчик скорости, в качестве которого можно
использовать тахогенератор или импульсный датчик положения, и регулятор
скорости. В первом случае для ввода сигнала с тахогенератора используется
АЦП, а во втором — «квадратурный декодер» менеджера событий. Регуля-
тор скорости, как и регуляторы токов, реализуется программно.
Все расчеты в системе управления должны выполняться за один период
ШИМ, который является интервалом дискретизации. Модель объекта управ-
ления может иметь тот же самый интервал квантования. В данной главе в
целях упрощения системы к объекту управления отнесены кроме двигателя
и силовых преобразователей также датчики токов и скорости.
M – M с = J Σ dω
------- ; (8.3)
dt
M = (kΦ)iя; (8.4)
( kΦ ) ном
kΦ = --------------------
-i . (8.5)
i в ном в
Первое уравнение описывает контур возбуждения машины, второе —
цепь якоря, третье — является уравнением движения, четвертое — опреде-
ляет связь между током якоря и электромагнитным моментом машины,
210
а пятое — между потоком и током возбуждения. В общем случае последнее
уравнение может быть нелинейным и задавать так называемую кривую
намагничивания машины. Модель двигателя постоянного тока имеет
несколько параметров:
Rв — активное сопротивление цепи возбуждения;
Lв — индуктивность цепи возбуждения;
Rя — активное сопротивление цепи якоря;
Lя — индуктивность цепи якоря;
(kΦ)ном — номинальное значение коэффициента передачи между током
якоря iя и электромагнитным моментом M, между электродвижущей силой E
и скоростью ω;
JΣ — суммарный момент инерции двигателя и присоединенных масс;
Mс — момент статической нагрузки.
Смоделируем работу двигателя непосредственно в сигнальном микрокон-
троллере. Для повышения скорости вычислений откажемся от использова-
ния арифметики с плавающей точкой в пользу арифметики с фиксированной
точкой, поддерживаемой библиотекой IQMath. При этом обязательным тре-
бованием является переход от физических единиц к относительным.
Удобно за базовые величины принять такие, которые характеризуют
работу двигателя в номинальном режиме. Так как кратности превышения
номинальных переменных машины (тока якоря, тока возбуждения, момента,
скорости) не превышают 5—7, то для представления переменных можно
использовать формат 4.28, обеспечивающий наибольшую точность расчетов.
Формат 8.24 позволяет получить несколько больший и гарантированно
достаточный динамический диапазон представления переменных без суще-
ственного ухудшения точности. В качестве базового времени удобно выбрать
единицу физического времени — 1 с. При этом все процессы в модели будут
протекать в том же масштабе времени, что и в реальном двигателе.
Итак, за базовые значения переменных в цепи возбуждения принимаются:
Uв баз = Uв ном; (8.6)
iв баз = iв ном; (8.7)
tбаз = Tбаз = 1 с. (8.8)
Если выбрать базовые значения сопротивления и индуктивности в кон-
туре возбуждения через уже определенные базовые величины:
U в баз
R в баз = -------------- ; (8.9)
i в баз
U в баз T баз
L в баз = ------------------------- , (8.10)
i в баз
211
то уравнение цепи возбуждения в относительных единицах не будет отли-
чаться от соответствующего уравнения в физических единицах, за исключе-
нием символа «*», характеризующего относительные переменные:
*
* * * * di в
Uв = Rв iв + L в ------- , (8.11a)
*
dt
или
*
* *⎛ * * di в⎞
Uв = Rв ⎜ iв + T в -------⎟ , (8.11б)
⎝ *
dt ⎠
*
где R в — безразмерное значение активного сопротивления цепи возбужде-
*
ния; L в — безразмерное значение индуктивности цепи возбуждения;
*
* Lв
Tв = ------ — безразмерная постоянная времени контура возбуждения, чис-
*
Rв
ленно совпадающая со значением реальной постоянной времени.
Принимая для цепи якоря за базовые значения электрических перемен-
ных (напряжения и тока) их номинальные значения, а за базовое значение
скорости — скорость идеального холостого хода двигателя при номинальном
напряжении на якоре и номинальном токе возбуждения, получаем похожее
уравнение, отличающееся от своего аналога в физической области только
символами «*» безразмерных переменных и параметров:
Uя баз = Uя ном; (8.12)
iя баз = iя ном; (8.13)
tбаз = Tбаз = 1 с; (8.14)
U я баз
R я баз = -------------- ; (8.15)
i я баз
U я баз T баз
L я баз = ------------------------- ; (8.16)
i я баз
U я баз
ω баз = ω 0 ном = ------------------- , (8.18)
( kΦ ) баз
откуда
212
*
* * * * di я * *
Uя = Rя iя + L я ------- + ( kΦ ) ω , (8.19)
*
dt
или
*
* *⎛ * * di я⎞ * *
Uя = Rя ⎜ iя + T я -------⎟ + ( kΦ ) ω , (8.20)
⎝ *
dt ⎠
*
где R я — безразмерное значение активного сопротивления цепи якоря;
*
* Lя *
Lя — безразмерное значение индуктивности цепи якоря; = ------ — безраз- Tя
*
Rя
мерная постоянная времени якоря, численно равная электромагнитной посто-
янной времени двигателя в физических единицах.
Примем за базовое значение электромагнитного момента двигателя его
номинальное значение при номинальном токе якоря и номинальном токе воз-
буждения:
Mбаз = Mном = (kΦ)номiя ном. (8.21)
В теории электропривода инерционность механических процессов учи-
тывается так называемой электромеханической постоянной времени. Ее зна-
чение равно времени разгона двигателя без нагрузки от нуля до скорости
идеального холостого хода при номинальном значении электромагнитного
момента:
J Σ ω баз
T м = ----------------- . (8.22)
M баз
С учетом этих соотношений уравнение механического равновесия двига-
теля в относительных единицах примет вид
*
* * * dω
M – M c = T м ---------- , (8.23)
*
dt
* Tм
где T м = ---------- — безразмерная электромеханическая постоянная времени.
T баз
Два последних уравнения, связывающих между собой ток с моментом и
поток с током возбуждения, в относительных единицах примут еще более
простой вид:
* * *
M = ( kΦ ) i я ; (8.24)
* *
( kΦ ) = i в . (8.25)
213
Таким образом, двигатель постоянного тока с управлением по цепи якоря
и возбуждения может быть описан системой дифференциальных уравнений
третьего порядка:
*
* *⎛ * * di в⎞
Uв = Rв ⎜ iв + T в -------⎟ ; (8.26)
⎝ *
dt ⎠
*
* *⎛ * * di я⎞ * *
Uя = Rя ⎜ iя + T я -------⎟ + iв ω ; (8.27)
⎝ *
dt ⎠
*
* * * * dω
i в i я – M c = T м ---------- . (8.28)
*
dt
Обратите внимание на то, что динамика двигателя полностью определя-
*
ется соотношением постоянных времени: возбуждения T в , электромагнит-
* *
ной T я и электромеханической T м . Более того, численные значения безраз-
мерных постоянных времени равны соответствующим физическим
значениям этих постоянных. Это очень удобно при отладке и настройке сис-
темы управления. Выбранная система базовых величин действительно упро-
щает цифровую реализацию модели ДПТ, однако не лишена недостатков.
Необходимо помнить, что базовые значения токов и напряжений, сопротив-
лений и индуктивностей в цепях якоря и возбуждения различаются. Вслед-
ствие этого, например, базовые значения мощностей по цепям якоря и воз-
буждения различны. Для расчета полной мощности, потребляемой
двигателем, потребуется корректирующий коэффициент.
Структурная схема двигателя постоянного тока в относительных единицах
представлена на рис. 8.2. Соответствующие передаточные функции двигателя
будут использованы далее при синтезе регуляторов системы управления.
ω*
x
iв*
E* –
Uя* 1/Rя* iя* M* 1 ω*
x
+ Tя*p + 1 + – Tм*p
Mс*
214
Контрольные вопросы
1. Получите передаточную функцию ДПТ по управлению по цепи якоря, считая, что
ток в контуре возбуждения установлен и равен номинальному.
2. Отношением каких двух постоянных времени будет определяться качество пере-
ходных процессов в двигателе? Сформулируйте условие апериодического процесса,
колебательного.
*
di я * * * 1- i *
*
1
------- = ------------
* *
( U я – i в ω ) – -----
* я
; (8.30)
dt Rя Tя Tя
*
1 * * *
- ( i i – Mс ) .
dω
---------- = ----- (8.31)
* * в я
dt Tм
Заменив непрерывные переменные дискретными, а производные левыми
разностями:
* * *
dx x [k] – x [k – 1]
-------- ⇒ -------------------------------------------- ,
* *
dt T диск
получим:
* *
iв [ k ] – iв [ k – 1 ] 1 * 1 *
------------------------------------------ = ------------ U в [ k ] – ------ i в [ k ] ; (8.32)
* * * *
T диск Rв Tв Tв
* *
iя [ k ] – iя [ k – 1 ] *
1
------------------------------------------ = ------------
* * *
( U я [ k ] – i *в [ k ]ω * [ k ] ) – -----
1 *
-i [k] ;
* я
(8.33)
T диск Rя Tя Tя
* *
ω [k] – ω [k – 1] 1 * * *
- ( i [ k ]i я [ k ] – M с ) .
---------------------------------------------- = ----- (8.34)
* * в
T диск Tм
215
После выделения значений переменных на k-м интервале квантования
через значения переменных на предыдущем (k – 1)-м интервале квантования,
система разностных уравнений примет вид:
* * *
iв [ k ] = K1 Uв [ k ] + K2 iв [ k – 1 ] ; (8.35)
* * * * *
i я [ k ] = K 3 ( U я [ k ] – i в [ k ]ω [ k ] ) + K 4 i я [ k – 1 ] ; (8.36)
* * * * *
ω [ k ] = K 5 ( i в [ k ]i я [ k ] – M с ) + ω [ k – 1 ] , (8.37)
где значения пяти коэффициентов, описывающих поведение двигателя в
динамике, равны:
*
T диск
K 1 = --------------------------------------- ; (8.38)
* * *
R в ( T в + T диск )
*
Tв
K 2 = -------------------------- ; (8.39)
* *
T в + T диск
*
T диск
K 3 = --------------------------------------- ; (8.40)
* * *
R я ( T я + T диск )
*
Tя
K 4 = -------------------------- ; (8.41)
* *
T я + T диск
*
T диск
K 5 = ------------- . (8.42)
*
Tм
Как видите, дискретная модель ДПТ представляет собой систему разно-
стных уравнений третьего порядка, реализация которой в микроконтроллере
требует использования, главным образом, операций умножения с накопле-
нием. Коэффициенты K1—K5 вычисляются один раз в процессе инициализа-
ции системы по пяти параметрам двигателя и относительному значению
интервала квантования.
0 0,5 1 γ –1 +1 U *
y ПЯ
–Udc
–Ud*c я
а) б)
+Ud*c я
Uy*ПЯ Ud*c я U *вых ПЯ
Tп*p + 1
–Ud*c я
+Ud*c в
Uy*ПВ Ud*c в U *вых ПВ
Tп*p + 1
–Ud*c в
со следующими коэффициентами:
220
* *
Rя Tя
k п р.т = ------------------------- ; (8.47)
* *
a т U dc я T п
* *
* a т U dc я T п
T и р.т = ------------------------- . (8.48)
*
Rя
Контрольные вопросы
1. Будет ли возникать динамическая ошибка по току при разгоне двигателя, когда
ЭДС станет отлична от нуля?
2. Почему при синтезе регулятора тока мы приняли коэффициент обратной связи по
току равным единице. Допустимо ли это? Будет ли это соответствовать системе с реаль-
ным датчиком, сигнал которого вводится в АЦП?
221
Синтез регулятора скорости
Если произвести настройку контура тока с коэффициентом aт ≥ 2, то пере-
даточная функция замкнутого контура тока может быть с высокой точностью
представлена в виде
1
W зам т = ------------------------- . (8.53)
*
aт Tп p + 1
В теории электропривода доказывается, что для синтеза регулятора ско-
рости можно в первом приближении пренебречь обратной связью по ЭДС
двигателя и представить контур скорости в виде, изображенном на рис. 8.7.
Если выбрать в качестве «некомпенсированной» постоянной времени
*
эквивалентную постоянную времени замкнутого контура тока a т T п , то жела-
емая передаточная функция контура скорости запишется следующим обра-
зом:
жел 1
W раз с = ----------------------------------------------------------- . (8.54)
* *
a с ( a т T п p )( a т T п p + 1 )
+i *я пуск
ω*зад Δω* i *я зад M* ω*
1 1
РС
атTп*p + 1 Tм*p
–
ω* –i *я пуск
222
8.6. ПОСТРОЕНИЕ ПРОЕКТА ШАГ ЗА ШАГОМ
Общая структура управления
двигателем постоянного тока
Ток в контуре возбуждения и ток цепи якоря регулируются с использова-
нием стандартного шестиключевого инвертора напряжений.
В этом параграфе основное внимание уделено непосредственно системе
управления. Информация о программировании периферийных устройств,
АЦП и ШИМ может быть найдена на сайте www.ti.kom.
Практическая работа
1. Запустите CodeComposer.
2. Из папки myprojects\lab8\Debug\ загрузите рабочее пространство
(workspace) main.wks. Разверните в менеджере проекта папку source и выбе-
рете файл main.c. Откроется окно, показанное на рис. 8.8.
Все строки программы имеют комментарии, по которым можно понять
значение кода. Изучите этот файл.
Справа находятся два графических окна, в которых будут отображаться
наблюдаемые переменные.
223
Лист. 8.1. Структура файла main.c
//файл main.c
//подключаем заголовочные файлы//
//библиотека работы с фиксированной точкой
#include "IQmathLib.h"
//описание регистров и периферийных устройств
//микроконтроллера
#include "DSP28_Device.h"
//описание переменных и функций главного модуля
#include "main.h"
// определение параметров ДПТ
#include "parameter.h"
// определение уровня построения проекта
#include "build.h"
// прототип функции описанной в этом файле
// основное прерывание ШИМ
interrupt void EvaTimer1(void);
// Глобальные переменные используемые в этой системе
float U_e_ref = 1; /* Задание напряжения обмотки возбуж-
дения (о.е) */
float U_a_ref=1; //Задание напряжения обмотки якоря (о.е)
float Mc_ref=0; //Задание момента сопротивления (о.е)
float Ia_ref=1; //Задание тока якоря для ПИ регулятора (о.е)
float speed_ref = 0.5; /* Задание скорости для регуля-
тора скорости (о.е) */
float T = SAMPLING_PERIOD; /* Период дискредизации объ-
явлен в parameter.h */
int isr_ticker = 0; /*счетчик прерываний ШИМ*/
// создание и инициализация модели ДПТ с НВ
BDCM bdcm =BDCM_DEFAULTS;
/* создание объекта пересчета параметров двигателя
в константы для модели ДПТ с НВ*/
BDCM_CONST bdcm_const = BDCM_CONST_DEFAULTS;
/*создание объекта управления ШИМ выходами*/
PWMGEN pwm =PWMGEN_DEFAULTS;
/* создание ПИ регуляторов*/
PI_REG pi_ia = PI_REG_DEFAULTS;
PI_REG pi_spd = PI_REG_DEFAULTS;
//НАЧАЛО ВЫПОЛНЕНИЯ ПРГРАММЫ
void main(void)
{//Инициализация регистров управления микроконтроллером,
//PLL,WatchDog
//Все часы устанавливаются в номинальное состояние
//Функция находиться в файле DSP28_SysCtrl.c
InitSysCtrl();
224
Продолжение лист 8.1
//Отключение и очистка всех прерываний CPU:
DINT;
IER = 0x0000;
IFR = 0x0000;
//Инициализация регистров управления прерываниями
//Функция находится в файле DSP28_PieCtrl.c
InitPieCtrl();
//Инициализация таблицы векторов прерывания в известные
//состояния
//Функция находится в файле DSP28_PieVect.c
//Таблица векторов прерывания заполняется указателями
//описанными в DSP28_DefaultIsr.c.
InitPieVectTable();
// Инициализация 1 таймера менеджера событий А
// (EVA Timer 1):
// Устанвка регистра управления
EvaRegs.GPTCONA.all = 0;
// Разрешение прерывания по событию Underflow
EvaRegs.EVAIMRA.bit.T1UFINT = 1;
EvaRegs.EVAIFRA.bit.T1UFINT = 1;
// Переопределение прерываний.
EALLOW;// Требуется разрешение на запись EALLOW
PieVectTable.T1UFINT = &EvaTimer1;
EDIS; // Запрещаем запись в защищенные регистры
// Разрешаем группу 2 (PIE group 2) прерывание 6 для T1UFINT
PieCtrlRegs.PIEIER2.all = M_INT6;
// Разрешаем CPU INT2 для T1UFINT:
IER |= M_INT2;
// Разрешаем глобальные прерывания для высокоприоритетных
// прерываний реального времени
EINT; // Разрешаем глобальное прерывание INTM
ERTM; /*Разрешаем глобальное прерывание реального вре-
мени DBGM*/
/* Инициализируем модуль ШИМ */
/* Частота прерываний для центрированной ШИМ = 5 kHz
при тактовой 150MГц (0x3A98 = 15000) */
pwm.n_period = 0x3a98;
//инициализируем модуль ШИМ
pwm.init(&pwm);
/* Инициализируем модуль подсчета констант */
bdcm_const.Re = R_EX;
bdcm_const.Le = L_EX;
bdcm_const.Ue_base = BASE_VOLTAGE_EX;
bdcm_const.Ie_base = BASE_CURRENT_EX;
225
Окончание лист 8.1
bdcm_const.Ra = R_A;bdcm_const.La = L_A;
bdcm_const.Ua_base = BASE_VOLTAGE_A;
bdcm_const.Ia_base = BASE_CURRENT_A;
bdcm_const.T_base=1;
bdcm_const.Ts = T;
bdcm_const.J=J_NOM;
bdcm_const.k_fi_nom = K_FI_NOM;
bdcm_const.calc(&bdcm_const);
/* Инициализируем константы */
bdcm.K1 = _IQ(bdcm_const.K1);
bdcm.K2 = _IQ(bdcm_const.K2);
bdcm.K3 = _IQ(bdcm_const.K3);
bdcm.K4 = _IQ(bdcm_const.K4);
bdcm.K5 = _IQ(bdcm_const.K5);
bdcm.Mc_pu = _IQ(0);
/* Инициализируем регулятор для контура тока якоря Ia */
pi_ia.Kp_reg3 = _IQ(0.567);
pi_ia.Ki_reg3 = _IQ(0.05);
pi_ia.Kd_reg3 = _IQ(0);
pi_ia.pid_out_max = _IQ(1);
pi_ia.pid_out_min = _IQ(-1);
/* Инициализируем регулятор для контура скорости */
pi_spd.Kp_reg3 = _IQ(10);
pi_spd.Ki_reg3 = _IQ(0.1);
pi_spd.Kd_reg3 = _IQ(0);
pi_spd.pid_out_max = _IQ(2);
pi_spd.pid_out_min = _IQ(-2);
// Пустой замкнутый цикл фоновой программы
for(;;);
}
226
Окончание лист 8.2
#define LEVEL3 3 /* прямой пуск двигателя */
#define LEVEL4 4 /* настройка регулятора тока ДПТ */
#define LEVEL5 5 /* настройка регулятора скорости */
#define LEVEL6 6 /* настройка регулятора скорости */
#define ALWAYS_RUN
/* Установка этапа проекта*/
#define BUILDLEVEL LEVEL5
#endif /* BUILDLEVEL */
Уровень LEVEL1
Код, выполняемый на первом этапе, содержит всего одну команду nop.
Самое важное, что хотим увидеть — это прерывание от таймера. В нем впо-
следствии будет считаться модель, а пока там только одна команда. Следует
обратить внимание на ее синтаксис. С помощью команды asm(« ») можно
поместить ассемблерную команду в код. В нашем случае это команда nop.
Для инициализации прерывания использовали стандартный объект
PWMGEN pwm и при инициализации записали в него значения
PWMGEN_DEFAULTS. Для настройки таймера и конфигурации прерывания
вызвали функцию инициализации pwm.init(&pwm), которая находится в
файле f28xpwm.c.
Уровень LEVEL2
Приступим к исследованию системы управления двигателя постоянного
тока, для описания которой выбраны базовые величины, позволяющие рас-
считывать модель двигателя в относительных единицах без использования
арифметики с плавающей точкой.
Скомпилируйте проект с использованием BUILD_LEVEL LEVEL2.
Установите точку останова, на процедуре подсчета модели (строка
bdcm.calc(&bdcm)) запустите программу в режиме ANIMATE.
На данном этапе протестируем работу контура возбуждения. В свойствах
верхнего графика, представленного на рис. 8.9, установите Start Address
229
&bdcm.i_e_pu — отображать ток в обмотке возбуждения. На вкладке окно
просмотра E_CONTROL измените U_e_ref (задание напряжения на обмотку
возбуждения) на 0,5 и увидите переходный процесс тока. Поэксперименти-
руйте с различными значениями.
Запустите программу в режиме ANIMATE. Остановите выполнение про-
граммы.
Рассмотрим, как реализован на языке Си контур возбуждения. Переход к
разностной форме описан в § 8.3. Здесь лишь коснемся особенностей про-
граммирования. В менеджере проекта выберите файл bdcm.c. В функции
bdcm_calc (BDCM *v) реализована модель ДПТ с НВ в относительных еди-
ницах. Найдите контур возбуждения. Это звено представляет собой инерци-
онный фильтр, математически полученный следующим образом:
Ik = K1Uk + K2I[k – 1].
На языке Си с использованием арифметики с «виртуальной» плавающей
точкой IQmath это выглядит так:
Лист. 8.7. Расчет тока возбуждения
v->i_e_pu=_IQmpy(v->K1,v->u_e_pu)+_IQmpy(v->K2,v-
>i_e_pu);
230
Лист. 8.9. Структура математической модели ДПТ
/* Файл bdcm.h */
typedef struct {
_iq u_e_pu; /* Вход: напряжение возбуждение (о.е) */
_iq u_a_pu; /* Вход: напряжение на якоре (о.е) */
_iq Mc_pu; /* Вход: момент сопротивления (о.е) */
_iq i_e_pu; /* Выход: ток обмотки возбуждения (о.е) */
_iq i_a_pu; /* Выход: ток якоря (о.е) */
_iq M_pu; /* Выход: момент (о.е) */
_iq W_pu; /* Выход: электрическая частота (о.е) */
_iq K1; /* Параметр: */
_iq K2; /* Параметр: */
_iq K3; /* Параметр: */
_iq K4; /* Параметр: */
_iq K5; /* Параметр: */
_iq Ts; /* Параметр: время дискретизации*/
void (*calc)(); /* Указатель на функцию счета*/
} BDCM;
/*---------------------------------------------------
Инициализация по умолчанию для обекта BDCM
---------------------------------------------------*/
#define BDCM_DEFAULTS { 0,0,0, \
0,0,0,0,0, \
0,0,0,0,\
(void (*)(long))bdcm_calc }
/*---------------------------------------------------
прототип функции в файле BDCM.C
---------------------------------------------------*/
void bdcm_calc(BDCM_handle);
Уровень LEVEL3
Запустим модель ДПТ напрямую включением на номинальное напряже-
ние. Для этого установим BUILD_LEVEL LEVEL3 и откомпилируем про-
грамму. Установите точку останова на строке bdcm.calc(&bdcm). Загрузите
программу и запустите ее, используя режим ANIMATE. Так как ожидаем
231
увидеть большой бросок момента, то установите значение maximum X value
на свойствах нижнего графика на 50 единиц (рис. 8.10).
На графике, приведенном на рис. 8.11, увидите зависимость момента от
скорости — это динамическая характеристика ДПТ. Поэкспериментируйте с
заданиями напряжения на обмотке якоря U_a_ref на вкладке A_CONTROL и
с напряжением обмотки возбуждения U_e_ref на вкладке E_CONTROL.
232
Изучите код на языке Си для модели ДПТ — файл bdcm.c. Использование
библиотеки IQmath существенно упрощает проведение математических опе-
раций. Полученный код мало отличается от кода для операций с плавающей
точкой. Для оценки ассемблерного кода используйте команду mixed mode\
source mode в контекстном меню. В смешанном режиме каждой строке Си
соответствует набор ассемблерных команд. Используя пошаговую отладку
(клавиша F8), можно последовательно выполнять ассемблерные команды.
Уровень LEVEL4
Для ограничения пускового тока и поддержания постоянного момента
введем контур тока якоря. Как известно, настройка контура тока может про-
изводиться при зафиксированном якоре. Для этого отключим обмотку воз-
буждения, подав на нее напряжение U_e_ref = 0.
Скомпилируем программу с уровнем LEVEL4. Установите точку останова
на строке bdcm.calc(&bdcm); и загрузите программу. В окне верхнего гра-
фика отобразите ток якоря bdcm.i_a_pu. Для этого измените start address на
&bdcm.i_a_pu. Изменяя задание тока Ia_ref на вкладке A_CONTROL, можно
наблюдать переходный процесс в контуре тока, представленный на рис. 8.12.
Перейдите на вкладку PID_IA_REG и проведите настройку регулятора
(рис. 8.13). В окне наблюдения нет возможности задавать переменные в фор-
233
Рис. 8.13. Настройка ПИ-регулятора контура тока
234
регулятор тока попадет в насыщение. Дальнейшее увеличение скорости тре-
бует ослабления поля. Измените напряжение на обмотке возбуждения
U_e_ref = 0,5 и наблюдайте процесс.
Уровень LEVEL5
Для обеспечения жесткости механической характеристики и регулирова-
ния момента введем контур скорости. ПИ-регулятор скорости располагается
на вкладке PID_SPD_REG. Настройте регулятор на технический оптимум.
Исследуйте режимы пуска, реверса, ослабления поля.
235
Глава 9
Система управления
(TMS320x2xxx)
tº
VD1 VD3 VD5 VD7
tº VT1 VT3 VT5
ДН
tº
ДТ ДТ
A B C
Rторм.
АД
ИДП
ТГ
236
Система управления реализуется на сигнальном микроконтроллере и
обеспечивает формирование ШИМ-сигналов управления шестью ключами
на базе многоканального ШИМ-генератора менеджера событий с высокой
несущей частотой — до 5—10 кГц. Обратные связи по току фазы A и B и
напряжению на звене постоянного тока (ЗПТ) реализуются с помощью дат-
чиков электрических величин (например, на элементах Холла компенсацион-
ного типа), выходные сигналы которых вводятся в контроллер через АЦП.
Ток в фазе С измерять не требуется, так как его можно вычислить по пер-
вому закону Кирхгофа из уравнения
ia + ib + ic = 0. (9.1)
Информация о скорости двигателя заводится с тахогенератора или с квад-
ратурного импульсного датчика положения ротора.
Все расчеты в системе управления должны выполняться за один период
ШИМ, который является интервалом дискретизации системы управления с
периодом TШИМ. Работоспособность системы управления в отсутствие
реального преобразователя частоты и двигателя будем отрабатывать на мате-
матической модели асинхронного двигателя, запущенной на этом же конт-
роллере. Математическая модель объекта управления (асинхронного двигателя
с короткозамкнутым ротором) будет иметь тот же самый интервал квантования.
239
u sα i sα R s dΨ sα ⎫
-------- = ------------- + --------------------, ⎪
Uб I б R б Ψ б ω б dt ⎪
⎪
u sβ i sβ R s dΨ sβ ⎪
-------- = ------------- + -------------------
-, ⎪
Uб I б R б Ψ б ω б dt ⎪
⎬ (9.16)
i rα R r dΨ rα Ψr β ω ⎪
0 = ------------- + -------------------- + -------------- , ⎪
I б R б Ψ б ω б dt Ψ б ω б ⎪
⎪
i rβ R r dΨ rβ Ψ rα ω ⎪
0 = ------------- + -------------------- – --------------- , ⎪
I б R б Ψ б ω б dt Ψ б ω б ⎭
а потом заменить переменные в физических единицах на переменные в отно-
сительных:
* ⎫
* * * 1 dΨ sα ⎪
u sα = i sα R s + ------ ------------- , ⎪
ω б dt
⎪
* ⎪
* * * 1 dΨ sβ ⎪
u sβ = i sβ R s + ------ ------------- , ⎪
ω б dt ⎪
⎬ (9.17)
* ⎪
* * 1 dΨ r α * *
0 = i rα R r + ------ ------------- + Ψ rβ ω , ⎪
ω б dt ⎪
⎪
* ⎪
* * 1 dΨ r β * * ⎪
0 = i rβ R r + ------ ------------- – Ψ rα ω . ⎪
ω б dt ⎭
В уравнениях (9.5) следует разделить обе части на базовое потокосцепле-
ние Ψб = LбIб, тогда уравнения можно записать в виде
Ψ sα L s i sα L m i rα ⎫
---------- = ------------- + -------------- , ⎪
Ψб Lб Iб Lб Iб ⎪
⎪
Ψ sβ L s i sβ L m i rβ ⎪
---------- = ------------ + -------------- , ⎪
Ψб Lб Iб Lб Iб ⎪
⎬ (9.18)
Ψ rα L r i rα L m i sα ⎪
---------- = ------------- + -------------- , ⎪
Ψб Lб Iб Lб Iб ⎪
⎪
Ψ rβ L r i rβ L m i sβ ⎪
---------- = ------------ + -------------- , ⎪
Ψб Lб Iб Lб Iб ⎭
где можно произвести замену переменных на относительные:
240
* * * * *
Ψ s α = L s i sα + L m i rα , ⎫
⎪
* * * * * ⎪
Ψ s β = L s i sβ + L m i rβ , ⎪
⎬ (9.19)
* * * * *
Ψ r α = L r i rα + L m i sα , ⎪
⎪
* * * * * ⎪
Ψ r β = L r i rβ + L m i sβ . ⎭
Уравнение момента:
M ⊥ Ψ s α i sβ – Ψ sβ i s α
-------- = ------------------------------------------ , (9.20)
Mб Ψб Iб
что даст:
* * * * *
M ⊥ = Ψ sα i sβ – Ψ sβ i sα . (9.21)
Уравнения механики (9.7) запишем через электрические величины. Для
этого сначала определим понятие базовой механической скорости, равной
скорости идеального холостого хода:
2πf ном
ω мех.б = ----------------- . (9.22)
pp
Электрическая и механическая скорости связаны выражением
ω = ppωмех. (9.23)
Если обе части разделить на б, то получится выражение:
ω ω мех
------ = p p ----------- , (9.24)
ωб ωб
ωб
а так как ω б.мех = ------ , то выражение упрощается до:
pp
* *
ω = ω мех , (9.25)
т.е. в относительных величинах электрическая скорость равна механической.
Это логично, так как 100 % номинальной электрической скорости всегда
будет соответствовать 100 % номинальной механической.
Преобразуем уравнение второго закона Ньютона, заменив все механичес-
кие величины электрическими:
dω мех
M мех = J --------------
-;
dt
3 1 dω
--- p p M ⊥ = J ----- ------- . (9.26)
2 p p dt
241
Полученное выражение можно записать так:
dω
M ⊥ = j ------- , (9.27)
dt
2J
где j = --- ----- — электрический момент инерции, т.е. момент инерции меха-
3 p2
p
низма, приведенный к электрической скорости двухфазной машины.
Если теперь заменить физические электрические момент и скорость на
момент и скорость в относительных единицах, получится выражение:
*
* dω
M ⊥ M б = jω б ---------- . (9.28)
dt
2
Разделив обе части уравнения на ω б , получим выражение
*
*M
M ⊥ ------б- = j ------
1 ---------
dω - , (9.29)
ωб
2 ω б dt
Mб
где ------- = J б — базовое значение электрического момента инерции, тогда
2
ωб
2
* 2J ω
j = --- ----- ------б- , (9.30)
3 p2 Mб
p
I
K1 = Ts α ; K2 = Ts ωδ ; K 3 = T s αL m -----δ- ;
ψ δ
ψ ψδ ωδ
K 4 = T s αβ -----δ- ; K 5 = T s β -------------
-; K6 = Ts γ ;
I δ I δ
Uδ Lm ψδ Iδ T
K9 = Ts B --- -----δ- .
K 10 = T s p
1 - ------
K 7 = T s -------- -; K8 = 3
--- p ------
- ----------- ; --- ;
σL s I δ 2 Lr Mδ J J ωδ
Ialpha
pu
Ibeta
pu
Ualpha
pu PsiAlpha
pu
Ubeta PsiBeta
pu ACI pu
LoadTorque Torque
pu pu
Wr
pu
WrRpm
Q0
244
Табл и ц а 9.1
Данные модуля ACI модели АД с короткозамкнутым ротором
Напряжение статора:
*
по оси α u sα Ualpha
*
по оси β u sβ Ubeta
*
Момент нагрузки (сопротивление) Mc LoadTorque
Ток статора:
*
по оси α i sα Ialpha
*
по оси β i sβ Ibeta
Потокосцепление ротора:
*
по оси α Ψ rα PsiAlpha
*
по оси β Ψ rβ PsiBeta
*
Момент двигателя M⊥ Torque
*
Скорость ротора двигателя ω Wr
Скалярное управление
Уравнение электрического равновесия для одной фазы можно записать
следующим образом:
dΨ sα
u sα = i sα R s + ------------- .
dt
Если пренебречь падением напряжения на активном сопротивлении фазы
статора, то потокосцепление изменяется по синусоидальному закону:
U max
Ψ sα = – ------------ cos ω 0эл t .
ω 0эл
246
Из полученного выражения видно, что амплитуда потокосцепления фазы
прямо пропорциональна напряжению и обратно пропорциональна частоте,
поэтому для поддержания постоянства потока требуется изменять напряже-
ние пропорционально частоте. Такой закон регулирования напряжения в
функции частоты называют U/f = const.
При уменьшении скорости доля iR-составляющей увеличивается по отноше-
нию к прикладываемому напряжению, что приводит к существенному уменьше-
нию потока на малых частотах и соответственно уменьшению момента. Для
обеспечения перегрузочной способности по моменту, близкой к номинальной во
всем диапазоне скоростей, применяют iR-компенсацию, при которой имеет
место завышение напряжения относительно закона U/f = const (рис. 9.3, а).
В области малых частот напряжение питания увеличивают по сравнению
с линейным законом. В области высоких частот напряжение питания доходит
до номинального значения. Увеличивать его больше номинального нельзя,
так как на этот уровень напряжения рассчитывается изоляция двигателя.
Преобразователи частоты со скалярным управлением дают возможность
обслуживающему персоналу задавать параметры закона изменения напряже-
ния в функции частоты: определять значения начального и конечного напря-
жения, наклон и прогиб кривой напряжения, а возможно и задание кривой по
точкам (рис. 9.3, б и в).
Настройка кривой напряжения в функции частоты производится для кон-
кретного вида нагрузки, с изменением вида нагрузки режим работы двига-
теля может оказаться далеким до оптимального — может произойти насы-
щение магнитной цепи, критический момент оказаться недостаточным для
преодоления момента нагрузки или произойти повышение потерь в резуль-
тате увеличившегося скольжения. Многие преобразователи поддерживают
функции автоматической перенастройки кривой напряжения от частоты,
адаптируя закон для конкретной нагрузки. В зависимости от момента на валу
двигателя они изменяют напряжение двигателя в целях обеспечения требуе-
мой перегрузочной способности, а также могут изменять частоту напряже-
ния статора для обеспечения более жестких механических характеристик
двигателя. Такое управление называется «с компенсацией скольжения». При
быстро меняющихся факторах скалярное управление не обеспечивает требу-
емого качества регулирования. В этих случаях применяют системы вектор-
ного управления и системы прямого управления моментом.
U U U
Uном Uном Un
U2
U U1
= const Umin
f
fном f fном f f1 f2 fn f
а) б) в)
247
Векторное управление
В развитии теории векторного управления большую роль сыграла разра-
ботка фирмой Siemens системы «Трансвектор». Эта система построена на
прямом измерении вектора потока в воздушном зазоре датчиками Холла. С
помощью математических преобразований, используя измеренный поток и
токи статора, вычисляют потокосцепление ротора и его угловое положение.
Контроль тока статора ведется по двум составляющим, одна из которых
задает потокосцепление, а другая — момент.
Для описания асинхронного двигателя используются уравнения в ортого-
нальной системе координат x, y, вращающихся со скоростью ωk:
dΨ sx ⎫
u s x = i sx R s + ------------- – ω k Ψ sy , ⎪
dt ⎪
dΨ sy ⎪
u s y = i sy R s + ------------- + ω k Ψ sx , ⎪
dt ⎪
⎪
dΨ r x ⎪
0 = i r x R r + ------------- – ( ω k – ω )Ψ ry , ⎬ (9.36)
dt ⎪
dΨ r y ⎪
0 = i r x R r + ------------- + ( ω k – ω )Ψ r x , ⎪
dt ⎪
⎪
Lm ⎪
M ⊥ = ------- ( Ψ rx i sy – Ψ ry i s x ), ⎪
Lr ⎭
где ωk и ω — электрические скорости вращения координатной системы x, y и
ротора двигателя.
Координаты x, y следует расположить так, чтобы ось x была сонаправлена
с вектором потокосцепления ротора (при этом Ψry = 0), а регулирование сле-
дует производить при Ψr = const, тогда уравнения роторной цепи упростятся:
0 = ir x Rr , ⎫
⎬ (9.37)
0 = i r y R r + ( ω k – ω )Ψ rx . ⎭
Для анализа полученного результата следует записать выражения пото-
косцеплений ротора асинхронного двигателя:
Ψ r x = L r i rx + L m i sx , ⎫
⎬ (9.38)
Ψ r y = L r i ry + L m i sy . ⎭
Согласно (9.37) irx = 0, при этом с учетом Ψry = 0 выражения (9.38) упро-
щаются:
Ψr x = Lm is x , ⎫
⎪
Lm ⎬ (9.39)
i ry = – ------- i sy . ⎪
Lr ⎭
248
Ток статора по оси x однозначно определяет потокосцепление. Тогда урав-
нение момента двигателя при Ψry = 0 примет вид
Lm
-Ψ i .
M = ------ (9.40)
L r rx s y
Сформулируем основной принцип векторного управления: с помощью
тока статора по оси x необходимо установить поле ротора, а по оси y зада-
вать ток, определяющий момент, развиваемый двигателем. Результирующая
структура СВУ показана на рис. 9.4.
Структурная схема содержит регуляторы потокосцепления, момента (тока
статора по оси y) и тока статора по оси x; блок координатных преобразова-
ний из x, y, связанных с потокосцеплением ротора, в неподвижные коорди-
наты α, β, связанные со статором; инвертор, работающий с заданиями напря-
жений в координатах α, β; АД; измерительную систему; наблюдатель,
который по измеренным значениям электрических, механических и терми-
ческих величин производит вычисление амплитуды Ψ r и положения θ Ψ
r
потокосцепления ротора АД; блоки координатных и фазных преобразований.
Блок фазных преобразований позволяет по измеренным токам двух фаз
определить токи двухфазной эквивалентной машины в стационарных коор-
динатах α, β. Блоки координатных преобразований осуществляют перерас-
чет ортогональных составляющих вектора тока из одних координатных осей
в другие.
В рамках данной лабораторной будет исследоваться упрощенная струк-
тура, изображенная на рис. 9.5, из которой будет исключен регулятор потока,
а регулятор момента представлен регулятором тока по оси y.
249
зад
зад
зад
зад
250
Рис. 9.6. Структура наблюдателя потокосцепления ротора в датчиковой системе векторного
управления
Контрольные вопросы
252
9.5. ИССЛЕДОВАНИЕ МОДЕЛИ АСИНХРОННОГО ДВИГАТЕЛЯ
В РЕЖИМЕ СКАЛЯРНОГО УПРАВЛЕНИЯ
Предложенная для исследования программа содержит флаг разрешения
работы системы — EnableFlag. Пока этот флаг не будет установлен, про-
грамма не сможет преодолеть приведенный в лист. 9.2 участок кода. Для
запуска расчета системы необходимо установить значение EnableFlag=1,
что можно сделать, используя окно «watch window».
UdRef Ds
Ibeta
SpeedRef I_PARK
Alpha Ualpha ACI
RAMPGEN
UqRef Qs Ialpha
Beta Ubeta
Angle PsiBeta
LoadTorque
PsiAlpha
Wr
Torque
253
Для реализации данного закона управления используется модуль vhzprof
Freq VoltOut
VHz_PROF
Ds Alpha
I_PARK
Qs
Angle Beta
Gain
RAMP_
Offset GEN
Out
Freq
Контрольные вопросы
1. Объясните увеличение тока при смене задания скорости.
2. Объясните работу осциллографа. Почему график момента содержит не все расчет-
ные точки?
3. Как, используя данные осциллографа, построить механическую характеристику?
258
SpeedRef IdRef Ref
Fdb PID_REG3 Out Ds
I_PARK Ibeta
Alpha Ualpha ACI
Wr
Torque
IDs CUR_
MOD
IQs Theta
Wr
Angle
Ds PARK
Alpha
Qs
Beta
Практическая работа
260
Лист. 9.5. Пример части программы второго уровня построения проекта
if (EnableFlag!=EnableFlag_prev)
{
dlog.graph_ptr1=(type_data *)dlog.dl_buffer1_adr;
dlog.graph_ptr2=(type_data *)dlog.dl_buffer2_adr;
dlog.graph_ptr3=(type_data *)dlog.dl_buffer3_adr;
dlog.graph_ptr4=(type_data *)dlog.dl_buffer4_adr;
}
if (EnableFlag==0)
{
pid1_id.Ui=0;
pid1_iq.Ui=0;
aci1.Ualpha = 0;
aci1.Ubeta = 0;
}
else
{
aci1.Ualpha = ipark1.Alpha;
aci1.Ubeta = ipark1.Beta;
}
Контрольные вопросы
1. Настройте регуляторы на технический оптимум.
2. Исследуйте работу системы, задавая различные значения скорости. Для этого
переведите режим осциллографа в «продолжительный» и в режиме реального времени
наблюдайте изменения тока, скорости, момента. Постройте механическую характерис-
тику получившейся системы, подобную изображенной на рис. 9.14.
261
9.7. МОДУЛЬ ОПРЕДЕЛЕНИЯ ПОЛОЖЕНИЯ
ВЕКТОРА ПОТОКОСЦЕПЛЕНИЯ РОТОРА
IQs
pu
IDs Theta
pu CUR_MOD pu
Wr
pu
Контрольные вопросы
1. Изучите код программы. Определите, на каких графиках отображаются ток ста-
тора, угол положения вектора потокосцепления ротора, скорость двигателя и момент.
2. Получите механическую характеристику системы при различных токах d и q.
3. Исследуйте поведение регуляторов тока в зависимости от скорости.
Контрольные вопросы
1. Измените настройки регулятора скорости так, чтобы переходный процесс по ско-
рости стал колебательным, а затем попытайтесь настроить регулятор на технический
оптимум.
2. Постройте механическую характеристику исследуемой системы векторного управ-
ления АД.
264
Задания для самостоятельного изучения
1. Изучите механическую характеристику системы векторного управле-
ния. Как по нескольким точкам, для нескольких заданий тока d и q построить
граничную и предельную характеристики двигателя?
2. Предложите альтернативные способы расчета положения вектора пото-
косцепления ротора, например в стационарных осях.
3. Подумайте, как должна быть устроена система векторного управления
для реализации бездатчикового варианта?
265
БИБЛИОГРАФИЧЕСКИЙ СПИСОК
266
ОГЛАВЛЕНИЕ
Предисловие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
267
Глава 4. Базовые возможности языка программирования Си . . . . . . . . . . . . . . . . . . . . 97
4.1. Операторы ветвления. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
4.2. Операторы организации циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.3. Работа с указателями . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.4. Указатели и массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.5. Функции в языке Си . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
268
Глава 9. Исследование системы векторного управления асинхронным двигателем . 236
9.1. Структура аппаратной части системы ПЧ—АД . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
9.2. Математическая модель асинхронного двигателя . . . . . . . . . . . . . . . . . . . . . . . . . . 237
9.3. Принципы частотного регулирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
9.4. Структура проекта. Рабочая область проекта . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
9.5. Исследование модели асинхронного двигателя в режиме скалярного управления 253
9.6. Исследование частотно-токовой системы управления асинхронного двигателя.
Настройка ПИ-регулятора тока. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
9.7. Модель определения положения вектора потокосцепления ротора . . . . . . . . . . . . 262
9.8. Интеграция ПИ-регулятора скорости. Исследование системы векторного
управления асинхронным двигателем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
269
Учебное издание
ВСТРАИВАЕМЫЕ ВЫСОКОПРОИЗВОДИТЕЛЬНЫЕ
ЦИФРОВЫЕ СИСТЕМЫ УПРАВЛЕНИЯ
Практический курс разработки и отладки программного обеспечения
сигнальных микроконтроллеров TMS320x28xxx
в интегрированной среде Code Composer Studio
Учебное пособие
по курсу
«Микропроцессорные системы управления»
для студентов, обучающихся по направлениям «Электротехника, электромеханика
и электротехнологии», «Промышленная электроника», «Роботы и манипуляторы», для слушателей
курсов повышения квалификации специалистов промышленности и преподавателей вузов