Analytics

пятница, 30 ноября 2012 г.

Лекция №04: Крутимся в цикле

Прим. переводчика: Прошу прощения, за огромную задержку. Было слишком много дел, да и редакторша подвела. В общем, отныне статьи выкладываться будут без редактирования, а почему - не удивляйтесь, если встретите в тексте какие-нибудь глуповатые словообороты или лишние запятые. Так что извините: чем богаты тем и рады.

Теперь, когда наших знаний достаточно для того чтобы написать нашу первую программу для MSP430, мы с вами поучимся их писать. Писать нашу первую программу, мы будем под микроконтроллер MSP430G2211 который поставляется с платой LaunchPad. Если же, вы не используете эту плату, то ничего страшного, эта программа настолько проста, что никаких проблем с этим возникнуть не должно. Единственное условие - это подключенный светодиод к одной из ножек GPIO(англ.: General Purpose I/O - система ввода/вывода общего назначения), а это - ножки нашего микроконтроллера. Подключите светодиод через резистор(пары сотен Ом, должно хватить) чтобы избежать возможности подачи слишком большого напряжения.
Владельцам LaunchPad’а же, ничего подключать не надо, на этой плате имеются все необходимые элементы.

В наших предыдущих лекциях, мы упоминали короткие имена BITx которые содержатся в специальном заголовочном файле для нашего устройства. Имя его совпадает с именем указанным на вашем микроконтроллере. К примеру - “msp430g2211.h”, так что если вы используете какой-либо другой микроконтроллер, просто укажите вашу маркировку.
Получается, что первая строчка любой программы для MSP430 должна выглядеть примерно(зависит от микроконтроллера) так:

#include <msp430g2211.h>

Обычно, это единственная строка которая требуется для того чтобы приступить к написанию “тела” основной программы. По крайней мере, для написания нашей первой программы, кроме неё уж точно ничего не требуется. Что же будет делать наша первая программа? Мы просто будем мигать нашими светодиодами. Это своеобразный “Hello world!” в программировании микроконтроллеров. Назовём эту программу “мигалкой”. Наша мигалка это простая программа, которая включает и выключает светодиод с заданным интервалом времени. Эта самая мигалка, поможет нам научиться использовать таймеры, прерывания и тому подобные вещи но, немного терпения: сначала нам надо рассмотреть более простой способ достичь того же функционала, пусть и несколько “грязновато”. Способ этот, самый простой из всех возможных: использовать “пустой” цикл чтобы имитировать необходимую нам паузу между включением и выключением светодиода. На нашей плате LaunchPad зеленый светодиод подключен к P1.0, а красный - к P1.6. Для начала, мы помигаем только зеленым. Приступим!
Начинаться наш код будет с таких строк:

#include <msp430g2211.h>

void main(void) {

} // main

Прежде чем мы продолжим, хотелось бы напомнить про специальный сторожевой таймер(англ.: WatchDog Timer), в одной из предыдущих статей я достаточно подробно описал то, зачем он нужен и что делает, поэтому не буду заострять на нём внимание, просто освежу ваши воспоминания: этот таймер с определенным интервалом сбрасывает микроконтроллер в начальное состояние.
По умолчанию, этот таймер включается вместе с нашим микроконтроллером. Так как нам не надо никаких сбросов, нам придется его отключить(как работать с этим таймером, чтобы получать необходимую нам задержку, мы поучимся позже).

У WDT имеется 16-битный настроечный регистр, названый WDTCTL(англ.: WatchDog Timer ConTroL) но только первые 8 бит этого регистра, содержат биты управления этим таймером, остальные, верхние 8 бит, использованы в целях безопасности - если вы хотите изменить настройки WDT вам придется предоставить “пароль”, верхние 8 бит и являются этим самым паролем, а именно: 0x5A(вообще, так как наш регистр все же 16-битный, то было бы правильнее написать - 0x5A00). Именно такое значение должно быть установлено в верхние биты этого регистра, чтобы избежать случайных записей в связи какими-нибудь сбоями. Не стоит пугаться - в наш заголовочный файл уже включено короткое имя для нашего пароля - WDTPW(англ.: WDT PassWord), для выключения сторожевого таймера, аналогично имеется короткое имя - WDTHOLD. Получается, что для того чтобы выключить наш надоедливый таймер, нам всего-то надо указать в настроечном регистре “кодовую фразу” и притормозить таймер:

WDTCTL = WDTPW + WDTHOLD;

Бит WDTHOLD можно рассматривать как логическое состояние “таймер остановлен”. То есть, если этот бит равен 1(истина), то таймер остановлен, если же 0(ложь) - таймер работает. Вышеуказанной строчкой, мы его “остановили” установив в этот бит значение 1.
Вам следует взять в привычку начинать все ваши первые программы с этой строки, чтобы избежать каких-либо осложнений, но имейте ввиду, WDT обладает очень полезным функционалом и не раз вам поможет в будущем, но на данной стадии обучения он нам совершенно не нужен, так что выключайте его с первых строк.

Окей, сторожевой таймер выключен, теперь мы можем продолжить написание нашего кода. Мы хотим зажечь светодиод на P1.0, из предыдущей лекции мы уже знаем как это сделать:

P1OUT = 0;
P1DIR = BIT0;

Теперь наша задача, заставить светодиод включаться и выключаться по истечению заданного интервала времени. В качестве примера, я буду использовать цикл for, хотя если вы желаете, вы можете написать любой цикл, будь то for, while или do-while. Кроме того, нам необходима переменная-счетчик для цикла, так что не забудьте определить её в начале вашего кода:

#include <msp430g2211.h>

void main(void) {
   unsigned int count;
   WDTCTL = WDTPW + WDTHOLD;

   P1OUT = 0;
   P1DIR = BIT0;

   P1OUT |= BIT0;
   for (count = 0; count < 60000; count++);
   P1OUT &= ~BIT0;
   for (count = 0; count < 60000; count++);

} //main

Что же произойдет когда микроконтроллер дойдет до последней строчки кода? Компьютер бы просто завершил программу, а вот микроконтроллер будет просто считает следующий адрес, выполнит следующую инструкцию, где может быть вообще что угодно. Скорее всего, там будут мусорные данные которые остались от предыдущих программ, которые превосходили по объему нашу. В любом случае, микроконтроллер будет считывать и считывать, пока не дойдет до самого конца адресного пространства выделенного под нашу программу и тогда … ну, я понятия не имею что тогда. Так или иначе, это совсем не то на что мы расчитывали при написании нашей программы, так что не помешало бы предотвратить подобное поведение. Сделаем мы это, заключив наш код в бесконечный цикл который будет выполнять наш код снова и снова, пока подача питания не прекратится. Вообще - довольно дурной тон, писать подобные конструкции, но пока что, нам не до манер, мы просто хотим поскорее сделать нашу мигалку:

#include <msp430g2211.h>

void main(void) {
   unsigned int count;
   WDTCTL = WDTPW + WDTHOLD;

   P1OUT = 0;
   D1DIR = BIT0;

   for (;;) {
       P1OUT |= BIT0;
       for (count = 0; count < 60000; count++);
       P1OUT &= ~BIT0;
       for (count = 0; count < 60000; count++);
   }
} // main

Как и прежде, вместо этого цикла вы можете использовать цикл while(1) или что-нибудь подобное, как вам удобнее.

Вот наша мигалка и готова! Светодиодик загорается, ждёт, затухает, снова ждёт, а потом возвращается к первому шагу, на котором он снова загорается и … и так до бесконечности.
Вот более “чистый” код, тут используются те самые битовые операции из предыдущей лекции:

#include <msp430g2211.h>

void main(void) {
   unsigned int count;         // счетчик цикла
   WDTCTL = WDTPW + WDTHOLD; // выключаем сторожевой таймер

   P1OUT = 0;                // инициализируем начальное значение светодиода как 0
   P1DIR = BIT0;             // P1.0 в режим вывода
   for (;;) {
       P1OUT ^= BIT0;       // изменить состояние светодиода как P1.0
       for (count = 0; count < 60000; count++);   // ждём
   }
}

Теперь, для того чтобы изменить частоту мигания, вам всего-то достаточно изменить “длину” цикла. К примеру, вместо 60000 написать 30000, тогда мигалка будет мигать в два раза быстрей.
Как вы заметили, некоторые строки кода снабжены комментариями. Да, согласен, в программах подобной сложности, они возможно и не нужны, так как код сам по себе очевиден, но в любом случае, вам следует взять в привычку комментировать свои исходные коды. Это считается хорошим тоном, да и вообще, не раз вам поможет.

Упражнения: Напишите программу, которая мигает поочередно красным и зеленым светодиодом. Затем, модифицируйте её так, чтобы они мигали независимо друг от друга.

Перевод: Александр Мошкин
Оригинал статьи: Tutorial 04: Stuck in a Loop
Следующая лекция: Лекция №05. Загружаем программу.
Предыдущая лекция: Лекция №03. Жонглируем битами.