Знакомство с LaunchPad от TI. Первые шаги по его программированию.

finaloverview

Доброго времени суток. Долгое время я завис на контроллерах семейства PIC и программировании на ассемблере. Но один мой знакомый подарил мне LaunchPad от Texas Instruments, c камешком MSP430G2553. И вы не поверите, но моя жизнь стала легче =))).
Как и все, начал я с простого. А именно, загрузил семпл программы от TI, и поковырял его, для того, чтобы иметь хотя бы малейшее представление, что и как работает.
Итак, сразу после установки Code Composer Studio и ее запуска, нам необходимо создать новый проект.

C_1.P_1

Далее появится следующее окно:

C_1.P_2

Здесь нам необходимо нажать на вкладочку Code Composer Studio, а затем CCS Project, и нажать Next. В следующем, появляющемся окне, необходимо выбрать тот тип контроллера, который установлен в вашем LaunchPad, ну и как нибудь обозвать ваш проект.

C_1.P_3

После чего вам станет доступна кнопка Finish.
В рабочем окне ССS необходимо вставить текст нашей будущей прошивки для LaunchPad. Можете скопировать его отсюда, либо из папки с примерами.
Хочу так же обратить внимание на то, что когда вы подключите LaunchPad к компьютеру, то скорее всего он начнёт моргать светодиодом. Это и есть та самая программка, которую мы и будем сейчас ковырять. Поэтому, для того, чтобы после прошивки контроллера мы могли сразу увидеть разницу, изменим частоту мерцания светодиода.

#include <msp430.h>
 
Int main(void) {

WDTCTL = WDTPW + WDTHOLD; // отключаем сторожевой таймер

P1DIR |= 0x01; // Настраиваем нулевой бит порта Р1 на выход

for(;;) {

volatile unsigned int i; // отключаем оптимизации для i

P1OUT ^= 0x01; // инвертируем значение нулевого бита порта Р1

i = 10000; // Присваиваем i значение 10000 (интервал задержки)

do i--;   // вычитаем из i = 10000 единицу до тех пор пока

while(i != 0); // i не станет равным нулю
} 
} 

Вот, собственно, простенький код нашей программы. Итак разберём подробно каждую строчку.
#include <msp430.h>

Здесь мы подключаем необходимые для программирования вашего контроллера библиотеки. Это стандартная запись , которую мы получаем автоматически при создании проекта.
Правильнее же будет записать её так :
#include <msp430G2553.h> или #include <msp430G2211.h>
Все будет зависеть от того, какой камень у вас установлен в LaunchPad.
Int main(void)
Тут мы объявляем функцию main, которая и будет основным телом нашей программы. Всё, что мы хотим записать в эту функцию, должно быть записано в фигурных скобках {}. Та же ситуация будет и с телами циклов в этой функции. Все, что мы хотим записать в тело какой либо функции, цикла и т.д., должно будет записываться в фигурных скобках.
WDTCTL = WDTPW + WDTHOLD;

Отключаем сторожевой таймер.
Сторожевой таймер (кратко WDT), имеет 16-битный регистр, называемый WDTCTL, но только младшие 8 бит используются для контроля. Старший байт используется для проверки безопасности: что бы ваш код случайно не изменил WDT, вы должны указать пароль. Это значение старшего байта, равное 0x5a (в старшем байте, полное же число 0x5a00), к счастью заголовочный файл уже содержит определение для этого значения WDTPW, проще запомнить его. Это значение добавляется к байту конфигурации, которую вы хотите вписать в WDTCTL.
Привыкайте использовать эту строчку вначале всех ваших программ, но не забывайте о том, что сторожевой таймер может выполнять несколько полезных функций.
Как и любой контроллер, MSP430 содержит параллельные порты ввода/вывода. Что это означает? А означает это следующее, что одна и та же ножка контроллера может как принимать сигналы, так и выдавать их. Например, если вы хотите, чтоб какой-то светодиод, реле, лампочка, любой исполнительный механизм подёргался или засветился и погас, вам необходимо настроить соответствующую ножку контроллера на выход. И наоборот, если вы хотите, чтоб контроллер реагировал на нажатие какой-то кнопки или любой другой сигнал из вне, то необходимо настроить соответствующую ножку контроллера на вход. На LaunchPad часть выходов маркирована как Р1.0, Р1.1……….Р1.7. Все они логически объединены в порт Р1, регистр P1DIR, которого, управляет направлением этих портов. То есть, если в N-й бит этого регистра записать 1, то N-й выход этого порта сконфигурирован как выход и можем управлять напряжением на этом выходе.
P1DIR |= 0x01;
Данная строчка настраивает нулевой бит порта P1, на выход. Нулевой бит соответствует первой ножке порта P1.0. Именно на этой ножке находиться красный светодиод. Так же альтернативной записью для настройки может быть следующее:
P1DIR |= BIT0;
Если внимательно присмотреться к LaunchPad, то вы увидете, что рядом с красным светодиодом находится зелёный. Он так же подключен к порту P1, но только уже к 6-му биту. И если мы захотим зажигать и этот светодиод , то нам также нужно настроить соответствующий бит на выход.
P1DIR |= BIT6; или P1DIR |= 0x40;
Если же мы хотим работать с обоими выходами, то настроим оба бита на выход.
P1DIR |= BIT0|BIT6; или P1DIR |= 0x41;
Если же мы захотим обнулить их и настроить на вход, то нам понадобиться другая команда: P1DIR &=~0x41; или P1DIR &=~(BIT0|BIT6); .
Для того, чтобы наш светодиод постоянно мигал, необходимо создать бесконечный цикл, в котором это будет происходить. Для этого объявим бесконечный цикл for(;;) , в котором описана переменная volatile unsigned int i; . Это беззнаковое целое, а ключевое слово volatile обозначает, что для этой переменной отключены оптимизации компилятора.
Из-за этого бесполезный с математической точки зрения цикл:

i = 10000; 

do i--;

while(i != 0);

не будет проигнорирован компилятором, а принудительно выполняться на МК. Бесполезный он потому, что внутри цикла ничего не делается и по его окончанию, переменная i всегда равна нулю. И с точки зрения компилятора, это все можно было бы заменить на i = 0. Но в нашем случае МК будет тратить 10000 тактов, чтобы обнулить i . То есть, цикл будет выполняться до тех пор, пока while(i != 0); (пока i не станет равным нулю).
При частоте в 1 МГц, это займет примерно 0.1 секунду.
Так же нам необходимо изменять состояние светодиода. В данном примере нам абсолютно не важно с какого состояния светодиода начнётся выполнение программы. По этому в начале цикла напишем следующую команду:
P1OUT ^= 0x01;
Эта команда будет инвертировать значение нулевого бита порта Р1. То есть, если до этого он был равен единице, то эта команда установит его в ноль, и наоборот.
Теперь зная, какая строчка и команда, за что отвечает, уменьшим частоту мерцания в два раза, а так же подключим второй светодиод, чтобы они оба моргали, причем поочерёдно.
Для того, чтобы уменьшить частоту мерцания в 2 раза, необходимо в 2 раза увеличить значение i. То есть, в цикле for(;;) присвоим i=20000 вместо 10000.
Если загрузить данную программу, изменив только значение переменной i, красный светодиод станет моргать в два раза реже. Но ведь нам еще необходимо подключить зелёный и мигать ими попеременно. Для этого настроим шестой бит порта P1 на выход. Заменим строчку
P1DIR |= 0x01; на P1DIR |= 0x41;
Таким образом, мы натсроили нулевой и шестой биты порта Р1 на выход. В двоичном коде, это выглядит так — 0100001. Порты нашего контроллера 8-ми битные, именно так очень удобно представлять себе их настройку перед записью в формате HEX, кстати для этого воспользуйтесь калькулятором вашей ОС, поменяв его вид на «программист» .
Итак, для изменения состояния светодиодов, нам всё так же удобно пользоваться командой инвертирования их состояния P1OUT ^= 0x41; .
Но если в стандартном примере нам не важно, с какого состояния светодиода начинает работать программа, то здесь нам необходимо указать, какой светодиод должен гореть, а какой нет, перед началом выполнения. По этому сразу после настройки порта запишем P1OUT |= 0x01; или P1OUT |= 0x40; , тем самым в начале выполнения программы мы зажигаем один из светодиодов, а вышеупомянутая команда P1OUT ^= 0x41; , будет менять их состояния на противоположные. Если в первом случае горел красный и не горел зелёный, то данная команда потушить красный светодиод и зажжет зелёный, при повторении цикла, снова произойдут изменения на противоположные.
Если же не записать одну из команд P1OUT |= 0x01; или P1OUT |= 0x40; , то оба светодиода будут работать синхронно — одновременно тухнуть и зажигаться.
И так, после всех выше перечисленных изменений, программа должна выглядеть следующим образом:

#include <msp430G2553.h> 

Int main(void) {

WDTCTL = WDTPW + WDTHOLD; // отключаем сторожевой таймер

P1DIR |= 0x41; // Настраиваем нулевой и шестой бит порта Р1 на 
               // на выход

P1OUT |= 0x01; // зажигаем один светодиод (P1.0, красный)

for(;;) {

volatile unsigned int i; // отключаем оптимизации для i

P1OUT ^= 0x41; // инвертируем значение нулевого бита порта Р1

i = 20000; // Присваиваем i значение 20000 (интервал задержки)

do i--;   // вычитаем из i = 20000 единицу до тех пор пока

while(i != 0); i не станет равным нулю

} 
}

После того, как вы введёте текст программы в рабочем окне, необходимо откомпилировать программу и прошить контроллер. По этому подключив ваш LaunchPad к компьютеру и выполнив все вышеуказанное, нажмем кнопку ”Debug rrr” , а после окончания компиляции и прошивки, кнопку ”Resume”.

C_1.P_4

Данный код реализует работу LaunchPad так, как это показано на видео ниже. Попробуйте внести свои изменения в код, пользуясь изложенной информацией. В следующей статье мы разберём систему прерываний и способы тактирования контроллера, а так же попробуем изменить поведение светодиодов по нажатию кнопки.

You may also like...

10 Responses

  1. Алексей Колесниченко:

    Весьма не дурно=)) с почином!

  2. Хороший сайт!!! Респект!!!)));;;

  3. Сергей:

    Скажите пожалуйста, а где взять стоковые прошивки, которыми прошиты 2 контроллера лончпада? Особенно 2553, с измерялкой температуры.
    На сайте TI пытался найти, но там чёрт ногу сломит.

  4. Сергей:

    Кажется, и в примерах кода нет того, что надо. Даже здесь http://www.ti.com/tool/msp-exp430g2
    Это же надо так спрятать.

  5. Сергей:

    Наконец-то! Слава тебе, яйца!

    Спасибо за ссылку. Самое непонятное, что 435-й архив я тоже скачивал раньше, но не было там ничего, кроме виндовой морды для градусника.

Добавить комментарий для Сергей Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>