Многие микроконтроллерные платформы поддерживают инструменты для создания начальной конфиграции периферийных устройств и портов ввода/вывода. Обычно это графическая среда, в которой задаются параметры работы кристалла и может быть сгенерирован исходный код — заготовка будущего проекта.

При использовании такого конфигуратора вы существенно упрощаете начальный этап программирования, но делаете это не в ущерб пониманию процессов, происходящих на кристалле [камень в огород готовых библиотек].
Ниже приведен пример использования конфигуратора для микроконтроллера C8051F930 от Silicon Labs. Будем управлять яркостью светодиода с потенциомера, написав руками всего две строчки кода. Just for fun, конечно.

Исходные данные


Все программные средства разработки для микроконтроллеров Silicon Labs доступны в составе программной платформы Simplicity Studio. Платформа распространяется бесплатно и содержит IDE, документацию, массу примеров программ, а также дополнительные утилиты вроде профайлера энергопотребления и конфигуратора. В этом примере будут использоваться конфигуратор и среда разработки.
В качестве аппаратной платформы послужит отладочная плата C8051F930-TB, так как на ней установлены потенциометр и светодиод, а микроконтроллер C8051F930 имеет необходимые блоки АЦП и ШИМ. В общем, к плате предъявляется нехитрый набор требований, под который подходит множество средств отладки. Но C8051F930-TB таки была под рукой :)

Шаг 1. Подготовка

Подготовка заключается в установке и запуске Simplicity Studio на компьютере и включении отладочной платы. Плата запитывается от батареи или от сети и, за неимением встроенного отладчика, подключается к компьютеру через программатор DEBUGADPTR1-USB.

image

После корректного подключения плата детектируется средой, и все инструменты для 8-разрядных кристаллов становятся доступны.

image

Шаг 2. Создание проекта

Для известной отладочной платы диалог создания нового проекта появляется сразу после нажатия на иконку конфигуратора. Мастер создания проекта не содержит никаких необычных элементов, только выбор целевого контроллера, названия и расположения проекта и т.п.
Интерфейс самого конфигуратора состоит из трех основных частей:
  • Конфигуратор периферийных устройств
  • Конфигуратор портов ввода/вывода
  • Граф состояний микроконтроллера

image

Шаг 3. Настройка периферии

Конфигуратор периферийных устройств представляет собой список доступных на выбранном кристалле периферийных модулей и функций ядра. Для реализуемой задачи понадобится:
  1. Активировать и настроить АЦП чтобы обрабатывать сигнал с потенциометра;
  2. Активировать и настроить таймер чтобы инициировать преобразование на АЦП с нужной частотой;
  3. Активировать и настроить блок PCA (т.н. программируемый массив счетчиков), на котором в микроконтроллерах C8051Fxxx доступен аппаратный ШИМ-генератор.

Но начнем с включения тактового генератора контроллера. Достаточно поставить галочку на Clock Conrol — встроенный генератор частоты на 25 МГц с делителем на 8 нас вполне устраивает, поэтому доступные в окне справа настройки блока оставляем с параметрами по умолчанию.

image

После настройки тактирования переходим к таймерам-счетчикам. Опрашивать АЦП будем раз в 1 мс, поэтому настраиваем TIMER2 на переполнение с соответствующей частотой: ставим галочку на блоке TIMER2, указываем частоту в микросекундах, задаем Start в поле Run Control чтобы работа таймера начиналась автоматически.

image

При активации TIMER2 модуль Timer Setup загорелся красным цветом. Timer Setup должен быть активирован для работы таймеров/счетчиков, ставим галочку.

image

По переполнению таймера будет начинаться преобразование на блоке АЦП. Настройка АЦП включает разрешение работы блока, указание события для старта работы, указание линии ввода/вывода для приема измеряемого сигнала и выбор 8-битного режима преобразования без усиления.

image

Опорное напряжение для АЦП указывается в отдельном блоке Voltage Reference. В соответствующем пункте указываем напряжение питания платы.

image

Итак, при корректном выполнении описанных настроек мы получим работающий кристалл, на котором раз в миллисекунду значение в регистре результата АЦП обновляется в соответствии с положением колесика потенциометра. Чтобы использовать это значение для формирования ШИМ-сигнала необходимо, кроме настройки блока ШИМ, разрешить прерывание от АЦП и настроить обработчик этого прерывания (копирование значения из регистра результата АЦП в регистр данных блока ШИМ). Средствами утилиты Configurator можно только настроить контроллер прерываний: активируем блок Interrupts и прерывание от ADC0, разрешаем все прерывания.

image

Осталось настроить блок PCA на генерацию ШИМ-сигнала. Выбираем нужный режим на Channel0 и задаем автоматический (т.е. сразу после включения или reset'а) старт работы.

image

Шаг 4. Настройка портов ввода/вывода

Режим работы контроллера создан. Переходим на соседнюю вкладку чтобы настроить порты ввода/вывода — понадобится определить вход АЦП и выход ШИМ в соответствии с топологией платы.

Линия P0.6, подключенная к потенциометру, была указана в качестве входа для сигнала ещё при настройке ADC0. Она отмечена на распиновке кристалла. Справа, в окне настройки режима работы выбранной «ножки», два красных крестика недвусмысленно намекают что нужно поправить два параметра.

image

Режим Open Drain не подходит для аналогового входа, меняем его на Analog I/O. Параметр Skip относится к CROSSBAR'у — цифровому коммутатору, который устанавливает связи типа «периферийный модуль -> порты ввода/вывода» в микроконтроллерах C8051Fxxx. Поскольку линия P0.6 является входом микроконтроллера, в CROSSBAR'е она не должна учитываться. Выбираем Skipped.

Переходим к настройке выхода для ШИМ-сигнала — нулевой канал блока PCA должен быть выведен на линию P1.6, к желтому светодиоду. Такая связь как раз задается через CROSSBAR. Разрешаем его работу.

image

Появилось меню настройки CROSSBAR'а. Ставим галочку на нулевом канале PCA, ШИМ автоматически оказалась на линии P0.0.

image

ШИМ нужно «передвинуть» на P1.6, а для P1.6 указать режим работы Push-Pull Output вместо Open Dain.

image

Шаг 5. Генерация и дополнение исходного кода

Генерация и обновление исходного кода из заданной конфигурации происходит при сохранении проекта или по команде Generate Source, доступной из меню по нажатию правой кнопки мыши. Исходный код нужно дополнить обработчиком прерывания, причем шаблон обработчика создан автоматически благодаря разрешению прерывания от АЦП.

image

Пишем те самые две строчки кода: снимаем флаг прерывания по окончанию преобразования, копируем содержимое регистра данных АЦП в регистр ШИМ.

ADC0CN_ADINT = 0;
PCA0CPH0 = (U8) (ADC0 >> 2);

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

Шаг 6. Компиляция, запуск

Проект создан, остались сборка, компиляция и программирование кристалла.
Результат работы — на видео.



Использованный ресурс

Комментарии (13)


  1. Eddy_Em
    01.07.2015 17:16
    -1

    Жесть, до чего докатились!
    Представляю себе, как выглядит автогенерированный код. Поди-ка поправь в нем что-нибудь…


    1. uuuulala
      01.07.2015 17:35
      +2

      А вы не представляйте, вы посмотрите.
      Там разграничены области, которые обновляются конфигуратором, и области для user code. Всё что между знаков $ перезаписывается автоматически.

      Часть функции инициализации АЦП
      extern void ADC_0_enter_DefaultMode_from_RESET(void) {
      	// $[ADC0MX - ADC0 Multiplexer Selection]
      	/*
      	// ADC0MX (AMUX0 Positive Input Selection) = ADC0P6 (Select channel
      	//     ADC0.6.)
      	*/
      	ADC0MX = ADC0MX_ADC0MX__ADC0P6;
      	// [ADC0MX - ADC0 Multiplexer Selection]$
      
      
      	// $[ADC0CF - ADC0 Configuration]
      	/*
      	// AD8BE (8-Bit Mode Enable) = 8_BIT (ADC0 operates in 8-bit mode.)
      	// ADGN (Gain Control) = GAIN_1 (The on-chip PGA gain is 1.)
      	// ADSC (SAR Clock Divider) = 0x19
      	// ADTM (Track Mode) = TRACK_NORMAL (Normal Track Mode. When ADC0 is
      	//     enabled, conversion begins immediately following the start-of-
      	//     conversion signal.)
      	*/
      	ADC0CF = ADC0CF_AD8BE__8_BIT | ADC0CF_ADGN__GAIN_1 | (0x19 << ADC0CF_ADSC__SHIFT)
      		 | ADC0CF_ADTM__TRACK_NORMAL;
      	// [ADC0CF - ADC0 Configuration]$
      
      
      	// $[ADC0TK - ADC0 Burst Mode Track Time]
      	// [ADC0TK - ADC0 Burst Mode Track Time]$
      
      
      	// $[ADC0PWR - ADC0 Power Control]
      	// [ADC0PWR - ADC0 Power Control]$
      
      ...
      


      1. Amomum
        01.07.2015 20:12
        +3

        Каждый раз, когда я вижу подобное разделение, у меня в голове голос робота говорит: «Че-ло-век, пи-ши код сю-да».


      1. DZhon
        01.07.2015 20:26
        +4

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


    1. Keroro
      02.07.2015 06:46

      Т.е. всё же это продвинутый графический инициализатор, который сейчас во многих платформах есть, или реально визуальный ЯП, типа «algorithm builder» или «дракон»?


      1. uuuulala
        02.07.2015 09:13
        +2

        Это инициализатор кристалла, ничего революционного, но весьма удобно. Позволю себе самоцитату:

        Многие микроконтроллерные платформы поддерживают инструменты для создания начальной конфиграции периферийных устройств и портов ввода/вывода. Обычно это ...

        Т.е. речь о автоматизации создания «статичных» режимов работы, а не полноценных алгоритмов.


        1. Keroro
          02.07.2015 09:26

          Ясно, меня смутило слово «программироваине».
          Вот кстати, если кому интересно, подобный инициализатор для PIC-ов:
          puu.sh/iKfw6/3f3185d837.png


          1. grossws
            02.07.2015 13:12

            И, в каком-то виде для STM32Fxxx/STM32Lxxx — STM32CubeMX. Как минимум, настройка системы тактирования там была. Настройка IO, скорее всего, тоже.


  1. ignat99
    01.07.2015 20:35
    +1

    Да всё к тому идёт что даташиты будут в специальном формате поступать на автогенератор кода системного драйвера/программы.


    1. uuuulala
      01.07.2015 23:57
      +1

      Ага, главное чтобы errata вовремя подгружались :)


  1. rgulomov
    02.07.2015 23:31

    Порог вхождения в программирование микроконтроллеров надо снижать и статьи подобные этой дают надежду неподготовленному читателю. Увы, без теоретических знаний добиться понимания будет сложно, использование автогенератора может только усложнить задачу для тех, кто хочет заниматься данным вопросом всерьез.


    1. uuuulala
      03.07.2015 12:52

      Ну это же не Arduinoвские analogRead(), а интерфейс, позволяющий вместо поиска в datasheet регистров Timer 2 Reload High и Low Byte набрать в поле Timer Overflow 1000 мс и, главное, получить

      	// $[TMR2RLH - Timer 2 Reload High Byte]
      	/*
      	// TMR2RLH (Timer 2 Reload High Byte) = 0xFF
      	*/
      	TMR2RLH = (0xFF << TMR2RLH_TMR2RLH__SHIFT);
      	// [TMR2RLH - Timer 2 Reload High Byte]$
      
      	// $[TMR2RLL - Timer 2 Reload Low Byte]
      	/*
      	// TMR2RLL (Timer 2 Reload Low Byte) = 0x30
      	*/
      	TMR2RLL = (0x30 << TMR2RLL_TMR2RLL__SHIFT);
      	// [TMR2RLL - Timer 2 Reload Low Byte]$
      


      Я бы вообще не говорила что конфигуратор — инструмент, предназначенный для новичков. Это инструмент, помогающий специалистам любого класса упросить ту часть работы, которую упрощать можно и нужно. Это как использовать Ctrl-F вместо пролистывания 500-страничного pdf.


      1. uuuulala
        03.07.2015 12:53

        Наверное было не совсем правильно разбирать в статье почти полностью автоматически созданное приложение. Это наталкивает на мысль, что программирование заключается в тыканьи мышкой, в реальности же работа инженера начинается только после нажатия «Genarate Source».


  1. Eddy_Em
    01.07.2015 17:16
    -1

    Жесть, до чего докатились!
    Представляю себе, как выглядит автогенерированный код. Поди-ка поправь в нем что-нибудь…


    1. uuuulala Автор
      01.07.2015 17:35
      +2

      А вы не представляйте, вы посмотрите.
      Там разграничены области, которые обновляются конфигуратором, и области для user code. Всё что между знаков $ перезаписывается автоматически.

      Часть функции инициализации АЦП
      extern void ADC_0_enter_DefaultMode_from_RESET(void) {
      	// $[ADC0MX - ADC0 Multiplexer Selection]
      	/*
      	// ADC0MX (AMUX0 Positive Input Selection) = ADC0P6 (Select channel
      	//     ADC0.6.)
      	*/
      	ADC0MX = ADC0MX_ADC0MX__ADC0P6;
      	// [ADC0MX - ADC0 Multiplexer Selection]$
      
      
      	// $[ADC0CF - ADC0 Configuration]
      	/*
      	// AD8BE (8-Bit Mode Enable) = 8_BIT (ADC0 operates in 8-bit mode.)
      	// ADGN (Gain Control) = GAIN_1 (The on-chip PGA gain is 1.)
      	// ADSC (SAR Clock Divider) = 0x19
      	// ADTM (Track Mode) = TRACK_NORMAL (Normal Track Mode. When ADC0 is
      	//     enabled, conversion begins immediately following the start-of-
      	//     conversion signal.)
      	*/
      	ADC0CF = ADC0CF_AD8BE__8_BIT | ADC0CF_ADGN__GAIN_1 | (0x19 << ADC0CF_ADSC__SHIFT)
      		 | ADC0CF_ADTM__TRACK_NORMAL;
      	// [ADC0CF - ADC0 Configuration]$
      
      
      	// $[ADC0TK - ADC0 Burst Mode Track Time]
      	// [ADC0TK - ADC0 Burst Mode Track Time]$
      
      
      	// $[ADC0PWR - ADC0 Power Control]
      	// [ADC0PWR - ADC0 Power Control]$
      
      ...
      


      1. Amomum
        01.07.2015 20:12
        +3

        Каждый раз, когда я вижу подобное разделение, у меня в голове голос робота говорит: «Че-ло-век, пи-ши код сю-да».


      1. DZhon
        01.07.2015 20:26
        +4

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


    1. Keroro
      02.07.2015 06:46

      Т.е. всё же это продвинутый графический инициализатор, который сейчас во многих платформах есть, или реально визуальный ЯП, типа «algorithm builder» или «дракон»?


      1. uuuulala Автор
        02.07.2015 09:13
        +2

        Это инициализатор кристалла, ничего революционного, но весьма удобно. Позволю себе самоцитату:

        Многие микроконтроллерные платформы поддерживают инструменты для создания начальной конфиграции периферийных устройств и портов ввода/вывода. Обычно это ...

        Т.е. речь о автоматизации создания «статичных» режимов работы, а не полноценных алгоритмов.


        1. Keroro
          02.07.2015 09:26

          Ясно, меня смутило слово «программироваине».
          Вот кстати, если кому интересно, подобный инициализатор для PIC-ов:
          puu.sh/iKfw6/3f3185d837.png


          1. grossws
            02.07.2015 13:12

            И, в каком-то виде для STM32Fxxx/STM32Lxxx — STM32CubeMX. Как минимум, настройка системы тактирования там была. Настройка IO, скорее всего, тоже.


  1. ignat99
    01.07.2015 20:35
    +1

    Да всё к тому идёт что даташиты будут в специальном формате поступать на автогенератор кода системного драйвера/программы.


    1. uuuulala Автор
      01.07.2015 23:57
      +1

      Ага, главное чтобы errata вовремя подгружались :)


  1. rgulomov
    02.07.2015 23:31

    Порог вхождения в программирование микроконтроллеров надо снижать и статьи подобные этой дают надежду неподготовленному читателю. Увы, без теоретических знаний добиться понимания будет сложно, использование автогенератора может только усложнить задачу для тех, кто хочет заниматься данным вопросом всерьез.


    1. uuuulala Автор
      03.07.2015 12:52

      Ну это же не Arduinoвские analogRead(), а интерфейс, позволяющий вместо поиска в datasheet регистров Timer 2 Reload High и Low Byte набрать в поле Timer Overflow 1000 мс и, главное, получить

      	// $[TMR2RLH - Timer 2 Reload High Byte]
      	/*
      	// TMR2RLH (Timer 2 Reload High Byte) = 0xFF
      	*/
      	TMR2RLH = (0xFF << TMR2RLH_TMR2RLH__SHIFT);
      	// [TMR2RLH - Timer 2 Reload High Byte]$
      
      	// $[TMR2RLL - Timer 2 Reload Low Byte]
      	/*
      	// TMR2RLL (Timer 2 Reload Low Byte) = 0x30
      	*/
      	TMR2RLL = (0x30 << TMR2RLL_TMR2RLL__SHIFT);
      	// [TMR2RLL - Timer 2 Reload Low Byte]$
      


      Я бы вообще не говорила что конфигуратор — инструмент, предназначенный для новичков. Это инструмент, помогающий специалистам любого класса упросить ту часть работы, которую упрощать можно и нужно. Это как использовать Ctrl-F вместо пролистывания 500-страничного pdf.


      1. uuuulala Автор
        03.07.2015 12:53

        Наверное было не совсем правильно разбирать в статье почти полностью автоматически созданное приложение. Это наталкивает на мысль, что программирование заключается в тыканьи мышкой, в реальности же работа инженера начинается только после нажатия «Genarate Source».