# Практика. Мигание светодиодом с заданной частотой.

Давайте возьмем за основу примеры Blink и DigitalReadBtnSerial из библиотеки VBCoreG4, их можно найти в File->Examples->VBCoreG4\_arduino\_system, и напишем свою программу, которая после загрузки которой, на плате будет мигать светодиод на определенной частоте. По нажатию на кнопку мигание прекращается, а частота мигание задается через Serial порт.

Для начала подключим библиотеку и определим нужные нам пины. На схеме платы можно увидеть, что светодиод соединен с выводом PA5, а пользовательская кнопка - с PC13. В библиотеке они уже определены как LED2 и USR\_BTN, но если мы об этом не помним, можно определить еще раз или присвоить выводам PA5 и PC13 любые другие имена. Делается это с помощью #define.

```arduino
#include <VBCoreG4_arduino_system.h>

#define LED2 PA5
#define USR_BTN PC13
```

Далее нам понадобятся несколько переменных - частота мигания светодиода, которую мы будем задавать через Serial порт. Пусть по умолчанию она равна 1 Гц.  Нужна переменная, которая покажет выключен ли режим мигания светодиодом - если выключен, то светодиодом не мигаем, переменная, в которую будет записано текущее состояние кнопки и переменная, в которую будет записано предыдущее состояние кнопки. И последнее, что нам понадобится в программе - это таймер, который будет задавать прерывания с заданной частотой.

```arduino
double freq = 1; //частота в Гц
int is_off = LOW; // переменная, определяющая выключен ли режим мигания
int prev_btnSt; // предыдущее состояние кнопки
int buttonState; // текущее состояние кнопки
HardwareTimer *timer = new HardwareTimer(TIM3); // таймер
```

В функции setup() устанавливаем пины PA5 и PC13 в режимы OUTPUT и INPUT\_PULLUP, определяем переменную prev\_btnSt, настраиваем таймер, по умолчанию светодиод мигает один раз в секунду.&#x20;

Подробнее о том, как работать с таймерами и прерываниями можно почитать [здесь](https://github.com/stm32duino/Arduino_Core_STM32/wiki/HardwareTimer-library).

```arduino
void setup() {
  Serial.begin(115200);
  pinMode(USR_BTN, INPUT_PULLUP);
  pinMode(LED2, OUTPUT);
  prev_btnSt = digitalRead(USR_BTN);

  timer->pause();
  timer->setOverflow(1, HERTZ_FORMAT); // задаем частоту прерывания
  timer->attachInterrupt(blink); //функция мигания светодиодом, вызывается с указанной частатой
  timer->refresh();
  timer->resume();
}
```

В основном цикле мы проверяем нажата ли кнопка, а также, если пользователь в Serial порт отправил число, мы задаем новую частоту. Обратите внимание, что частота мигания светодиода задается в Гц. Если она больше либо равна 1, мы можем использовать HERTZ\_FORMAT, как второй параметр метода setOverflow. Если же требуемая частота меньше 1, то в качестве второго параметра задается формат MICROSEC\_FORMAT. Предварительно на значение частоты нужно разделить 1000000\*

\*В 1 секунде 1000000 микросекунд. Чтобы задать частоту в 1 Гц - светодиод загорается раз в секунду, время цикла должно быть равно 1000000 микросекунд. Если мы хотим получить частоту в 0,5 Гц, то есть светодиод загорается 1 раз в 2 секунды, время цикла между загораниями увеличивается в два раза и равно 2 секунды = 2000000 микросекунд = 1000000/0,5. Если хотим частоту 1 Гц уменьшить в 4 раза до 0,25 Гц, то соответственно время между циклами с 1 секунды увеличивается в 4 раза до 4 секунд = 4000000 микросекунд = 1000000/0,25.&#x20;

```arduino
void loop() { 
  buttonState = digitalRead(USR_BTN); //читаем состояние кнопки
  if(buttonState == LOW && prev_btnSt == HIGH){ //если в предыдущем цикле она 
                                                //не была нажата, а сейчас на нее нажали
    is_off = !is_off;                          //режим мигания лампочки меняем на противоположный.
                                              //если светодиод мигал, то отключаем мигание, 
                                              //если нет - то, наоборот, включаем
    prev_btnSt = buttonState;              //предыдущему состоянию кнопки даем текущее значение
  }
  if(buttonState == HIGH) {prev_btnSt = buttonState;}//предыдущему состоянию кнопки даем текущее значение
  if (Serial.available() > 0) { // если в порте появились какие-то данные
    freq = Serial.readString().toDouble(); // считываем частоту, преобразуем в тип double
    if(freq>=1){timer->setOverflow(freq, HERTZ_FORMAT);} //если частота >= 1, то используем HERTZ_FORMAT
    else if (freq> 0 && freq<1){timer->setOverflow(1000000/freq, MICROSEC_FORMAT);} // иначе - MICROSEC_FORMAT
    else {Serial.println("incorrect value for frequency");} //в случае если частота задана в неверном формате, <=0
    timer->refresh(); //обнуляем таймер
    timer->resume(); //запускаем таймер
  }
}
```

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

```arduino
void blink(){
  if(is_off == LOW){ //если режим работы не выключен
    digitalWrite(LED2, !digitalRead(LED2));  //мигаем светододом
  }
  else{digitalWrite(LED2, LOW);} //иначе выключим светодиод
}
```

Вот и вся программа. Далее загружаем ее на плату и тестируем работу. С полным кодом можно ознакомиться ниже.

```arduino
#include <VBCoreG4_arduino_system.h>

#define LED2 PA5
#define USR_BTN PC13

double freq = 1; //частота в Гц
int is_off = LOW; // переменная, определяющая выключен ли режим мигания
int prev_btnSt; // предыдущее состояние кнопки
int buttonState; // текущее состояние кнопки
HardwareTimer *timer = new HardwareTimer(TIM3); // таймер

void setup() {
  Serial.begin(115200);
  pinMode(USR_BTN, INPUT_PULLUP);
  pinMode(LED2, OUTPUT);
  prev_btnSt = digitalRead(USR_BTN);

  timer->pause();
  timer->setOverflow(1, HERTZ_FORMAT); // задаем частоту прерывания
  timer->attachInterrupt(blink); //функция мигания светодиодом, вызывается с указанной частотой
  timer->refresh();
  timer->resume();
}

void loop() { 
  buttonState = digitalRead(USR_BTN); //читаем состояние кнопки
  if(buttonState == LOW && prev_btnSt == HIGH){ //если в предыдущем цикле она 
                                                //не была нажата, а сейчас на нее нажали
    is_off = !is_off;                          //режим мигания лампочки меняем на противоположный.
                                              //если светодиод мигал, то отключаем мигание, 
                                              //если нет - то, наоборот, включаем
    prev_btnSt = buttonState;              //предыдущему состоянию кнопки даем текущее значение
  }
  if(buttonState == HIGH) {prev_btnSt = buttonState;}//предыдущему состоянию кнопки даем текущее значение
  if (Serial.available() > 0) { // если в порте появились какие-то данные
    freq = Serial.readString().toDouble(); // считываем частоту, преобразуем в тип double
    if(freq>=1){timer->setOverflow(freq, HERTZ_FORMAT);} //если частота >= 1, то используем HERTZ_FORMAT
    else if (freq> 0 && freq<1){timer->setOverflow(1000000/freq, MICROSEC_FORMAT);} // иначе - MICROSEC_FORMAT
    else {Serial.println("incorrect value for frequency");} //в случае если частота задана в неверном формате, <=0
    timer->refresh(); //обнуляем таймер
    timer->resume(); //запускаем таймер
  }
}

void blink(){
  if(is_off == LOW){ //если режим работы не выключен
    digitalWrite(LED2, !digitalRead(LED2));  //мигаем светододом
  }
  else{digitalWrite(LED2, LOW);} //иначе выключим светодиод
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://voltbro.gitbook.io/upravlenie-elektrodvigatelem/kollektornyi-dvigatel/praktika.-vbcores/praktika.-miganie-svetodiodom-s-zadannoi-chastotoi..md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
