Лабораторная работа № 4.
Изучение микроконтроллера MSP430. Обработка прерываний и измерения неэлектрических величин
Цель работы
Изучение основных характеристик и архитектуры микроконтроллера MSP430. Изучение основных приемов программирования микроконтроллера MSP430 для измерения неэлектрических величин с помощью функций обработки внешних прерываний, измерения температуры и временных интервалов.
Задачи
Создание программ управления цифровыми и аналоговыми линиями порта ввода-вывода для отладочного модуля MSP430 LaunchPad с помощью среды программирования Energia. Прошивка микроконтроллера и проверка работы программ.
Теоретическая часть
3.1. Обработка прерываний
В микроконтроллерах MSP430 имеется три типа прерываний:
- сброс системы; немаскируемые (NMI); маскируемые.
Приоритеты прерываний фиксированы и зависят от местонахождения конкретного модуля в цепочке, как показано на рис. 4.1. Чем ближе расположен модуль к ЦПУ, тем выше приоритет его прерывания. Приоритеты определяют порядок обработки прерываний при одновременной генерации нескольких запросов.

Рис. 4.1. Приоритеты прерываний
Немаскируемые прерывания (NMI)
Немаскируемые прерывания NMI не маскируются битом общего разрешения прерываний (GIE), однако могут быть по отдельности разрешены/запрещены при помощи индивидуальных битов разрешения прерывания (NMIE, ACCVIE, OFIE). При возникновении немаскируемого прерывания все биты разрешения этого прерывания автоматически сбрасываются. Выполнение программы продолжается с адреса, содержащегося в векторе немаскируемого прерывания, 0FFFCh. Для повторного разрешения прерывания пользовательская программа должна снова установить требуемые биты.
Немаскируемое прерывание может быть вызвано тремя событиями:
- появление активного фронта на выводе RST/NMI при конфигурации последнего в режиме NMI; возникновение неисправности тактового генератора; нарушение доступа к флэш-памяти.
Вывод RST/NMI
При включении микроконтроллера вывод RST/NMI конфигурируется как вход аппаратного сброса. Назначение этого вывода задаётся в регистре управления сторожевого таймера WDTCTL. Если вывод RST/NMI используется в качестве входа сброса, то ЦПУ будет удерживаться в состоянии сброса до тех пор, пока на этом выводе будет присутствовать сигнал НИЗКОГО уровня. При подаче на вход сигнала ВЫСОКОГО уровня ЦПУ начинает выполнять программу с адреса, хранящегося в векторе сброса (0FFFEh). Одновременно с этим устанавливается флаг RSTIF.
Если вывод RST/NMI сконфигурирован в программе как вход немаскируемого прерывания, то появление на этом выводе активного фронта (задаётся битом WDTNMIES) при установленном бите NMIIE вызывает генерацию немаскируемого прерывания. Также устанавливается флаг NMIIFG.
Нарушение доступа к флэш-памяти
При нарушении доступа к флэш-памяти устанавливается флаг ACCVIFG. Генерация немаскируемого прерывания при возникновении такой ситуации разрешается установкой бита ACCVIE. В процедуре обработки немаскируемого прерывания можно проверить флаг ACCVIFG, чтобы определить, было ли прерывание вызвано именно нарушением доступа к флэш-памяти.
Неисправность тактового генератора
Сигнал неисправности генератора позволяет предотвратить ошибки, связанные с неправильным функционированием кварцевого генератора. Генерация немаскируемого прерывания при обнаружении неисправности генератора разрешается установкой бита OFIE. В процедуре обработки немаскируемого прерывания можно проверить флаг OFIFG, чтобы определить, было ли прерывание вызвано именно сбоем в работе генератора.
Маскируемые прерывания
Маскируемые прерывания генерируются периферийными устройствами, имеющими такую возможность. В том числе, маскируемое прерывание может генерироваться по переполнению сторожевого таймера при работе последнего в режиме интервального таймера. Прерывания от каждого из источников могут быть
запрещены с помощью индивидуальных битов разрешения прерываний. Кроме того, все маскируемые прерывания могут быть запрещены с помощью бита общего разрешения прерываний GIE регистра состояния (SR).
Обработка прерывания
При возникновении запроса прерывания от периферийного устройства, если установлены бит разрешения прерывания от этого устройства и бит общего разрешения прерываний GIE, вызывается процедура обработки прерывания. Для вызова обработчика немаскируемого прерывания достаточно установленного индивидуального бита разрешения конкретного прерывания.
Принятие запроса прерывания
Задержка обработки прерывания, т. е. время с момента принятия запроса прерывания до начала выполнения первой команды процедуры обработки прерывания (рис. 4.2), составляет 5 (MSP430X) или 6 (MSP430) тактов ЦПУ.

Рис. 4.2. Обработка запроса на прерывание
Обработка запроса на прерывание производится в следующей последовательности:
1. Ожидается завершение команды, исполняемой в данный момент.
2. Содержимое счётчика команд PC, указывающего на следующую команду, помещается в стек.
3. Содержимое регистра состояния SR помещается в стек.
4. Если за время выполнения последней команды было сформировано несколько
запросов на прерывание, то выбирается прерывание с наибольшим приоритетом.
5. Если прерывание имеет один источник, то флаг прерывания автоматически сбрасывается. Если прерывание может генерироваться несколькими источниками, то флаги прерывания остаются установленными для последующей обработки в программе.
6. Регистр состояния SR очищается. В результате процессор переходит из режима пониженного потребления в активный режим. Поскольку бит GIE сбрасывается, последующие прерывания запрещаются.
7. Содержимое вектора прерывания загружается в счётчик команд PC и начинается выполнение процедуры обработки прерывания, расположенной по этому адресу.
Возврат из прерывания
Процедура обработки прерывания всегда завершается командой: RETI (возврат из процедуры обработки прерывания).
Для возврата из прерывания требуется 5 (MSP430) или 3 (MSP430X) такта ЦПУ, необходимых для выполнения следующих действий (рис. 4.3):
1. Восстановление содержимого регистра SR из стека. В результате вступают в действие все предыдущие установки битов GIE, CPUOFF и пр., независимо от их установок, использовавшихся в процедуре обработки прерывания.
2. Содержимое счётчика команд PC извлекается из стека, и выполнение программы продолжается с того места, где она была прервана.

Рис. 4.3. Возврат из прерывания.
Вложенные прерывания
Вложенные прерывания разрешаются установкой бита GIE в процедуре обработки прерывания. При этом любое прерывание, возникшее во время выполнения процедуры обработки прерывания, прервёт её выполнение, независимо от приоритетов обслуживаемого и нового прерываний.
Векторы прерываний
Векторы прерываний и вектор сброса располагаются в диапазоне адресов 0FFFh…0FFC0h, как показано в табл. 4.1.
Таблица 4.1. Источники, флаги и векторы прерываний
Источник прерывания | Флаг прерывания | Системное прерывание | Адрес | Приоритет |
Включение питания, внешний сброс, сторожевой таймер, пароль флэш-памяти, выборка команды по некорректному адресу | PORIFG RSTIFG WDTIFG KEYV | Сброс | 0FFFEh | 31, высший |
NMI_прерывание, неисправность генератора, нарушение доступа к флэш-памяти | NMIIFG | Немаскируемое | 0FFFCh | 30 |
OFIFG | Немаскируемое | |||
ACCVIFG | Немаскируемое | |||
Определяется устройством | 0FFFAh | 29 | ||
Определяется устройством | 0FFF8h | 28 | ||
Определяется устройством | 0FFF6h | 27 | ||
Сторожевой таймер | WDTIFG | Маскируемое | 0FFF4h | 26 |
Определяется устройством | 0FFF2h | 25 | ||
Определяется устройством | 0FFC0h | 0, низший |
Каждый вектор программируется пользователем посредством записи в него 16-битного адреса соответствующей процедуры обработки прерывания. Полный перечень векторов прерывания приводится в справочной документации на конкретные модели микроконтроллеров.
Рекомендуется предусматривать процедуры обработки прерываний для всех прерываний, реализованных в конкретном микроконтроллере. При этом все неиспользуемые в программе вектора могут указывать на пустой обработчик прерывания, содержащий единственную команду RETI.
Незадействованные вектора прерываний при необходимости можно использовать для размещения программного кода.
Некоторые биты включения периферийных модулей, биты разрешения прерываний и флаги прерываний находятся в регистрах специальных функций (SFR). Эти регистры являются 8-битными и располагаются в младших адресах адресного пространства. Обращаться к регистрам специальных функций необходимо с помощью команд, работающих с однобайтными операндами. Конфигурация области SFR приводится в справочной документации на конкретные модели микроконтроллеров.
Порты P1 и P2 поддерживают внешние прерывания. Для каждого из выводов портов P1 и P2 можно индивидуально разрешить прерывание и сконфигурировать его так, чтобы оно генерировалось по нарастающему или спадающему фронту входного сигнала. Все линии ввода/вывода порта P1 назначены одному вектору прерываний, а все линии порта P2 — другому вектору.
3.2. Функции языка Arduino для работы с прерываниями и измерениями временных интервалов
Функция attachInterrupt(interrupt, function, mode)
Описание:
Определяет функцию, которая будет вызвана при срабатывании внешнего прерывания. Заменяет привязанную ранее функцию. Большинство платформ имеют два внешних прерывания: с номерами 0 (на цифровом входе 2 – P1_2, вывод 4) и 1(на цифровом входе 3 – P1_3, вывод 5, PUSH2).
Параметры:
interrupt: номер прерывания (тип int);
function: функция, вызываемся при срабатывании прерывания. Следует учесть, что функция не должна иметь параметров и ничего не возвращать. Такая функция называется обработчиком прерывания.
mode: определяет, на что должно срабатывать прерывание. Четыре константы устанавливают определеное действие:
- LOW: срабатывание прерывания, когда на цифровом входе присутствует низкий уровень напряжения, CHANGE: срабатывание прерывания каждый раз при изменении уровня напряжения на цифровом входе; RISING: срабатывание прерывания по фронту - когда состояние цифрового входа вывода изменяется от LOW к HIGH; FALLING: срабатывание прерывания по спаду - когда состояние цифрового входа изменяется от HIGH к LOW.
Примечание:
Внутри функций обработки прерывания функция delay() не работает, и значение, возвращаемое функцией millis(), не инкрементируется. Передаваемые по последовательному порту данные могут быть потеряны. Следует объявить как volatile любые перемены, модифицируемые в обработчике прерывания.
Использование прерываний:
Прерывания отлично подходят для создания автоматических действий в программах и могут решать некоторые временные проблемы.
Показательной задачей с использованием прерываний является программа управления объектом с энкодером. Нужно быть уверенным, что ни один импульс от энкодера не будет потерян, однако сложно написать программу, выполняющую кроме слежения что-то еще. Подключив выход энкодера на внешнее прерывание, можно с легкостью решить эту проблему.
Пример:
volatile int state = HIGH;
volatile int flag = HIGH;
int count = 0;
void setup()
{
Serial. begin(9600);
pinMode(GREEN_LED, OUTPUT);
digitalWrite(GREEN_LED, state);
pinMode(PUSH2, INPUT_PULLUP);
attachInterrupt(PUSH2, blink, FALLING); // Прерывание вызывается, когда
// происходит нажатие кнопки PUSH2
}
void loop()
{
digitalWrite(GREEN_LED, state); //Светодиод устанавливается в состояние state
if(flag) {
count++; // инкремент количества прерываний
Serial. println(count); // вывод количества прерываний в COM-порт
flag = LOW;
}
}
void blink() // процедура обработки прерывания
{
state = !state;
flag = HIGH;
}
Функция detachInterrupt(interrupt)
Описание:
Выключает объявленное ранее прерывание.
Параметры
interrupt: номер отключаемого прерывания (0 или 1).
Функция noInterrupts()
Описание:
Деактивирует прерывания.
Прерывания можно после снова активировать функцией interrupts(). Прерывания обычно решают важные задачи, и по умолчанию активированы. Однако, некоторые функции не могут работать, пока прерывания активированы, и входные данные могут быть проигнорированы. Прерывания могут повлиять на время-зависимые функции, вы можете деактивировать прерывания при выполнении критически важных функций.
Функция interrupts()
Описание:
реактивирует прерывание (после того, как оно было деактивировано функцией noInterrupts()).
Пример:
void setup() {}
void loop()
{
noInterrupts();
// здесь записывается код для критических, время-зависимых операций
interrupts();
// здесь записывается другой код
}
Функция pulseIn().
Описание:
Измеряет длительность импульса (HIGH или LOW). Например, если HIGH, то pulseIn() будет ждать, когда на входе будет значение HIGH, запустит счет, после чего будет ждать, когда на входе установится значение LOW и выключит отсчет времени. Возвращает: длительность импульса в микросекундах или 0, если за определенное время ни одного импульса не пришло.
Функция нормально работает при длительности импульса от 10 микросекунд до 3 минут.
Синтаксис:
pulseIn(pin, value) или
pulseIn(pin, value, timeout)
Параметры:
pin: номер вывода микроконтроллера, на котором мы хотим измерить длительность импульса (тип int);
value: тип измеряемого импульса - HIGH или LOW (тип int);
timeout (опционально): число микросекунд ожидания импульса (по умолчанию 1 минута). Тип unsigned long.
Пример:
int pin = 7; // номер вывода, на котором ожидается импульс
unsigned long duration; // переменная для приема значения длительности
void setup()
{
pinMode(pin, INPUT); // вывод pin настраивается на цифровой ввод
}
void loop()
{
duration = pulseIn(pin, HIGH); // вызов функции для измерения длительности
}
3.3. Встроенный датчик температуры
Некоторые модели микроконтроллеров MSP430 имеют встроенный датчик температуры. К их числу относятся и микроконтроллеры, поставляемые в комплекте с отладочной платой LaunchPad EXP-430G2: MSP430G2452 и MSP430G2553. Последний микроконтроллер (MSP430G2553), поставляемый в комплекте с LaunchPad, имеет прошивку демонстрационной программы измерения температуры. Поскольку датчик температуры – встроенный, измеряется температура корпуса микроконтроллера. Программа работает следующим образом:
- при подаче питания на плату начинают мигать светодиоды; если нажать кнопку на линии порта P1.3 (PUSH2), то температура начинает считываться, первый результат после нажатия запоминается как эталонный и в сэмулированный асинхронный приемо-передатчик (COM-порт) передается значение 248 для индикации нажатия; текущее значение температуры, выраженное в градусах Фаренгейта, выдается в COM-порт; если текущая измеренная температура больше эталонного значения — повышается яркость свечения красного светодиода, если меньше — зеленого.
Датчик температуры для измерений подключается ко входу аналого-цифрового преобразователя (АЦП). Для этого используется фиксированный аналоговый вход АЦП с номером INCHx = 10102. При конфигурировании АЦП на измерение температуры нужно установить величину опорного напряжения.
Типичная передаточная характеристика датчика температуры приведена на рис. 4.4. При использовании датчика температуры время выборки должно быть не менее 30 мкс. Этот датчик имеет большую погрешность смещения и для получения абсолютных значений температуры требует калибровки.

Рис. 4.4. Типичная передаточная характеристика встроенного датчика температуры: TA – температура, V – выходное напряжение датчика.
Для работы с датчиком температуры используются следующие функции языка Arduino.
Функция analogReference(type).
Описание: Устанавливает опорное напряжение для аналоговых входов. Функция analogRead() вернет 1023 для входного уровня, равного опорному напряжению или превышающего его.
Параметры:
type: тип используемого опорного напряжения (DEFAULT, INTERNAL1V5, INTERNAL2V5 или EXTERNAL). Они означают:
- DEFAULT: значение опорного напряжения по умолчанию – величина напряжения питания микроконтроллера (VCC) ~ 3.3В … 3.6В; INTERNAL1V5: внутреннее опорное напряжение (от внутреннего источника опорного напряжения ИОН) величиной 1.5В; INTERNAL2V5: внутреннее опорное напряжение величиной 2.5В; EXTERNAL: внешнее опорное напряжение от источника, подключенного к выводу VREF платы.
Функция analogRead().
Описание: Читает входное значение с определенного аналогового вывода.
Синтаксис:
analogRead(pin);
Параметры:
pin: номер аналогового входа, который следует прочесть (от A0 до A7 на большинстве платформ). Если в качестве параметра указать символическое имя TEMPSENSOR, то будет прочитано значение со встроенного датчика температуры.
Возвращает:
int (0 … 1023) – целое число, представляющее собой выходной код АЦП.
Пример:
int val = 0; // переменная для сохранения прочитанного значения
void setup()
{
Serial. begin(9600); // настройка COM-порта
}
void loop()
{
val = analogRead(TEMPSENSOR); // чтение датчика температуры
Serial. println(val); // передача значения через COM-порт
Delay(100); // задержка 100 миллисекунд
}
Полученное от функции analogRead(TEMPSENSOR) целое значение [0..1023] нужно преобразовать в действительное значение температуры [0C]. Зависимость напряжения на выходе температурного датчика от температуры задается формулой:
V = 0.00355 * TA + 0.986. (4.1)
Из нее можно получить формулу для преобразования напряжения в температуру:
TA = V / 0.00355 - 277.75. (4.2)
Если опорное напряжение АЦП Vref ≠ 0, то преобразование входного напряжения АЦП V в его выходной код A подчиняется зависимости:
A = 1023 * V / Vref. (4.3)
При величине опорного напряжения Vref = 1.5В получим:
V = A * 0.0014663. (4.4)
Подставим это выражение в формулу для температуры (4.2) и получим:
TA = A * 0.413 - 277.75. (4.5)
По этой формуле целое значение кода A преобразуется в действительное значение температуры TA, которое нужно представлять переменной в форме с плавающей запятой. Однако операции с плавающей точкой в микроконтроллере выполняются медленно и требуют значительной памяти, поэтому лучше выполнить преобразование значений к целому типу с последующим выделением отдельно целой части и дробной части требуемого результата. Такое преобразование можно выполнить умножением и делением правой части (4.5) на 65536 (216). В результате:
TA = (A * 27069 - 18202393) / 65536. (4.6)
При вычислениях в программе деление на 65536 эквивалентно сдвигу числа на 16 разрядов вправо, поэтому формула (4.6) для записи на языке Arduino приобретает вид:
TA = (A * 27069 - 18202393) >> 16. (4.7)
Для округления результата к выражению в скобках следует добавить 0.5 * 65536. Получим:
TA = (A * 27069 - 18202393 + 32768) >> 16. (4.8)
Тогда
TA[0C] = (A * 27069 - 18169625) >> 16. (4.9)
Для преобразования выходного кода АЦП в температуру в градусах Кельвина и в градусах Фаренгейта можно пользоваться аналогичными формулами:
TA[0K] = (A * 27069 - 268467) >> 16, (4.10)
TA[0F] = (A * 48724 - 30634388) >> 16. (4.11)
Пример программы, которая измеряет температуру и выдает на каждое измерение два значения: измеренное и усредненное по последним 4 измерениям.
#define NUMBER 4 // константа – размер массива
int ledState = HIGH; // статус светодиодов
uint8_t i = 0; // целочисленная переменная, представленная без знака в 1 байте
uint32_t average = 0; // беззнаковое целое в 4 байтах – накопленная сумма,
// среднее значение
uint32_t values[NUMBER]; // массив измеренных значений
uint8_t j = 0; // счетчик элементов массива
boolean flag = false; // признак необходимости печатать среднее значение
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
analogReference(INTERNAL1V5); // величина опорного напряжения 1.5В
analogRead(TEMPSENSOR); // первое чтение датчика обычно с ошибкой
Serial. begin(9600);
pinMode(PUSH2, INPUT_PULLUP);
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
Serial. print("\n\n\n*** MSP430 Thermometer \n");
Serial. print("Press PUSH2 to end\n");
Serial. print("instant\taverage\n"); // 1 колонка – измерение, 2 колонка – ср. значение
for (j=0; j<NUMBER; j++) values[j]=0; // обнуление элементов массива
average = 0; // обнуление суммы
j=0;
}
// процедура печати целого числа как десятичного с 1 десятичным разрядом
void printDec(uint32_t ui) { // ui умножено на 10
Serial. print(ui/10, DEC); // целая часть
Serial. print(".");
Serial. print(ui%10, DEC); // дробная часть – остаток от деления на 10
}
void loop() {
ledState = !ledState; // инверсия статуса светодиодов
// LEDs: green = готовность; red = измерение
digitalWrite(flag? GREEN_LED : RED_LED, ledState);
// если flag == true, то GREEN_LED устанавливается в состояние RED_LED,
// иначе в состояние ledState
if (i == 10) { // 9 тактов измерений по 100 мс пропускаются, измерение через 1 с
i = 0;
// формула для расчета результата измерения и накопление суммы
average -= values[j]; // вычесть из суммы предыдущее значение
values[j] = ((uint32_t)analogRead(TEMPSENSOR)*27069 - 18169625) *10 >> 16;
average += values[j]; // сложить с суммой новое значением
// Печать измерения
printDec(values[j]);
Serial. print("\t");
// печать среднего значения
if (flag) printDec(average/NUMBER);
Serial. print("\n");
j++; // инкремент индекса массива
if (j==NUMBER) flag=true; // когда массив 4 измерений заполнен, можно печатать // средние значения
j %= NUMBER; // j принимает значение остатка от деления на 4
}
// проверка кнопки и прекращение измерений
if (digitalRead(PUSH2)==LOW) {
Serial. print("\n\n*** End \n");
Serial. end();
while(true); // бесконечный цикл
}
delay(100); // задержка 100 мс – длительность такта
i++; // инкремент счетчика тактов
}
3.4. Дистанционное измерение расстояния ультразвуковым датчиком
Дистанционные (бесконтактные) датчики для измерения расстояния могут использовать различные принципы измерений: индуктивный, ультразвуковой или оптический. Все они имеют электрический выходной сигнал, величина которого пропорциональна расстоянию до измеряемого объекта.
Принцип действия ультразвуковых датчиков расстояния основан на излучении импульсов ультразвука и измерении времени, пока звуковой импульс, отразившись от объекта измерения, вернется обратно в датчик. При этом достигается разрешение измерения расстояния до 0,2 мм. Наиболее важными особенностями применений ультразвуковых датчиков служит их возможность измерять расстояния до таких сложных объектов таких как, например, сыпучие вещества, жидкости, гранулы, прозрачные или напротив сильно отражающие поверхности. В дополнение ультразвуковыми датчиками можно измерять сравнительно большие расстояния, при этом сохраняя их небольшие размеры, что может быть существенно для ряда применений.
Однако ультразвуковые датчики имеют ряд ограничений. Прежде всего, это пена и другие объекты, сильно поглощающие ультразвуковые колебания. Такое поглощение сильно уменьшает измеряемую дистанцию. Сильно изогнутые поверхности так же снижают расстояние и точность измерений, поскольку рассеивают ультразвуковые колебания в различных направлениях. Ультразвуковые датчики излучают импульс в виде широкого конуса, что ограничивает возможность измерения расстояния до небольших объектов, увеличивая уровень помех от других объектов, которые так же могут находиться в поле зрения датчика. Некоторые ультразвуковые датчики имеют конус с углом всего 5 градусов. Это позволяет использовать их для распознавания или измерения расстояния до небольших объектов.
Пример ультразвукового дальномера – устройство HC-SR04 (рис. 4.5).

Рис. 4.5. Ультразвуковой дальномер HC-SR04
Сенсор дальномера работает по принципу эхолокации (сонара) —пьезоэлектрический излучатель посылает ультразвуковой пучок, пьезоэлектрический приемник улавливает отраженный сигнал. По задержке отражённого от объекта сигнала определяется расстояние до цели (рис. 4.6).

Рис. 4.6. Принцип работы ультразвукового дальномера HC-SR04
Особенности ультразвукового дальномера HC-SR04:
- Простота в использовании и 4-контактное подключение. Диапазон измерения: от 2 см до 400 см. Точность измерения: ± 1 см (при максимальной дальности ± 3 см). Угол измерения: 15є. Ультразвуковой диапазон работы на частоте 40 кГц. Рабочее напряжение 4,8 В до 5,5 В (± 0.2 В макс). Диапазон рабочих температур: 0 ° С до 60 °С (± 10%).
Подключение модуля HC-SR04
Модуль подключается четырьмя выводами. Контакты VCC и GND служат для подключения питания, а Trig и Echo— для отправки и приема сигналов дальномера. Напряжение питания дальномера +5 В.
Пример работы (рис. 4.7):

Рис. 4.7. Осциллограммы сигналов ультразвукового дальномера HC-SR04
Для того, чтобы инициализировать отправку сигнала дальномером, необходимо подать сигнал высокого уровня длительностью 10 мкс на вывод Trig (a). После получения высокого сигнала длительностью 10 мкс на входе Trig модуль HC-SR04 генерирует пачку из 8-ми импульсов частотой 40 кГц (b) и устанавливает высокий уровень на выходе Echo (с). После получения отраженного сигнала модуль устанавливает на выходе Echo низкий уровень (c).
Импульс высокого уровня Echo имеет длительность до 25 мс. Длительность выходного импульса будет пропорциональна расстоянию до препятствия, от которого отразилась ультразвуковая волна. Нам остается только поймать этот импульс, посчитать его длительность и перевести это значение в расстояние (рис. 4.8).

Рис. 4.8. Длительности импульсов ультразвукового дальномера HC-SR04
Зная продолжительность высокого сигнала на контакте Echo, можем вычислить расстояние, умножив время, которое потратил звуковой импульс, прежде чем вернулся к модулю, на скорость распространения звука в воздухе (340 м/с).
Функция pulseIn() языка Arduino позволяет получить длительность импульса в [мкс]. Запишем результат работы этой функции в переменную duration.
Теперь вычислим расстояние, переведя скорость из м/с в см/мкс:
distance [см] = duration [мкс] * 340 м/с = duration [мкс] * 0.034 [см/мкс].
Преобразуем десятичную дробь в обыкновенную:
distance [см] = duration [мкс] * 1/29 = duration [мкс] / 29.
Принимая во внимание то, что звук преодолел расстояние до объекта и обратно, поделим полученный результат на 2:
distance [см]= duration [мкс] / 58. (4.12)
Пример программы, которая измеряет расстояние до объекта и выдает результат в последовательный порт:
// что к каким контактам подсоединено
// для HC-SR04
int trigPin = 13;
int echoPin = 12;
void setup()
{
Serial. begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop()
{
int duration, distance;
// для большей точности установим значение LOW на пине Trig
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// теперь установым высокий уровень на пине Trig
digitalWrite(trigPin, HIGH);
// подождем 10 мкс
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// узнаем длительность высокого уровня на пине Echo
duration = pulseIn(echoPin, HIGH);
// рассчитаем расстояние [см]
distance = duration / 58;
// выведем значение в Serial Monitor
Serial. print(duration);
Serial. print(" ");
Serial. print(distance);
Serial. println(" cm");
delay(100);
}
Меры безопасности
Во время выполнения лабораторной работы необходимо:
- соблюдать правила включения и выключения вычислительной техники; не подключать кабели, разъемы и другую аппаратуру к компьютеру, не относящиеся к лабораторной установке; при включенном напряжении сети не отключать, не подключать и не трогать кабели, соединяющие различные устройства компьютера; в случае обнаруженной неисправности в работе оборудования или нарушения правил техники безопасности сообщить руководителю лабораторной работы; не пытаться самостоятельно устранить неисправности в работе аппаратуры; по окончании работы привести в порядок рабочее место.
ВНИМАНИЕ! При работе за компьютером необходимо помнить: к каждому рабочему месту подведено опасное для жизни напряжение. Поэтому во время работы надо быть предельно внимательным и соблюдать все требования техники безопасности!
Описание лабораторной установки
Внутри корпуса лабораторной установки размещены (рис. 1.7):
- плата отладочного модуля MSP430 LaunchPad (MSP-EXP430G2); 4-позиционный дисплей отображения информации на основе 7-сегментных светодиодных индикаторов SHD0028G(R); пьезокерамический излучатель ЗП-1, предназначенный для получения звуковых эффектов.
Ультразвуковой дальномер HC-SR04 установлен на плате расширения
Плата LaunchPad подключается к порту USB компьютера с помощью прилагаемого кабеля. На контакты микроконтроллера платы LaunchPad могут устанавливаться дополнительные платы расширения. Напряжение питания платы расширения подается от порта USB компьютера через дополнительное гнездо питания и контактную колодку. Подключение кабелей к лабораторной установке (рис. 1.10): черный кабель подключается разъему мини-USB платы LaunchPad и основному порту USB компьютера, через который осуществляется программирование микроконтроллера. Красно-черный кабель подключается к гнезду дополнительного питания +5В лабораторной установки и к любому другому свободному порту USB компьютера (только если используется 4-позиционный дисплей или устанавливается плата расширения).
Используемая в лабораторной работе плата расширения с устанговленным модулем HC-SR04 подключается к разъему платы LaunchPad (выводы 11… 20). Выводы Trig и Echo модуля соединяются с выводами микроконтроллера 13 (линия порта P2.5) и 12 (линия порта P2.4) соответственно. Питание +5В на плату расширения подается через установленную на ней контактную колодку (разъем) белого цвета и кабель от гнезда питания (желто-белый на рис. 1.7). Питание на плату расширения следует подавать после того, как она подключена к плате LaunchPad.
Описание используемых программных комплексов
Для программирования отладочного модуля MSP430 LaunchPad (MSP-EXP430G2) в лабораторной работе используется среда разработки Energia. Для поддержки операций с последовательным интерфейсом в составе среды Energia имеется специализированный модуль Serial Monitor. Вызов окна Serial Monitor производится либо из меню Tools/Serial Monitor, либо с помощью кнопки Serial Monitor на панели инструментов.
Задание
7.1. Подключить отладочный модуль MSP430 LaunchPad с установленным в DIP-гнездо микроконтроллером MSP430G2452 при помощи кабеля к разъему порта USB компьютера. Запустить среду разработки Energia. Произвести настройку связи среды разработки Energia с отладочным модулем LaunchPad.
7.2. Написать, отладить и протестировать программу измерения длительности нажатия кнопки PUSH2 с использованием функции pulseIn(). Перед началом измерения программа должна выдавать в COM-порт приглашение для нажатия кнопки и произвести мигание красным светодиодом. После измерения, если кнопка действительно была нажата, в COM-порт нужно выдать измеренное значение времени нажатия в миллисекундах и мигнуть зеленым светодиодом. В противном случае – выдать в COM-порт сообщение об отсутствии нажатия кнопке.
7.3. Подключить 4-позиционный светодиодный дисплей к линиям порта P2.2, P2.1, P2.0, P1.5. Написать, отладить и протестировать программу обработки внешнего прерывания.
7.4. Написать, отладить и протестировать программу измерения температуры с помощью встроенного в микроконтроллер датчика. Программа должны работать по алгоритму демонстрационной программы, приведенному в разделе 3.3, и выдавать в COM-порт значения метки времени, текущего измерения температуры, среднего значения температуры по 5 измерениям в градусах Цельсия, Кельвина и Фаренгейта. Кроме того, на светодиодный 4-позиционный дисплей должны выдаваться значения температуры в виде целых значений градусов Цельсия.
7.5. Подключить плату расширения к плате LaunchPad. Подключить плату расширения к свободному порту USB компьютера. Написать, отладить и протестировать программу измерения расстояния с помощью ультразвукового модуля HC-SR04. Значения расстояния в сантиметрах выдавать в последовательный порт и на светодиодный дисплей. Проверить правильность показаний ультразвукового дальномера с помощью линейки или рулетки.
Методика выполнения задания
8.1. Настройку программной среды Energia производить в соответствии с указаниями раздела 5 Лабораторной работы № 1 по курсу «Применение микроконтроллеров в технических системах».
8.2. Изучить пример использования функции puiseIn() в разделе 3.
8.3. Изучить пример обработки прерывания в разделе 3. Придумать и реализовать световые и звуковые эффекты, выдаваемые основной программой до и после обработки прерывания. Количество нажатий кнопки отображать на светодиодном дисплее.
8.4. При написании программы следует использовать расчетные формулы 4.9 – 4.11 и пример программы из раздела 3.3. Нагревать корпус микроконтроллера можно пальцем.
8.5. При написании программы следует использовать расчетную формулу (4.12) и пример программы из раздела 3.4. В качестве объекта, до которого определяется расстояние, можно использовать крышку лабораторной установки.
Требования к содержанию и оформлению отчета
Отчет по лабораторной работе должен содержать:
- краткие теоретические сведения; формулировку задания на лабораторную работу; описание последовательности выполнения работы; изображения рабочих окон с текстами программ; тексты программ, не помещающихся в рабочем окне; выводы по лабораторной работе.
Контрольные вопросы
10.1. Какие виды прерываний имеются в микроконтроллерах MSP430?
10.2. Как определяются приоритеты прерываний в микроконтроллерах MSP430?
10.3. Какие прерывания являются немаскируемыми?
10.4. Какие прерывания являются маскируемыми?
10.5. Как производится обработка прерывания?
10.6. Как назначаются векторы прерываний в микроконтроллерах MSP430?
10.7. Какие функции языка Arduino используются при обработке прерываний?
10.8. Какие функции языка Arduino используются для работы с температурным датчиком микроконтроллеров MSP430?
10.9. Каков принцип измерения расстояния с помощью ультразвукового дальномера?
10.10. Как программируется процесс измерения расстояния с помощью ультразвукового модуля HC-SR04?
Критерии оценки выполнения лабораторной работы
Лабораторная работа считается выполненной в том случае, если:
- студент выполнил все задания в соответствии с представленной методикой; результаты выполнения работы, представленные в виде отчета, соответствуют предъявленным к ним требованиям; студент правильно ответил на все контрольные вопросы и может интерпретировать полученные результаты.


