8-900-374-94-44
[email protected]
Slide Image
Меню

Программирование msp430 – Программирование под MSP430

MSP430, учимся программировать и отлаживать железо (часть 3) / Habr


Возможно Вы уже не первый раз садитесь за программирование Вашего MSP430. Если это не так, то рекомендую ознакомиться с предыдущими статьями по данной тематике: часть 1, часть 2.
В этой статье мы рассмотрим инструмент для графической настройки периферии нашего микроконтроллера — Grace, познакомимся с принципом работы watchdog и поработаем с виртуальным COM-портом (через программатор). Уже традиционно будет рассмотрен небольшой пример кода, и предоставлены все необходимые для понимания ссылки.
Введение

В первой статье я упоминал Code Composer Studio, от рассмотрения которого отказался, но недавно моё внимание, благодаря Соколову А.В., привлёк один плагин для неё — Graphical Peripheral Configuration Tool (Grace).

Каждый раз, когда приходится настраивать очередной периферийный модуль MSP430, мы сталкиваемся с рядом сложностей. К таким сложностям можно отнести незнание списка регистров конкретного модуля, отличительные особенности конкретного микроконтроллера или плохое понимание англоязычных документаций. В любом из перечисленных случаев Grace может стать полезным.

Grace

Скачать и установить этот инструмент можно вместе с Code Composer Studio v5 по следующей ссылке. Для этого потребуется зарегистрироваться на сайте Texas Instruments.

После установки CCS выбираем Project→New CCS Project, в облати Project templates and examples выбираем Empty Project→Empty Grace (MSP430) Project, в области Device не забудьте указать микроконтроллер из списка.

Как только появится экран «Grace — Welcome», нажимаем клавишу Device Overview. Перед Вами появится следующая картинка.

Кликнув по конкретному устройству на ней, Вы перейдёте к его настройке, которую можно производить в нескольких режимах. Режимы могут отличаться для разных устройств, но обычно это Basic User, Power User и Registers. Basic User

и Power User предназначены для быстрой настройки периферийного устройства интуитивно. Registers отображает список всех регистров устройства и позволяет менять их значения.

Совет: в datasheet к микроконтроллеру не всегда содержится полная информация об интересующем устройстве, про все регистры и параметры обычно можно прочитать в файле MSP430xxxx Family User’s Guide, который можно скачать на сайте Texas Instruments.

Поскольку для работы я уже привык использовать Workbench, после завершения настройки, все конфигурационные данные требуется перенести туда. Для этого нажимаем Project→Build All, находим в папке проекта директорию /src/csl/, в ней и находятся все *.c файлы с конфигурацией каждого устройства.

Пример кода

Следующий код работает с USB-UART мостом встроенным в программатор, так же в код включено использование watchdog, но обо всём по порядку.
  1.  
  2. #include «msp430f2274.h»
  3. #include <string>
  4.  
  5. void UARTWriteString(string str);
  6.  
  7. bool watchdogReset = true;
  8.  
  9. void main(void)
  10. {
  11.   WDTCTL = WDT_MRST_32; // Watchdog автоматически
  12.                         // перезапустит систему через 32ms.
  13.  
  14.   BCSCTL1 = CALBC1_1MHZ; // Устанавливаем тактовую частоту Basic Clock System.
  15.   DCOCTL = CALDCO_1MHZ; // Устанавливаем тактовую
  16.                         // частоту Digital Controlled Oscillator.
  17.  
  18.   P3SEL = BIT4 + BIT5; // Выбираем функцию P1.4/P1.5 как TXD/RXD для UART.
  19.  
  20.   UCA0CTL1 |= UCSWRST; // Этот бит блокирует работу прерываний от UART и работу 
  21.                        // сдвигового регистра чтобы не мешать
  22.                        // настройке (грубо говоря отключает UART).
  23.   UCA0CTL1 |= UCSSEL_2; // Наш UART будет работать от 
  24.                         // SMCLK (Sub-main clock), тоесть от 1MHZ.
  25.   UCA0BR0 = 0x68; // Делитель частоты для SMCLK (1000000 / 9600).
  26.   UCA0BR1 = 0x00;
  27.   UCA0MCTL = 0x04; // Определяет маску модуляции.
  28.                   // Это помогает минимизировать ошибки.
  29.   UCA0CTL1 &= ~UCSWRST; // Включаем UART обратно.
  30.  
  31.   P1DIR |= BIT0; // Настройка светодиодов.
  32.   P1DIR |= BIT1;
  33.   P1OUT &= ~BIT0;
  34.   P1OUT &= ~BIT1;
  35.  
  36.   UARTWriteString(«—Привет, Хабр!—«);
  37.  
  38.   unsigned char data;
  39.   while(true)
  40.   {
  41.     while (!(IFG2&UCA0RXIFG)) // Проверка готовности буфера приёма.
  42.       if(watchdogReset)
  43.         WDTCTL = WDTPW + WDTCNTCL; // Сброс таймера watchdog в ноль.
  44.     data = UCA0RXBUF;
  45.     if(data == 0x01)
  46.     {
  47.       UARTWriteString(«—Погасить зеленый светодиод.—«);
  48.       P1OUT &= ~BIT1;
  49.     }
  50.     else if(data == 0x02)
  51.     {
  52.       UARTWriteString(«—Зажечь зеленый светодиод.—«);
  53.       P1OUT |= BIT1;
  54.     }
  55.     else if(data == 0x03)
  56.     {
  57.       UARTWriteString(«—Переключить состояние красного светодиода.—«);
  58.       P1OUT ^= BIT0;
  59.     }
  60.     else
  61.     {
  62.       UARTWriteString(«—Принятые данные не соответствуют.—«);
  63.       watchdogReset = false;
  64.     }
  65.   }
  66. }
  67.  
  68. void UARTWriteString(string str)
  69. {
  70.   int strSize = str.length();
  71.   for(int i = 0; i < strSize; i++)
  72.   {
  73.     WDTCTL = WDTPW + WDTCNTCL; // Сброс таймера watchdog в ноль.
  74.     while (!(IFG2&UCA0TXIFG)); // Проверка готовности буфера отправки.
  75.     UCA0TXBUF = str[i];
  76.   }
  77. }
  78.  

Для работы с COM-портом со стороны компьютера нам потребуется программное обеспечение, мой выбор пал на COM Port Toolkit. Что именно выберите Вы — не имеет значения.

Небольшое видео, которое позволит понять что именно делает пример.

В отличии от предыдущих статей, я постарался дать внятные комментарии прямо в коде программы. Не вижу смысла в этот раз пояснять каждый использованный в коде регистр. Хочу лишь обратить внимание на некоторые аспекты.

  1. Для расчёта значений UCA0BR0, UCA0BR1 и UCA0MCTL существует неплохой онлайн калькулятор.
  2. SMCLK — сигнал, который поступает из внешнего резонатора (если установлен) или из DCO с применением делителей 1, 2, 4 или 8. Используется как тактовый сигнал для периферии.
  3. В примере, watchdog используется не совсем по назначению, данный код лишь объясняет принцип его работы. Смысл заключается в том, что если Ваша программа в течении 32ms (WDT_MRST_32) не установит бит WDTCNTCL в регистре WDTCTL в единицу, то система будет перезагружена. Watchdog требуется для предотвращения зависания Вашего программного обеспечения.
  4. Регистр WDTCTL имеет 16 бит, первые 8 необходимо устанавливать в WDTPW каждый раз когда производится запись в него. Это механизм защиты регистра от случайной записи в случае программных сбоев.
  5. Описание и настройка Basic Clock System это повод для целой статьи, пока следует понять, что MSP430 имеет очень гибкую систему тактовых генераторов, которую, в упрощенном виде, можно настроить с помощью Grace.
  6. Использование такого метода отладки сильно замедляет работу программы в целом, однако это позволяет достоверно определить порядок выполнения кода, в том числе в обработчиках прерываний.
Заключение

Чем дольше я пишу, тем сложнее и больше становится материал. Эта статья станет предпоследней в серии для новичков.
В следующий раз я затрону все вопросы, на которые не успел ответить ранее.

Я надеюсь, что эта статья оказалась полезна тебе, читатель.

habr.com

Быстрый старт с MSP430. | MicroTechnics

Немного отвлечемся от микроконтроллеров STM32 и сегодня займемся устройствами от Texas Instruments – контроллерами MSP430. И эта статья будет посвящена так называемому быстрому старту с этими девайсами. Все опыты и эксперименты будут ставиться на недорогой отладочной платке – MSP430 LaunchPad.

Итак, открываем коробку с платой и достаем все, что нам понадобится. На данном этапе нам нужна лишь сама плата и USB-кабель для подключения ее к компьютеру. Смело втыкаем шнур в USB-разъем и ждем пока заботливый Windows установит нам необходимые драйвера. Но тут есть одна неприятность – драйвер MSP430 Application UART надо найти и установить самим. Не вопрос! Идем на официальный сайт Texas Instruments и качаем IDE (я остановил свой выбор на IAR Embedded Workbench for MSP430). Архив скачан, распаковываем и идем в диспетчер устройств. Там находим наш девайс и указываем вручную пути к файлам драйвера, которые находятся в скачанном архиве в папке Drivers. В случае успеха отладочная плата будет определяться в диспетчере устройств следующим образом:

Первый этап позади, теперь необходимо установить IAR Embedded Workbench. С этим никаких сложностей возникнуть не должно 😉

Запускаем IAR и создаем новый проект. Для этого идем в Project->Create New Project. В появившемся окне выбираем следующее:

В результате получаем пустой проект, в который уже включен файл main.c. Теперь мы можем переходить к написанию собственного кода. Давайте по традиции начнем с портов ввода-вывода. На отладочной плате есть пользовательская кнопка и парочка светодиодов – а точнее два, красный и зеленый. Давайте так – если кнопка нажата горит зеленый, иначе красный ) Но перед тем как писать программу, посмотрим, какие же регистры отвечают в MSP430 за порты ввода-вывода. Итак, начинаем!

Регистр PxDIR (P1DIR, P2DIR..)

Каждый бит этого регистра отвечает за режим работы соответствующего вывода микроконтроллера. Если в регистре бит равен 0, то ножка контроллера является входом, если бит равен 1 – выходом. Пусть, например, второй бит регистра P1DIR равен 1. Что это значит? А то, что вывод P1.1 работает в режиме выхода.

Регистр PxREN

А этот регистр отвечает за включение/отключение подтяжки вверх/вниз. Тут больше и сказать то нечего.

Регистр PxOUT

А вот здесь поинтереснее 😉 Если вывод у нас работает в режиме выхода, то биты этого регистра отвечают за уровень сигнала на ножке контроллера. Пусть у нас P1.3 работает как выход. Если мы выставим четвертый бит регистра P1OUT в 1, то на выводе P1.3 появится сигнал высокого уровня (логическая единица), если 4-ый бит P1OUT равен 0, то и сигнал на ножке контроллера низкого уровня.

Другое дело, если пин работает как вход. В этом случае биты этого регистра отвечают за подтяжку вывода. Вот небольшой примерчик, чтобы сразу все стало понятно. Пусть P1.0 – вход. Если нулевой бит P1OUT = 1, то подтяжка вверх, если нулевой бит равен 0, подтяжка вниз. Все очень логично )

Следующий регистр – PxIN

Тут все просто – биты этого регистра соответствуют уровню сигнала на соответствующих пинах микроконтроллера. На входе – 1, в регистре – 1, на входе 0, и в регистре – 0. Каждому выводу, например, порта 1 (P1.0, P1.1…) соответствует свой бит регистра P1IN.

Регистры PxSEL и PxSEL2 отвечают за альтернативные функции выводов при использовании какой-либо периферии микроконтроллера.

Кроме всего вышеперечисленного, каждый пин портов 1 и 2 может работать в режиме внешнего прерывания. То есть при изменении сигнала на каком-либо выводе программа ускачет на обработку прерывания. Но мы пока не будем на этом останавливаться, а перейдем уже наконец-то к написанию кода программы ) Осталось лишь разобраться, что куда подключено на нашей отладочной плате:


Видим, что кнопка висит на ножке P1.3, а светодиоды на P1.0 и P1.6.

#include "io430.h"
 
int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
 
  // Выводы P1.0 и P1.6 работают в качестве выходов
  P1DIR = BIT6 | BIT0;
  // Обнуляем значение регистра P1OUT и все светодиодики гаснут
  P1OUT = 0x00;
 
  // Как видно из схемы кнопка у нас замыкает вывод на землю,  
  // поэтому активируем для вывода P1.3 подтяжку вверх
  P1REN |= BIT3;
  P1OUT |= BIT3;
 
  while(1)
  {
    // Проверяем состояние кнопки
    if ((P1IN & BIT3) == 0)
    {
      // Зажигаем зеленый, гасим красный, если нажата
      P1OUT |= BIT6;
      P1OUT &= ~BIT0;
    }
    else
    {
      // Не нажата - гасим зеленый, зажигаем красный
      P1OUT |= BIT0;
      P1OUT &= ~BIT6;
    }
  }
 
  return 0;
}

Осталось совсем немного – а именно настроить наш проект и отладчик. Идем в настройки проекта и выбираем наш контроллер:

В этом же окне идем во вкладку Debugger и выбираем FET Debugger вместо Simulator. Теперь мы готовы прошивать программу в контроллер!

В итоге при нажатии на кнопку мы должны увидеть горящий зеленый светодиод, а если кнопка не нажата, то горит красный. На этом, собственно, и все, с быстрым стартом для MSP430 мы разобрались!

microtechnics.ru

Загружаем программу / MSP430 / Сообщество EasyElectronics.ru

Замечание: Я только-только получил свой LaunchPad в посылке, и теперь он у меня есть. Это очень хорошо для развития этих уроков в будущем, но, тем не менее, когда я писал этот урок, то использовал свою 28-выводую TSSOP плату с F2132, описывая всё так, будто бы это G2211 и LaunchPad. Поэтому вы можете заметить некоторые расхождения текста и скриншотов.

Здесь я расскажу о том, что вам необходимо для использования Code Composer Studio (CCS). CCS – это среда программирования, или интерактивная среда разработки (Interactive Development Environment (IDE)). Она базируется на Eclipse, – проекте с открытыми исходниками. Eclipse прекрасная среда для редактирования, вам будет на удивление легко писать программы для MSP430. Википедия TI, посвященная LaunchPad содержит линк на скачку CСS, там необходима регистрация, но потом, ее можно будет использовать для получения бесплатных семплов от TI, так что зарегестрируйтесь. CCS свободна к использованию вплоть до 16Кб кода. Это звучит как не очень много, но не забывайте, что MSP430 идущие с LaunchPad не имеют больше 2Кб под программы! (С LaunchPad версии 1.5 идут микроконтроллеры с 16Кб и 8Кб флеш-памяти, но это тоже не выходит за рамки ограничений бесплатной версии.

– Прим. пер.). Код, получающийся при программировании MSP430, очень эффективный и плотный, он не занимает много места. Что бы понять, сколько места займет ваш код, мы используем отладчик, включенный в CСS.

После установки CСS, запустите его, и он задаст вопрос о рабочем пространстве (workspace). Рабочее пространство, это просто папка, в которой хранятся ваши проекты. Вы можете всегда поменять ее, просто выберете опцию [Change Workspace] в меню [File]. Пока используйте простой путь, такой как “~/My Documents/MSP430 LaunchPad”. Как закончите с этим, появиться приветственная страница как на картинке выше. Вы можете сразу попасть в рабочую среду, кликнув на кубике в верхнем правом углу. Но, в начале, лучше выбрать иконку с надписью

“Getting Started”, кликнув в нее, вы получите несколько линков на полезную информацию о том, как использовать CСS. Рекомендую изучить это перед началом работы.

Положим, вы закончили со всем этим, и разобрались в интерфейсе. Закрывайте приветственную страницу (можно снова ее вызвать опцией [Welcome] в меню [Help]) и заходите в интерактивный редактор. Для начала, нужно всего лишь создать новый проект. Select File → New → CCS Project, и назовите свой проект, как-нибудь понятно для вас. Мне нравится включать в название программы имя конкретной модели микроконтроллера, для которой она пишется. Для мигалки, я назвал проект blinky_G2211. Нажимаем [Next], и убеждаемся что проект именно для MSP430 (скорее всего это единственный вариант, т.к. вы установили версию CCS только для MSP430). Жмем [Next]. Нечего делать на следующей странице, так что снова жмем [Next]. На последней странице нужно выбрать модель нашего микроконтроллера. Убедитесь что [Output Type] выбран как “Executable”, и выберите MSP430G2XXX в фильтре [Device Variant]. Фильтр позволяет вам выбирать подсемейства MSP430, уменьшая число вариантов, что бы легче было найти свою модель. После фильтрации, найдите и выберите MSP430G2211 в поле [Device Variant]. Остальные опции можно оставить по умолчанию. Напомню, перед тем как продолжить, убедитесь в правильном выборе вашего микроконтроллера, т.к. для каждой модели необходим свой компилятор.

Нажмите [Next], в последний раз, и откроется окно редактирования нового проекта. Проект создает подкаталоги в своей папке, где хранятся все необходимые файлы, для загрузки в микроконтроллер. Для начала нам необходим код программы. Выбираем File → New → Source File и вводим имя исходника с расширением “.c” (CСS будет выдавать предупреждение, пока вы не введете расширение “.c” для файла). Имя описательного характера неплохо для больших проектов с множеством файлов, а для начала имя “main.c” будет хорошим выбором. Нажимаем [Finish] и открывается окно, в котором можно вводить код вашей программы. Введите код мигалки, и не забудьте хорошо откомментировать то, как она работает. Убедитесь, что у вас есть одна пустая строка в конце кода, иначе CСS будет выдавать предупреждение.
Если кто-то знает, как от этого избавиться, дайте мне знать. А пока, просто будьте в курсе этой особенности.

Я изменил размер окна редактирования. Мне нравится, когда у редактора 80 столбцов (стандарт окон терминала). Таким образом, я стараюсь избегать чрезмерно длинных строчек кода. Вы можете настраивать размер окна, как вам угодно. Хорошо, у нас есть код, нужно его откомпилировать. Технически, не обязательно компилировать программу, пока мы не собираемся загружать её в MSP430, но это полезно сделать, т.к. во время компиляции вылезают все наши ошибки. Кнопка [Build Active Project] компилировать текущий проект, справа от [Print] печать, откомпилирует ваш проект. Или можно выбрать в меню Project → Build Active Project. Если вы не наделали орфографических ошибок, ваш код должен откомпилироваться без проблем. Компилятор открывает внизу два новых окна, [Console] консоль, показывает команды компилятора и их результаты, [Problems] проблемы, выдает список ошибок и замечаний. Код из предыдущего урока должен откомпилироваться без ошибок.

Итак, мы убедились, что наш код будет работать, давайте загрузим его в микроконтроллер! Втыкайте ваш LaunchPad в USB. Если драйвера уже установлены, кликните в кнопку [Debug] отладка (она похожа на жука) или, по другому, в меню Target → Debug Active Project. Отладчик меняет окна, убедитесь, что ваш код откомпилирован после последних изменений и проверьте соединение LaunchPad с компьютером. Если питания на плате нету, CCS не сможет ее обнаружить. Если все в порядке, код загрузится в микроконтроллер и появится окно отладчика. Обратите внимание на нижнее окно, там видно размер кода, загруженного в MSP430. Мигалка показывает: Text: 86 bytes Data: 2 bytes. Мигалка, не особо сложная программа, но все-равно можно видеть, как мало места она занимает. Тех 2 Кб места для программ, которые есть в ваших G2211 и G2231 должно хватить для всего, что вы можете с ними сделать. (Ну-ну, ага. – Прим. пер.)

Если вы надеялись увидеть, как весело замигал ваш светодиод, вы будете разочарованы. Отладчик останавливает микроконтроллер в состоянии, сразу после сброса по включению питания (Power Up Reset или еще PUC). В среднем окне, вы можете увидеть подсвеченную строку вашего кода: void main(void) { Это окно, демонстрирует позицию в коде, на которой находится выполнение программы в микроконтроллере. Позже мы изучим возможности этого подхода, а пока просто кликните на зеленую стрелку [Run] пуск, с левой стороны окна отладчика. Это отключит контроль тактового генератора отладчиком, и позволит микроконтроллеру работать в нормальном режиме. Светодиод должен мигать примерно раз в секунду.

Итак, наконец-то вы можете видеть мигающий диод, поздравляю, вы закончили ваш первый проект на MSP430! Тем не менее, прочтите следующий урок. Если вы не можете заставить ваш код работать, отладчик может показать вам место, где вы допустили ошибку. Для выхода из отладчика, нажмите [Terminate All] остановить всё, это иконка рядом с иконкой [Run] пуск.

Оригинал урока на английском: Tutorial 05: Loading the Program

Предыдущий урок этого цикла: Урок 04: Застреваем в цикле
Следующий урок этого цикла: Урок 06: Избавляемся от ошибок

we.easyelectronics.ru

Программирование под MSP430: Лекция №05: Загружаем программу

Примечание: мною было решено внести некоторые изменения в процесс перевода. Теперь я буду не просто переводить лекции, а адаптировать их под нынешние реалии. Нет никакого резона писать о микроконтроллерах и приложениях трёхлетней давности. Поэтому:
Приложение: Code Composer Studio 5.3.0
Микроконтроллер: msp430g2553. Enjoy.

В этой лекции мы поучимся пользоваться приложением от TI, под названием Code Composer Studio. Это IDE(интегрированная среда разработки) основанная на open-source проекте Eclipse.
Eclipse это замечательный инструмент, и вам непременно понравится использовать его для программирования вашего микроконтроллера 🙂
Wiki от TI содержит ссылку на загрузку данного программного обеспечения. Для того чтобы загрузить его, вам потребуется регистрация на TI, но это отнюдь не минус — пользуясь вашим аккаунтом, вы можете получать бесплатные примеры кода прямо от Texas Instruments. Да и скорее всего, вы уже там зарегистрированы, так что в этом особой проблемы не будет.
CCS в данном случае — совершенно бесплатна для вас. При запуске, вам будет предложено несколько вариантов лицензирования этого приложения, среди которых, имеется бесплатный — с ограничением на длину кода. Ограничение это составляет аж 16кб. Но стоит огорчаться, для нашего микроконтроллера это в самый раз 🙂 Так что, вы можете со спокойной совестью пользоваться ограниченной версией CCS абсолютно бесплатно, не испытывая никакого дискомфорта. Даже кряк искать не надо 😉 Впрочем, когда мы приступим к программированию и отладке, вы сами убедитесь в том, насколько малы наши приложения.

После установки CCS — запустите его. Студия спросит вас о том, где бы вы хотели расположить ваше рабочее пространство(воркспейс). Воркспейс это просто напросто директория в которой будут храниться все ваши проекты. Не больше и не меньше. Кстати говоря, позаботьтесь о том, чтобы в пути к дистрибутиву CCS не было кириллицы. Впрочем, вас об этом предупредят. Вы всегда можете изменить расположение вашего рабочего пространства, кликнув в меню ‘File -> Switch Workspace -> …’

Примечание: я использую англоязычную версию CCS в силу того что я понятия не имею, есть ли вообще в миру русскоязычная. Да и знать не хочу, честно говоря. Привыкайте к английскому 😉


Стартовый экран CCS 5.3.0
Для начала, выберите в качестве воркспейса что-нибудь типа ‘Мои документы/MSP430 LaunchPad’
Как только вы закончите, перед вами появится стартовый экран, прямо как на этой картинке. Вы, конечно же, можете сразу же кликнуть на ‘New Project’, но все таки, если вы начинающий — стоит обратить внимание на ролик ‘Getting Started’. Я его, кстати, так и не посмотрел, так как он мне почему-то предложил установить Adobe Flash Player, который у меня и так есть. Поэтому о содержании оного, мне остается лишь догадываться(да и лень вообще-то). Так что, в какой-то степени — вам повезло! Смотрите и наслаждайтесь 🙂 Скорее всего, там вам дадут некоторые базовые понятия о данной IDE. 



Code Composer Studio
Как только вы почувствуете что вы готовы, и вас не смущает новое для вас программное окружение — закройте стартовый экран(вы всегда можете вернуться в него по меню Help->Welcome to CCS). Теперь вы в наедине с IDE. По началу, приложение не блещет разнообразием, выглядит довольно пустовато, согласитесь(честно говоря, скриншот был сделан уже после того как я поработал с IDE, поэтому не знаю как он выглядит изначально, но думаю — пустовато :Р), но не отчаивайтесь, скоро вам вообще места хватать не будет. Ну что же, приступим к созданию нашего первого проекта(Woo-Hoo!). Кликаем на ‘File->New->CC Project’ и введите имя вашего проекта. Не пишите «test» или подобную ерунду, имя программы должно отражать его суть. Кстати говоря, к названиям я предпочитаю добавлять суффикс, который показывал бы, для какой конкретно модели микроконтроллера расчитана данная программа. К примеру для нашей мигалки, это выглядит так: blinky_g2553. В пункте Output File выберите «Executable», остальные пункты подгоните подстать вашему микроконтроллеру, например: Family: MSP430, Variant: MSP430Gxxx Family, MSP430G2553. В пункте Connection обычно уже выставлено то что надо, при условии подключенной платы LaunchPad к вашему компьютеру. Жмём «Finish» и готово!



Исходный код мигалки 😉
Вот и наш редактор кода! Растяните окна так как вам удобно, и введите исходный код нашей мигалки. Ввели? Отлично. Теперь пришло время скомпилировать наш код. Вообще говоря, вовсе не обязательно компилировать вашу программу перед тем как загружать её в микроконтроллер. Но лучше всё таки побороть лень, и сделать это. Зачем? Ну, вам же будет проще, если все возможные ошибки вылезут наружу ДО того как вы приступите к отладке вашего приложения, не так ли?:) Для того чтобы скомпилировать программу, вам следует найти иконку с молотком и нажать на неё. Всё просто. Если вы не допускали ошибок по ходу написания программы, компиляция пройдет как по маслу. Кстати об этом. Вы наверное заметили, что при компиляции программы, внизу CCS появляется два дополнительных окна — «Console» и «Problems» так вот, если вы допустили какие-то ошибки в исходном коде, в окошке «Problems» компилятор на них укажет. Во втором же окне, отображается просто информация о ходе сборки. Ничего важного для нас там, пока что нет. 



Отладка нашей мигалки
Окей, всё хорошо, ошибок нет, код скомпилирован. Хватит дурить, пора заливать код в наш MSP430! Подключите ваш LaunchPad в USB порт. Если при установке CCS драйвера установились корректно и без ошибок, тогда просто кликните на иконку с жуком. Она рядом с молотком 🙂 После нажатия, главное окно CCS полностью поменяется, заполнится всякими пока ещё непонятными окошечками и надписями. Впрочем, некоторые из них уже нам знакомы. Но сейчас не об этом. В общем, если питания поступающего от USB хватает, если драйвера установлены, то все должно пройти без заминки. Если же возникли какие-то проблемы, попробуйте переустановить CCS(или Windows) другого решения проблем в этой ОС я просто не знаю 😉 Ладно, ближе к делу. Обратите внимание на окно с заголовком «Console». Там информация о нашей мигалке:

MSP430: Loading complete. Code Size — Text: 180 bytes Data: 2 bytes.

Это информация о загруженных в микроконтроллер данных. Обратите внимание — всего 182 байта. На MSP430G2553 доступно 16кБ. Подсчитайте, сколько таких мигалок туда влезет 😉

Вот вы нажали на «жучка» и затаив дыхание, с глуповатой улыбкой уставились на ваш LaunchPad. Ждёте что он замигает? Ха — нет. По крайней мере, не сразу. Дело в том, что наш отладчик останавливает выполнение программы сразу же после того как было подано питание(Power Up Reset, аббр.: PUC). В середине нашей CCS мы видим, что строка с кодом 
void main(void) {
выделена другим цветом. Так отображается то место в коде, на котором в данный момент остановлено выполнение программы. Возможно вас это несколько обескуражит, но это КРАЙНЕ полезная вещь. Что это такое и с чем это едят, мы рассмотрим в другой лекции. Сейчас же, все что нам надо, это наконец заставить мигать чёртов светодиод! Сказано — сделано 🙂 Жмём зелёный треугольничек(или F8) и наслаждаемся. Треугольничек отключит режим отладки и передаст управление в руки MSP430. Yay! Наша мигалка работает. Мигать она должна с интервалом что-то около секунды. Кстаати, вот ещё что:
Если ваша мигалка вовсе не мигалка, а просто горящий светодиод, то вы немного ошиблись в коде. Держу пари, что для переменной count вы указали тип int, а не unsigned int как было сказано. В знаковом int’е просто напросто нет такой цифры — 60000, он не сможет до неё досчитать. Поэтому нужен беззнаковый — unsigned int.

Спасибо за внимание 😉

Перевёл и дополнил: Александр Мошкин 
Оригинал статьи: Tutorial 05. Loading the Program 
Следующая лекция: Лекция №06. Отладка приложения
Предыдущая лекция: Лекция №04. Крутимся в цикле

msp430-ru.blogspot.com

Программирование под MSP430: Лекция №02: MSP430. Города и регистры.

Большинство статей, посвященные MSP430, что мне довелось видеть, почти с первых строк рассказывали об архитектуре процессора, адресации памяти, шинах данных и прочих технических штуках, которые, к сожалению, человеку без опыта в области электроники, довольно тяжело понять. В этой статье я попытаюсь объяснить вам азы, необходимые для начала работы с этим семейством микроконтроллеров(далее МК), без всяких заумных вещей типа биполярных соединений и тому подобного. Глубокие технические знания были бы очень полезны в тонкой настройке разрабатываемой системы или в программировании на ассемблере, но и элементарных знаний языка С достаточно, чтобы начать вполне комфортную и продуктивную работу.

Одна из особенностей, которая выделяет микроконтроллеры MSP430 из основной массы, — это фон-Неймановская архитектура: все данные, которыми может оперировать процессор, расположены в одном адресном пространстве. Остальные же микроконтроллеры отличаются в этом плане: их данные могут располагаться в различных адресных пространствах, что повышает эффективность, но изрядно усложняет работу с ними, а нам этого ой как не хочется. Чтобы быстро понять, о чем речь, можно представить себе микроконтроллер как город: в фон-Неймановских городах(как MSP430) все люди живут в одном городе и имеют свой собственный, уникальный адрес. Ну а, к примеру, в Гарвардской архитектуре городов несколько, поэтому адреса могут повторяться. Таким образом, если вы захотите отправить письмо по определенному адресу, сначала вам придется уточнить город.

Память
Адресное пространство MSP430 включает в себя область для хранения непосредственно самой программы, область для хранения данных, необходимых этой программе, оперативную память и прочую важную информацию, которую мы с вами рассмотрим чуть позже. Сегодня же всю вашу неуёмную тягу к знаниям мы будем удовлетворять изучением адресов в памяти, которые называются “регистрами”. Эти адреса как различные коммунальные и социальные службы (такие как почта или ЖКХ) в нашем небольшом MSP430-городке. В нашем же микроконтроллере регистрами контролируются различные функции процессора и периферии. Представьте себе помещение с множеством разных переключателей и кнопочек, от которых зависит включат ли завтра в вашем районе отопление или горячую воду — это и будут наши регистры. Как и любые другие выключатели, они имеют всего лишь два состояния — “включено” и “выключено”, говоря компьютерным языком — 1 и 0. В микроконтроллере же состояние регистров определяет как будет себя вести та или иная периферия, за что будет отвечать та или иная ножка вашего МК, что произойдет при наступлении определенного события, и так далее, и тому подобное. Регистры в MSP430 сгруппированы в 3 секции:
1) Регистр специальных функций (англ: special function registers (SFR)).
(прим. переводчика.: подобные аббревиатуры следует запоминать, или хотя бы записывать, в дальнейшем, они будут использоваться достаточно часто)
2) 8-битные регистры, для различной периферии процессора(для хранения “настроек” периферии которым, достаточно лишь 8 бит)
3) 16-битные регистры(то же самое, только выделяется 16 бит).  
В качестве примера, давайте взглянем на самого маленького представителя семейства MSP430, а именно — на микроконтроллер MSP430G2001. Откройте следующие документы: описание серии x2xx и спецификации G2x01.


Заметьте, что вышеуказанные ссылки могут быть несуществующими, такое случается, если “Texas Instruments” делает обновление документации. Проще всего отыскать эти документы, перейдя на официальный сайт TI и найти блок “Search by Part Number”. Для того, чтобы найти документацию по серии G2x01, достаточно ввести любую маркировку, которая попадает под эту маску, к примеру msp430g2001.


Давайте взглянем на четвертую часть первой главы(Address Space) описания серии x2xx(англ.: family guide), которая иллюстрируют нам карту нашего “городка” семейства x2xx.  Как вы видите, регистры SFR расположены, начиная с адреса 0h и заканчивая Fh (символ h указывает на то, что адрес написан в шестнадцатеричной системе исчисленgия; в десятеричной же они бы выглядели как 0 и 15).  Следующими идут 8-битные регистры; их адреса начинаются с 010h и заканчиваются адресом 0FFh (в десятичной системе: с 16 по 255), затем, с адреса 0100h по 01FFh идут 16-битные регистры. Вы, наверное, заметили огромное пустое место между областями оперативной и флэш памяти(прим.: не путайте flash-память с USB-накопителями или другими внешними накопительными устройствами, в данном случае, флэш-память — это “перепрограммируемая память”). Описание данной серии микроконтроллеров показывает нам те области памяти, которые относятся ко всему семейству x2xx, чтобы увидеть точные значения для какого-либо конкретного микроконтроллера, вам необходимо обратиться к спецификации этого чипа, называемой даташитом(англ.: datasheet — привыкайте к этому названию, везде используется именно оно).

Одиннадцатая страница даташита предоставляет нам карту распределения памяти, которая соответствует всем микроконтроллерам серии G2x01 и G2x11. Взглянув на столбик с G2001, можно увидеть, что сначала идут служебные регистры периферии(SFR, 8-bit, 16-bit)  затем идут 128 бит оперативной памяти. Адресное пространство, начиная с адреса 0201h и заканчивая 10FEh, пустое, после него мы видим 256-бит памяти, именуемые служебной областью памяти(эта область памяти хранит в себе калибрационные данные и прочие важные значения,которые необходимо сохранить, если питание к устройству перестало поступать. Обычно эти данные недоступны для перезаписи, но это не значит,что это невозможно при реальной необходимости, но это отдельная история, заслуживающая отдельной лекции). В итоге мы имеем 512 байт памяти для программного кода и, в довершение всему, память, которая выделена под векторы прерываний(но об этом тоже в другой лекции).

Регистры
Теперь мы с вами видим как выглядит изнутри наш “G2001-городок”, следовательно, нам следовало бы разобраться, как работать с теми самыми “домами с переключателями”, которые мы описали выше. Регистры в микроконтроллере MSP430 — это специальные секции в памяти, с помощью которых он конфигурируется и которые сообщают нам, когда случается что-то важное. Страница номер 10 нашего даташита показывает, какие регистры специальных функций(SFR) доступны в нашем G2001. Как мы видим, у этого устройства есть только четыре регистра спец. функций, расположенных по адресам с 0h по 3h: регистр разрешения прерываний 1 (англ.: Interrupt Enable 1(IE1)), регистр разрешения прерываний 2(IE2), и два регистра флагов прерываний IFR1 и IFR2 (англ.: Interrupt FlaG Register). Каждый адрес указывает на 1 байт в памяти, а в одном байте, как нам известно, — 8 бит. Помните наши “дома с переключателями”? Так вот, каждый бит в регистре выполняет роль одного переключателя. Таким образом, сам регистр является домом, а каждый его бит — переключателем, который имеет два состояния 0(выкл) и 1(вкл). Каждый из этих битов очень важен, состояние каждого из них так или иначе влияет на работу микроконтроллера и его поведение в целом. Страница 10 также показывает нам какие биты в этих регистрах доступны на нашем G2001.

В данном случае, в регистре IE1 нам доступны только 0, 1, 4 и 5 бит, в то время как в IFG1 нам доступны все биты с 0 по 5. В даташите содержится полная информация о том, какое имя носит каждый из этих бит и какую функцию он выполняет. К примеру, нулевой бит в регистре IE1 называется WDTIE — разрешение прерываний сторожевого таймера(англ.: WatchDog Timer Interrupt Enable). По умолчанию этот бит имеет значение 0, но если мы изменим его и установим в него 1, то мы позволим сторожевому таймеру “поднимать” флаг прерывания в регистре IFG1(бит под номером 0, если быть точнее), тем самым вызывая прерывание(как уже говорилось, что такое прерывания мы рассмотрим позже). Проще говоря, этот бит указывает нашему MSP430, может ли сторожевой таймер сигнализировать процессору о том, что нужно что-то сделать, или же он используется в обычном режиме. Тут, наверное, стоило бы пояснить, что такое сторожевой таймер и что есть “обычный” его режим. Сторожевой таймер необходим для того чтобы сбрасывать процессор в то состояние, в котором он был на момент подачи питания. Сбрасывает он его регулярно, с определенным интервалом. Зачем же это нужно? Если во время работы программы происходит какой-то сбой, то сторожевой таймер сбрасывает эту программу, чтобы она снова смогла работать. Разумеется, его можно отключить. Когда мы переводим сторожевой таймер в интервальный режим, то он вместо того, чтобы сбрасывать нашу программу, просто напросто посылает процессору сигнал. Как обрабатывать этот сигнал и что делать процессору при получении этого сигнала — это решение ложится на плечи программиста. Обычно это используется для того, чтобы совершать какие-либо цикличные действия. К примеру, в самом элементарном случае поморгать светодиодом, чем мы с вами вскоре и займемся.

Теперь взглянем на 14 страницу нашего даташита. Эта таблица предоставляет нам всю информацию о существующих периферийных “устройствах”, адреса их регистров и их имена.  Кстати говоря, внизу таблицы расположена информация и о SFR, которые мы не раз упоминали в данной статье.  Таким образом, когда вы захотите использовать какую-либо периферию вашего микроконтроллера, эта таблица будет вашей отправной точкой для того чтобы узнать какие именно “домики с переключателями” вам необходимо посетить, чтобы быть уверенным, что все ваши регистры настроены правильно. Сегодня мы с вами подробнее рассмотрим регистры предназначенные для порта 1(Port P1) и порта 2(Port P2), так как они являются основными элементами которые необходимы для работы с нашим микроконтроллером.

Порты это основные устройства ввода/вывода доступные на микроконтроллере, ввод/вывод производится через ножки(англ.: pin) вашего МК. Распиновку вашего устройства вы можете посмотреть на третьей странице даташита. Под портом обычно подразумевается набор из 8 пинов микроконтроллера. Но пинов у порта может быть и меньше, это бывает, если ножек просто напросто не хватает до полного набора. Распиновка, изображенная в даташите, показывает нам, что G2001 имеет полный набор из 8 ножек для порта 1(c P1.0 по P1.7) и две ножки для порта 2(с P2.6 по P2.7). Каждый регистр каждого порта имеет бит, который соотносится с соответствующей ножкой микроконтроллера. К примеру, P1.4 контролируется 4-м битом каждого регистра, который принадлежит порту 1(P1). Давайте познакомимся поближе с регистрами, которые предлагает нам микроконтроллер.

PxIN
Входной регистр, значения которого находятся в режиме “только для чтения”(англ.: read-only).  Если направление ножки было выбрано как “входящее”(англ.: INput), то значение этого регистра будет сообщать вам, подано ли в данный момент напряжение на эту ножку или же нет. Следует понимать, что чтение значения регистра PxIN возвращает вам данные по всем ножкам соответствующего порта за раз. Не стоит так же забывать и то, что это цифровая технология, поэтому каждый считанный бит может быть только в двух состояниях: 1 или 0. Эти значения показывают нам, какое напряжение подано на ножку: Vss(если значение 0) или же Vcc(если значение 1), значение 0 принимается в том случае, если поданное напряжение ниже 1.8 вольт(Vss < 1.8В), ну а значение 1 принимается в том случае, если поданное напряжение попадает в рамки между 1.8 и 3.6 вольт(1.8В <= Vcc <= 3.6В). Во избежание нанесения ущерба вашему устройству НИКОГДА не пытайтесь напрямую подавать напряжение выше верхнего порога Vcc. Если говорить в двух словах — Vcc это вольтаж, а Vss — земля.

PxOUT
Выходной регистр, доступный для записи. Когда определенный пин вашего микроконтроллера установлен в “режим вывода”(англ.: OUTput), вы можете подавать на него напряжение, просто установив соответствующему биту в этом регистре значение 1. Так же как и в регистре PxIN при значении 0 на ножку подается напряжение с Vss, если 1 — Vcc.

PxDIR
Регистр направления(англ.: DIRection), определяет пин в режим ввода, если в соответствующем бите данного регистра установлено значение 0 и в режим вывода, если 1. В самом начале вашей программы следует указать все направления пинов, которые вы планируете использовать. Разумеется, это не значит, что вы не можете изменить эти значения где-нибудь в середине программы.

PxIE, PxIES, и PxIFG
Следующие три регистра, которые имеются у наших портов: регистр разрешения прерываний(англ.: Interrupt Enable (IE)), контрольный регистр прерываний(англ.: Interrupt Edge Select (IES)) и регистр флагов прерываний(англ.: Interrupt FlaG (IFG)). Мы рассматриваем эти три регистра вместе, так как работа с любым из этих регистров, предполагает работу с двумя оставшимися, они неразрывны друг с другом.  Что такое прерывание? В настоящий момент вам достаточно будет просто представить, что это некое сообщение, посылаемое процессору, при получении которого он приостанавливает все свои дела и начинает выполнять те действия, которые предписаны на выполнение при получении оного. Как только он завершит обработку прерывания, процессор как ни в чем не бывало возвращается к своей предыдущей работе и продолжает выполнение основной программы. Чтобы разрешить определенному пину вашего порта генерировать прерывания, вы просто “поднимаете”(устанавливаете значение 1) соответствующий этой ножке бит в регистре разрешения прерываний(PxIE где x — номер порта). Контрольный регистр прерываний(PxIES) содержит в себе контрольные биты(edge-bits), с которыми сравнивается текущее состояние регистра PxIN. Проще говоря, если у вас есть ножки, которые в регистре PxDIR назначены в input-режим(битам, соответствующим ножкам назначено значение 0), то регистр PxIN сравнивается по битам со всеми значениями регистра PxIES и если случается так, что значения соответствующих битов в этих регистрах имеют разное значение, то следующее, что делает процессор — это проверяет, разрешены ли для этих ножек прерывания — сравнивает с регистром PxIE,- и если прерывания разрешены — генерируется прерывание, а это, в свою очередь, ни что иное как “поднятие” соответствующих битов в регистре PxIFG(регистр флагов прерываний).
Ещё раз вкратце: прерывание для определенной ножки вашего микроконтроллера считается сгенерированным, если в регистре PxIFG поднят флаг(бит принял значение 1) который своим порядковым номером соответствует этой ножке. Биты регистр PxIE определяют, какие вообще ножки вашего микроконтроллера имеют право поднимать эти флаги, если в регистре PxIE бит с порядковым номером 0 имеет значение 0, то эта ножка попросту не имеет доступа к регистру PxIFG, а следовательно, не может генерировать прерывания. В регистре PxIES хранятся контрольные значения. Процессор сравнивая регистры PxIN и PxIES генерирует прерывания для ножек, значения битов которых в этих регистрах разнятся.

В силу того что я не очень хорошо разбираюсь в подобных нюансах, при переводе я допустил несколько грубых ошибок. Особенно это касается регистра PxIES. В комментариях есть более  правильно объяснение того, за что отвечает этот регистр. К сожалению, я пока ещё сам его не понял. Так что, как только все прояснится, обещаю внести поправки в статью. Пока — довольствуемся комментарием 🙂

PxSEL
Если снова взглянуть на третью страницу нашего даташита, где изображена распиновка нашего микроконтроллера, можно заметить, что каждая ножка имеет несколько функций, которые разделены слэшем. Этот регистр выбора(англ.: SELection Register) определяет, какую функцию тот или иной пин будет выполнять. Функция, которую та или иная ножка выполняет по умолчанию, указана первой — так мы можем заметить, что все ножки первого порта(P1) по умолчанию настроены просто на ввод и вывод(I/O — Input/Output), в то время как ножки P2 по умолчанию подключены к кварцевому генератору. Изменение битов в PxSEL поменяет основную функцию соответствующей ножки. Все это мы рассмотрим позднее, сейчас же наша основная задача — научиться использовать стандартные функции, которые предопределены в этом регистре.

PxREN
Регистр включения резисторов(англ.: Resistor ENable register) — очень удобная функция портов. Иногда необходимо вручную подать напряжение или же напротив, прекратить подачу оного. К примеру если вы подключите к вашему микроконтроллеру какую-нибудь кнопку. Регистр включения резисторов предоставляет вам эту возможность. Когда бит, соответствующий вашей ножке в этом регистре “поднят”, подача может регулироваться установкой этого же бита в регистре PxOUT в 1 или 0.

Ну что же, мы рассмотрели некоторые доступные нам “переключатели”, поэтому, чтобы закрепить пройденное, в следующей статье мы рассмотрим как их использовать при написании нашей программы и загрузке её на наше устройство.

Оригинал статьи: Tutorial 02: The MSP430 Township and Registers
Перевод: Александр Мошкин
Коррекция: Алёна Ступникова 

msp430-ru.blogspot.com

MSP430 — учебный курс. Часть 2

Итак, продолжим.

Сегодня мы разберём приведённую на прошлой паре… э-э-э, блин, привычка однако… программу.

Кто желает, может скачать новый IAR (текущая версия набора 5.20, среда разработки Embedded Workbench — 6-й версии), без необходимости заполнения анкеты как на сайте www.iar.com. Самый свежий. При этом, официально бесплатный, правда с ограничением в 4 Кб кода. Для наших уроков это не проблема — данного объёма вполне хватит.
Заходим по ссылке http://focus.ti.com/docs/toolsw/folders/print/iar-kickstart.html и жмём кнопку «Download».
Предупреждение! Размер скачиваемого архива значителен — около 200 Мб!

А пока я жду заказанного MSP430F249, оговорюсь — рассматриваем 149-й (вернее серию 1xx). Моделька помладше версией ядра, но по ногам они 1 к 1 и совместимы снизу вверх. Кстати, оба контроллера — старшие модели в своём классе.

Приведу текст программы ещё раз:


#include "msp430.h"                     ; подключаем заголовочный файл

        NAME    main                    ; имя модуля
        PUBLIC  main                    ; установить видимость модуля из других
                                        
; Определение констант
ArrLn   EQU     16                      ; длина массива

        ; Вектора прерываний
        RSEG    INTVEC
        ORG     RESET_VECTOR           ; вектор сброса
        DC16    init 

        RSEG    CSTACK                  ; объявление сегмента стека

        RSEG    CODE                    ; объявление сегмента кода

init:   
        MOV     #SFE(CSTACK), SP        ; инициализация регистра стека

main:                                   ; начало основной части
        MOV.W   #WDTPW+WDTHOLD,&WDTCTL  ; запрет сторожевого таймера
        
SortMain:
        ; Переписать из ПЗУ в ОЗУ массив данных
        mov     #ArrLn, R4              ; инициализируем счётчик количества данных
        mov     #RamArr, R5             ; установим R5 как указатель на данные в ОЗУ
        mov     #RomArr, R6             ; установим R6 как указатель на данные в ПЗУ
        
MoveRomToRam:
        mov     @R6+, 0(R5)             ; копирование слова
        add     #2, R5                  ; продвинем указатель
        dec     R4                      ; уменьшим счётчик
        jnz     MoveRomToRam            ; если не ноль, то повторим
   
BasicCycle:
        JMP $                           ; jump to current location '$'

        
;       определение данных в ОЗУ
        RSEG    DATA16_N
RamArr:
        DS16    ArrLn

;       определение данных в ПЗУ
        RSEG    DATA16_C
RomArr:
        DC16    101, 11, 25, 657, 567, 217, 5732, 896, 123, 5467, 12, 65, 2345, 23, 98, 2398


        END

Первые три строки — как и в прошлом уроке.

Следом определяем константу длины массива в элементах, чтобы потом пользоваться символьным именем вместо изменения конкретной цифры в куче мест. Да и удобнее сделать так, если вдруг прийдется поменять тип хранимых элементов. То же самое можно сделать как «#define ArrLn 16«, если вам стиль C больше по душе.


        ; Вектора прерываний
        RSEG    INTVEC
        ORG     RESET_VECTOR           ; вектор сброса
        DC16    init 

Здесь мы определяем таблицу векторов прерываний. Я предпочитаю делать именно так, а не как в заготовке проекта (первый пример на скриншоте из первого урока). «RSEG INTVEC» определяет сегмент векторов. Вторая строка — адрес вектора сброса. Здесь будьте внимательны — константа RESET_VECTOR (как и другие вектора) исчисляется от начала сегмента. Т.е., нельзя писать вторую строку без первой — компилятор вас не поймёт и разместит вектор по адресу 001Eh вместо положенных FFFEh. Адрес начала таблицы FFE0h и, соответственно, RESET_VECTOR от него в 30 байтах.
Т.к. разрядность контроллера 16 бит, то адреса тоже 16-ти разрядные, посему каждый вектор занимает 2 байта. А вот адресация памяти побайтная, а не пословная (как адресация памяти программ в AVR). Обратите внимание на это.
Как уже было сказано, в вектор помещается не команда перехода к обработчику, а непосредственно его адрес. Делается это третьей строкой «DC16 init«, что означает «разместить по текущему адресу 16-ти битную константу значения адреса, определённого меткой init». Данная метка располагается в начале кода программы и значение её адреса вычисляется на этапе связывания (линковки). Как заметили читатели, DC16 означает «Define Constant 16 bit», директива аналогична DW.
Вообще, рекомендую почитать заголовочные файлы. Расположены они в каталоге «C:\Program Files\IAR Systems\Embedded Workbench Evaluation 4.0\430\inc\». Номер версии может отличаться от моего, тогда нужно подправить путь. «msp430.h» не содержит ничего существенного, но ссылается на заловочные файлы для конкретных серий, например «msp430x14x.h», как у меня.

Далее объявление сегмента стека «RSEG CSTACK«. Стек располагается в конце ОЗУ и растёт вверх.
После него объявление сегмента кода программы «RSEG CODE«. С этого места и начинается наша программа. По умолчанию, сегмент кода начинается с начала ПЗУ, если нет сегментов данных в нём. Если есть — то после них.
Кстати, RSEG означает «перемещаемый сегмент» (relocatable).

Команда

MOV     #SFE(CSTACK), SP
заносит адрес стека в регистр-указатель. Директива SFE служит для вычисления адреса конца сегмента (любого).
Внимание, запоминаем раз и навсегда! Значок # служит для определения непосредственно значения выражения. В противном случае оно считается адресом памяти, откуда надо взять данные. Исключение — команды переходов типа jmp, в них подставляются выражения без диеза (в команде call диез нужен!). В следующей части рассмотрим режимы адресации подробнее.
Также запомните — порядок операндов прямой, т.е. «откуда в куда».

Следующая команда

MOV.W   #WDTPW+WDTHOLD,&WDTCTL
запрещает сторожевой таймер, записывая в его управляющий регистр предусмотренную для этого комбинацию бит.

Перед тем как рассматривать код дальше, обратим внимание на конец текста программы. Там располагаются определения данных в ОЗУ и ПЗУ.


       RSEG    DATA16_N
RamArr:
       DS16    ArrLn
Здесь определяются данные в ОЗУ. Директивой «RSEG DATA16_N» определяем сегмент неинициализируемых 16-ти разрядных данных для статических и глобальных переменных. По умолчанию располагаются в начале ОЗУ. Директивой «DS16 ArrLn» определяем массив 16-ти разрядных слов в количестве ArrLn. Метка RamArr нужна для обращения к этим данным с помощью символьного имени без необходимости указания абсолютного адреса (чтобы не высчитывать его вручную, да и менять состав данных так легче и меньше будет семантических ошибок).

        RSEG    DATA16_C
RomArr:
        DC16    101, 11, 25, 657, 567, 217, 5732, 896, 123, 5467, 12, 65, 2345, 23, 98, 2398
Здесь мы определяем данные в ПЗУ. Директивой «RSEG DATA16_С» определяем сегмент постоянных 16-ти разрядных данных. Обратите внимание на разницу в именых сегментов. По умолчанию располагаются в начале ПЗУ. Директивой «DC16 ArrLn» определяем массив 16-ти разрядных слов со значениями, указанными в перечислении следом. При компиляции эти значения будут занесены в ПЗУ. Ну и не забываем метку.

Вернемся к коду.


SortMain:
        mov     #ArrLn, R4        
        mov     #RamArr, R5             
        mov     #RomArr, R6             

Первым действием заносим константу в регистр R4, он будет счётчиком. Диез не забываем, иначе получим не то, что ожидали.
Вторая команда заносит значение адреса метки RamArr в R5, третья — значение адреса метки RomArr в R6.
Если не поставим диез, получим значения из ячеек памяти по этим адресам — можете поэкспериментировать.

Теперь перенесём данные из ПЗУ в ОЗУ.


MoveRomToRam:
        mov     @R6+, 0(R5)             
        add     #2, R5                  
        dec     R4                      
        jnz     MoveRomToRam            

Первая команда перемещает данные из ячейки памяти, адрес которой в R6 в ячейку, адрес которой равен «R5 + (смещение, равное нулю)«. Символ @ указывает на косвенную адресацию. При этом, содержимое R6 увеличивается на два, т.к. команда в таком виде обращается к словам, а не к байтам. К сожалению, нельзя написать «mov @R6+, @R5+» и даже «mov @R6+, @R5«, т.к. это не поддерживается. Поэтому следующей командой мы вручную увеличиваем содержимое R5 на 2. После чего декрементируем счётчик и последней командой проверяем его на равенство нулю. Если не равен нулю, то идем опять за следующим значением, т.е. по метке MoveRomToRam. Если равен — выходим на следующую команду.

Последней командой

jmp $
зацикливаем код ($ — ссылка на счётчик команд, т.е. на текущее положение), дабы не улететь в сияющие чистотой дали пустого FLASH’а.

На следующей… паре, мы рассмотрим режимы адресации и структуру памяти, а пока вам для затравки полная версия программы сортировки.
Ну а я поехал кататься на свежекупленном Т-34-85 :-), бо глаза от буковок разбегаются, а мозг требует засадить бронебойным кому-нибудь в боеукладку. До завтра!


#include "msp430.h"                     ; #define controlled include file

        NAME    main                    ; module name

        PUBLIC  main                    ; make the main label vissible
                                        ; outside this module
; Constant definition
ArrLn	EQU	16



	ORG     0FFFEh
        DC16    init                    ; set reset vector to 'init' label

        RSEG    CSTACK                  ; pre-declaration of segment
        RSEG    CODE                    ; place program in 'CODE' segment

init:   MOV     #SFE(CSTACK), SP        ; set up stack

main:                                   ; main program
        MOV.W   #WDTPW+WDTHOLD,&WDTCTL  ; Stop watchdog timer
        
SortMain:
        ; Переписать из ПЗУ в ОЗУ массив данных
        mov	#16, R4
	mov	#RamArr, R5
	mov	#RomArr, R6
	
MoveRomToRam:
	mov	@R6+, 0(R5)
	add	#2, R5
	dec	R4
	jnz	MoveRomToRam
        
SortingInit:
	mov	#(ArrLn-1), R4
	mov	#RamArr, R6
Sorting:
	mov	R4, R5
	mov	R6, R7
Sort1:
	add	#2, R7
	cmp	0(R6), 0(R7)
	jge	Sort1NonSwap
	mov	0(R6), R8
	mov	0(R7), 0(R6)
	mov	R8, 0(R7)
Sort1NonSwap:
	dec	R5
	jnz	Sort1
	add	#2, R6
	dec	R4
	jnz	Sorting
	
	
	
BasicCycle:
	JMP $                           ; jump to current location '$'

	
;	RAM definition
	RSEG	DATA16_N
RamArr:
	DS16	ArrLn

;	ROM definition
	RSEG	DATA16_C
RomArr:
	DC16	101, 11, 25, 657, 567, 217, 5732, 896, 123, 5467, 12, 65, 2345, 23, 98, 2398


        END

we.easyelectronics.ru

учебный курс. / MSP430 / Сообщество EasyElectronics.ru

Добрый день всем!

Позвольте представить вам учебный курс по микроконтроллерам MSP430.

Хочу сразу предупредить — данный тип МК несколько тяжеловат для рядового пользователя. Его используют в основном профессиональные разработчики, но… Я хочу сделать его доступным для всех. Так, что смотрим и не боимся.
Да, и ещё — традиционно я тяготею к ассемблерным типам языков, так что начнём с них. Потом будет и С.

Как уже говорил глубокоуважаемый _YS_, данный тип контроллеров построен по Фон-Неймановской архитектуре, т.е. имеет одну адресную ось. Деления на память программ и данных нет, просто они располагаются по разным адресам. Чуть позже приведу разбивку.
Мануалы пока читать не будем, просто покажу основное.
Контроллер 16-ти разрядный, в составе ядра есть 16 регистров, четыре из которых специального назначения (R0 или PC — счетчик команд, R1 или SP — указатель стека, R2 или SR — регистр состояния, R3 или CG — генератор констант). Остальные (R4-R15) доступны как регистры общего назначения. Есть одна отличная вещь — любой регистр может быть указателем.
Пока сведений достаточно.

С чего начать? Со среды программирования, ибо первые шаги можно делать не имея аппаратуры.

Внимание! Кто захочет начать с аппаратуры — запомните! Контроллер питается от напряжения 3,3 вольта, 5 вольт для него смертельны! Будьте осторожны.

Итак, среда разработки. Во всём мире профессионалы пользуются программами фирмы IAR Systems — www.iar.com.
Не будем изобретать велосипед, последуем их рекомендациям. С официального сайта можно скачать 30-дневную бесплатную версию. Заморочка в том, что прийдётся заполнить длинную форму личных данных. Кто не боится — вперёд!

После установки и запуска мы видим (у меня 4-я версия, текущая на официальном сайте — 5-я, но отличий немного):

Посмотреть на Яндекс.Фотках

Жмём кнопку «Создать новый проект в текущем рабочем пространстве» («Create new project in current workspace»).
Смотрим на окошко и выбираем «asm/asm».

Посмотреть на Яндекс.Фотках

Нажимаем «Ok» сохраняем файл проекта в нужное нам место. Рекомендую, каждый проект сохранять в отдельный каталог.

Получаем следующее:

Посмотреть на Яндекс.Фотках

Комментирую полученный код.


#include "msp430.h"

Ну тут всё ясно, подключаем заголовочный файл.

        NAME    main                    ; module name

        PUBLIC  main                    ; make the main label vissible
                                        ; outside this module

Это стандартное объявление имени модуля и его видимости из других модулей.

        ORG     0FFFEh
        DC16    init                    ; set reset vector to 'init' label

Тут мы объявляем вектор перехода по сигналу «Reset». Я делаю это несколько иначе, чуть ниже покажу как.
У MSP430 вектора прерываний располагаются в конце памяти — от адреса FFFFh и вниз. Для серии F1xxx и F1xx их 16 штук. Да, и ещё существенное отличие — в вектор заносится адрес, а не команда перехода! Т.е., в данном случае, адрес метки «init».

        RSEG    CSTACK                  ; pre-declaration of segment
        RSEG    CODE                    ; place program in 'CODE' segment

Тут объявляем сегмент стека и кода.
Вот собственно с этого и начинается программа.

init:   MOV     #SFE(CSTACK), SP        ; set up stack

Вот она метка «init», её адрес компилятор потом подставит в вектор сброса.
Первая команда — инициализация стека. Директива SFE вычисляет конец сегмента. А # нужен, чтобы подставлять вычисленное значение, а не рассматривать его как адрес. К примеру:

mov   #1, R1 - поместить 1 в R1,
а
mov   1, R1 - поместить значение из ячейки памяти с адресом 1 в R1

Вот такие хитрости.
Идём далее.
Команда «nop» у нас просто для задержки.
А вот это важная вещь:

        MOV.W   #WDTPW+WDTHOLD,&WDTCTL  ; Stop watchdog timer

Дело в том, что по умолчанию у MSP430 включен сторожевой таймер. Чтобы не было неожиданностей, выключаем его данной командой.
Да, и обратите внимание: все команды пишутся немного не так как у AVR, x51 или x86 — источник сначала, затем приёмник.

        JMP $                           ; jump to current location '$'
                                        ; (endless loop)

Это прыжок «сам на себя». Просто, чтобы создать замкнутый цикл.

Ну и не забываем «END» в конце программы, также как и у PIC в MPLAB. После этого волшебного слова программа заканчивается.

Что сейчас делает наша программа? Почти ничего. Давайте наполним её смыслом. А в качестве примера сделаем сортировку случайных чисел.
Задача следующая:
1. Имеем данные в ПЗУ (набор из 16 случайных чисел).
2. Переместим данные из ПЗУ в ОЗУ.
3. Отсортируем данные в ОЗУ.

Для начала настроим проект.
Выберем тип контроллера. Открываем меню «Projects->Options»:

Посмотреть на Яндекс.Фотках

Появится вот такое окошко, где мы и выберем тип контроллера.

Посмотреть на Яндекс.Фотках

Далее выберем тип отладчика:

Посмотреть на Яндекс.Фотках
Счастливые владельцы аппаратного эмулятора могут выбрать «FET Debugger», ну а нам пока сойдет и «Simulator».

Для начала настроек достаточно. Жмём «Ok».

Далее, вставляем вместо всего в окошке текста следующий код (пока без самой сортировки):


#include "msp430.h"                     ; подключаем заголовочный файл

        NAME    main                    ; имя модуля
        PUBLIC  main                    ; установить видимость модуля из других
                                        
; Определение констант
ArrLn	EQU	16                      ; длина массива

        ; Вектора прерываний
        RSEG	INTVEC
        ORG     RESET_VECTOR           ; вектор сброса
        DC16    init 

        RSEG    CSTACK                  ; объявление сегмента стека

        RSEG    CODE                    ; объявление сегмента кода

init:   MOV     #SFE(CSTACK), SP        ; инициализация регистра стека

main:                                   ; начало основной части
        MOV.W   #WDTPW+WDTHOLD,&WDTCTL  ; запрет сторожевого таймера
        
SortMain:
        ; Переписать из ПЗУ в ОЗУ массив данных
        mov	#ArrLn, R4              ; инициализируем счётчик количества данных
	mov	#RamArr, R5             ; установим R5 как указатель на данные в ОЗУ
	mov	#RomArr, R6             ; установим R6 как указатель на данные в ПЗУ
	
MoveRomToRam:
	mov	@R6+, 0(R5)             ; копирование слова
	add	#2, R5                  ; продвинем указатель
	dec	R4                      ; уменьшим счётчик
	jnz	MoveRomToRam            ; если не ноль, то повторим
   
BasicCycle:
	JMP $                           ; jump to current location '$'

	
;	определение данных в ОЗУ
	RSEG	DATA16_N
RamArr:
	DS16	ArrLn

;	определение данных в ПЗУ
	RSEG	DATA16_C
RomArr:
	DC16	101, 11, 25, 657, 567, 217, 5732, 896, 123, 5467, 12, 65, 2345, 23, 98, 2398


        END

Разберём по частям. Но для начала научимся запускать программу на выполнение.
Скомпилируем проект — пункт меню «Project -> Make» или значок на панели инструментов:

Появится окошко «Messages», в котором отражен процесс компиляции. В случае успеха (а данный текст должен нормально скомпилироваться) появится сообщение об этом.

Далее жмем «Project -> Debug» или кнопку:

Должен запуститься собственно отладчик. IAR поддерживает два набора окон — раздельно для редактирования и отладки.
Закроем лишнее. Структура проекта при отладке не нужна, окно «Disassembly» используется редко, да и «Messages» не нужно.
А вот регистры и память хотелось бы видеть. Жмём «View -> Registers» и два раза «View -> Memory». Перетаскиваем окошки в нужные углы и получаем картинку (на мой вкус, можете сделать по своему):

Посмотреть на Яндекс.Фотках
В окошках «Memory» выбираем типы памяти «RAM» и «Flash», так будет удобнее просматривать. Также, в каждом окшке памяти щёлкаем правой кнопкой и выбираем из контекстного меню «2x Units» (для просмотра 16-ти разрядных данных) и «Data Coverage -> Enable» (будет показано обращение к текущим ячейкам — удобно).
К отладке готовы!

С помошью кнопки F10 (не входить в подпрограммы) или F11 (входить в подпрограммы) проходим по шагам и любуемся результатом. Техника нам подвласна!

На сегодня всё, а завтра продолжим разбор программы.

Просьба — прокомментируйте. Понравилось, не понравилось, не слишком ли тяжело для понимания, что хотелось бы ещё в этом уроке, а также что хочется на будущие. Жду откликов.
Спасибо за внимание.

we.easyelectronics.ru

Добавить комментарий

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