Программинг микроконтроллеров / MSP430, учимся программировать и отлаживать железо (часть 2)

в 20:29, , рубрики: Новости, метки: ,

Программинг микроконтроллеров / MSP430, учимся программировать и отлаживать железо (часть 2)

Здравствуй, уважаемый хабрапользователь.
В предыдущей статье мы начали рассматривать программирование под MSP430.
Материал, описанный в данной статье, позволит в общих чертах ознакомиться с прерываниями и понять некоторые тонкости MSP430.
Введение
Прерывание (англ. interrupt) — сигнал, сообщающий процессору о наступлении какого-либо события. При этом выполнение текущей последовательности команд приостанавливается и управление передаётся обработчику прерывания, который реагирует на событие и обслуживает его, после чего возвращает управление в прерванный код.
Механизм прерываний создан для обеспечения максимально оперативной реакции программы на определенные события. Это очень важная часть знакомства с любым микроконтроллером.
Прерывания

Начнём с небольшого примера.

#include "msp430f2274.h"

 

void main()

{

  WDTCTL = WDTPW + WDTHOLD;

 

  P1DIR &= ~BIT2;

  P1REN |= BIT2;

 

  P1IE |= BIT2; // Разрешение прерываний на P1.2

  P1IES |= BIT2; // Прерывание происходит по 1/0 (отпусканию/нажатию)

  P1IFG &= ~BIT2; // Очистка флага прерываний для P1.2

 

  P1DIR |= BIT0 + BIT1;

  P1OUT |= BIT0;

  P1OUT &= ~BIT1;

  __bis_SR_register(GIE); // Установка флага глобального разрешения прерываний

 

  while(true);

}

 

#pragma vector=PORT1_VECTOR

__interrupt void P1INT() // Обработчик прерывания

{

  P1IE &= ~BIT2; // Запрет прерываний на P1.2

 

  P1OUT ^= BIT0; // P1.0 меняет своё состояние

  P1OUT ^= BIT1; // P1.1 меняет своё состояние

 

  for(volatile unsigned int i = 30000; i != 0; i--); // Задержка

  P1IE |= BIT2; // Разрешение прерываний на P1.2

  P1IFG &= ~BIT2; // Очистка флага прерываний для P1.2

}

 

В данном примере по нажатию на кнопку (P1.2) происходит прерывание, которое меняет состояние двух светодиодов (P1.0 и P1.1). Давайте разберёмся как же это происходит.PxIE разрешает прерывания для пинов порта Px. Значение «1», записанное в определенный разряд позволяет получать прерывания от определенного пина.PxIES определяет по какому уровню сигнала будет происходить прерывание. В нашем случае это означает, что единица, помещенная в конкретный разряд данного регистра, позволит получать событие нажатия кнопки. И наоборот, ноль позволит получать событие отпускания кнопки.Напомню, что кнопка в данном примере «подтянута» до единицы, это означает что нажатая кнопка имеет значение ноль.
На схеме подключения резистор R1 нарисован показательно, на самом деле он находится внутри микроконтроллера и включается регистром P1REN.PxIFG и есть флаг прерывания. В случае возникновения события нажатия кнопки он будет установлен в единицу, что и вызовет обработчик прерывания (__interrupt void P1INT()). Соответственно, сразу после обработки события флаг необходимо сбросить.Попробуйте убрать из примера строчку 32 в конце обработчика, и тогда, сразу после первого нажатия кнопки, лампочки будут переключаться так, как будто вы постоянно нажимаете на кнопку.__bis_SR_register(GIE) устанавливает флаг глобального разрешения прерываний (Global Interrupt Enable) в status register. Фактически это эквивалентно записи SR |= GIE, но мы можем обращаться к регистру SR только по средствам функций __bis_SR_register и __get_SR_register.
Ниже приведена схема битов в SR регистре.0, 1, 2 и 8 биты — это биты математических операций.4, 5, 6, 7 — биты управления уровнями энергопотребления, за счёт уменьшения частоты или отключения АЛУ.
Ну и собственно бит 3 — это глобальное разрешение прерываний. Пока этот бит не установлен в единицу, никакие прерывания обрабатываться не будут.#pragma vector — директива, которая определяет что нижеследующая функция является обработчиком указанного прерывания.Список всех доступных векторов прерываний можно посмотреть в заголовочном файле для Вашего контроллера. В данном случае это msp430f2274.h.
Дребезг контактов

Про это явление можно подробно прочитать в википедии. Дребезг контактов возникает при нажатии кнопки, благодаря чему обработчик прерываний будет вызван многократно. В данном примере этого удалось избежать следующим образом:Сразу после вызова обработчика устанавливается запрет прерываний (строка 25);

после переключения состояний светодиодов делается задержка (строка 30);

снова устанавливается разрешение прерываний (строка 31).

Директива volatile в 30 строке кода означает, что переменная i не будет оптимизироваться при компиляции. Если её убрать, то задержки не будет.
Заключение

После прочтения предыдущей статьи, коллеги и друзья упрекнули меня в том, что я не уделяю достаточно внимания мелочам. В этот раз я постарался исправить этот недостаток и сделать материал статьи ещё более доступным. Однако это значительно увеличило объем информации.
В следующий раз я постараюсь рассмотреть передачу данных с контроллера на персональный компьютер по средствам программатора и, в зависимости от полученного объема, watchdog.
Я надеюсь, что эта статья оказалась полезна тебе, читатель.


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js