LPC

Мигание светодиодом в LPC1114. 5 способов.

Традиционно, первым учебным проектом на микроконтроллере предлагается программный код, осуществляющий мигание светодиода, подключенного к какому-либо порту. Ниже приведены варианты реализации подобной функции, выполненные с помощью различных возможностей микроконтроллера LPC1114.

Задачу получения периодического зажигания и гашения светодиода можно свести к формированию выходного сигнала с определенной частотой. Практически любой микроконтроллер позволяет выполнить такое действие несколькими способами. В их число входят как чисто программные, так и аппаратные варианты. Ниже рассмотрены 5 способов, которые можно использовать в микроконтроллерах серии LPC11xx или на плате LPCXpresso. В первых четырех вариантах светодиод подключен к выходу PIO2_10. В пятом имеется жесткая привязка к аппаратной платформе. Все примеры программ написаны и опробованы в среде CodeRed.

1. Программная задержка в цикле.

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

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

Задержка в цикле

#include"driver_config.h"

#include"target_config.h"

uint32_t i;

int main (void) {

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // Подключение GPIO к AHB

  LPC_GPIO2->DIR |= (1<<10);           // Настройка GPIO2_10 на вывод  

  while (1) /*Бесконечный цикл */

{

    LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (1<<10);// Установка выхода

    for (i=0;i<480000;i++);                     // Пустой цикл

    LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (0<<10);// Сбросвыхода

    for (i=0;i<480000;i++);                     // Пустой цикл

}

}

2. Задержка с помощью таймера.

Реализация задержки с помощью таймера отличается от предыдущего случая только использованием специального блока контроллера, позволяющего задавать временные интервалы. 

Задержка по таймеру

#include"driver_config.h"

#include"target_config.h"

int main (void) { 

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // Подключение GPIO к AHB

  LPC_GPIO2->DIR |= (1<<10);     // Настройка GPIO2_10 на вывод

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9);

  LPC_TMR32B0->TCR = 0x02;       // Сброс таймера

  LPC_TMR32B0->PR = 0x00;        // Сброс предделителя

  LPC_TMR32B0->MR0 = 4800000;    // Установка регистра сравнения

  LPC_TMR32B0->IR = 0xff;        // Сброс прерываний

  LPC_TMR32B0->MCR = 0x04;       // Останов таймера по сравнению с MR0

while (1) /*Бесконечный цикл */

{ LPC_TMR32B0->TCR = 0x02;       // Сброс таймера

  LPC_TMR32B0->TCR = 0x01;         // Пуск таймера

  LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (1<<10); // Установка выхода

  while (LPC_TMR32B0->TCR & 0x01); // Ожидание окончания счета

  LPC_TMR32B0->TCR = 0x02;         // Сброс таймера

  LPC_TMR32B0->TCR = 0x01;         // Пуск таймера

  LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (0<<10); // Сбросвыхода

  while (LPC_TMR32B0->TCR & 0x01); // Ожидание окончания счета

}

 

3. Работа по значению таймера.

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

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

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

Работа по значению таймера

#include"driver_config.h"

#include"target_config.h" 

int main (void) {

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // Подключение GPIO к AHB

  LPC_GPIO2->DIR |= (1<<10);           // Настройка GPIO2_10 на вывод

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9); // Подключение TIM32_0 к AHB

  LPC_TMR32B0->TCR = 0x02;   // Сброс таймера

  LPC_TMR32B0->PR = 0x00;    // Сброс предделителя

  LPC_TMR32B0->MR0 = 9600000;// Установка регистра сравнения

  LPC_TMR32B0->IR = 0xff;    // Сброс прерываний

  LPC_TMR32B0->MCR = 0x02;   // Настройка таймера на сброс по достижении MR0

  LPC_TMR32B0->TCR = 0x01;  // Пуск таймера

while (1) /* Бесконечный цикл*/

//Смена состояния выхода    

{if (LPC_TMR32B0->TC < 4800000) LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (1<<10);

 else LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (0<<10);

}

}

 

4. Работа по прерыванию от таймера.

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

Пример прерывания от таймера

#include"driver_config.h"

#include"target_config.h"

/* Прерывание */

void TIMER32_1_IRQHandler (void) {

LPC_TMR32B1->IR = 1;                   // Сброс флага прерывания

if (LPC_GPIO2->MASKED_ACCESS[(1<<10)]) // Смена состояния выхода

           LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (0<<10);

else       LPC_GPIO2->MASKED_ACCESS[(1<<10)] = (1<<10);

return;

}

/* Основнойцикл */

int main (void) {

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // Подключение GPIO к AHB

  LPC_GPIO2->DIR |= (1<<10);           // Настройка GPIO2_10 на вывод

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<10);// Подключение TIM32_1 к AHB

  LPC_TMR32B1->TCR = 0x02;          // Сброс таймера

  LPC_TMR32B1->PR = 0;              // Установка предделителя

  LPC_TMR32B1->MR0 = 19200000;      // Установка регистра сравнения

  LPC_TMR32B1->MCR = 0x03;      //Сброс таймера и прерывание по достижении MR0

  LPC_TMR32B1->TCR = 0x01;         // Пуск таймера

  NVIC_EnableIRQ(TIMER_32_1_IRQn); // Разрешение прерывания

while (1) {}// Бесконечный цикл

}

 5. Работа таймера в режиме сравнения.

Еще одним полезным вариантом организации мигания может стать использование функции формирования внешнего сигнала от модуля сравнения таймера. В этом случае не требуется никакого программного кода, кроме функции настройки. Все необходимые действия выполняются непосредственно самим таймером, процессор может решать свои задачи, не отвлекаясь на переключение выхода. Данный способ имеет и солидное практическое применение при организации ШИМ. Недостатком данного способа является жесткая привязка выходных устройств к аппаратным модулям микроконтроллера. В примере используется модуль TIM16_1 и его выход MAT0, совмещенный с PIO1_9. 

Режим формирования внешнего сигнала от модуля сравнения таймера

#include"driver_config.h"

#include"target_config.h"

int main (void) {

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // Подключение GPIO к AHB

   LPC_SYSCON->SYSAHBCLKCTRL |= (1<<8); // Подключение TIM16_1 к AHB

    LPC_IOCON->PIO1_9 = 0x01;          // Линия 1_9 - выход таймера 

  LPC_TMR16B1->TCR = 0x02;           // Сброс таймера 

  LPC_TMR16B1->PR = 500;             // Установка предделителя 

  LPC_TMR16B1->MR0 = 48000;          // Установка регистра сравнения

  LPC_TMR16B1->MCR = 0x02;           // Сброс таймера и прерывание по достижении MR0

  LPC_TMR16B1->EMR = 48;             // Настройка срабатывания выхода 1_9

  LPC_TMR16B1->TCR = 0x01;           // Пуск таймера  

while (1) {}// Бесконечный цикл

} 

Еще по теме:

Работа с периферийными портами в LPC11xx

Таймеры в микроконтроллерах LPC11xx

You have no rights to post comments