Практика. Мигание светодиодом с заданной частотой.
Давайте возьмем за основу примеры Blink и DigitalReadBtnSerial из библиотеки VBCoreG4, их можно найти в File->Examples->VBCoreG4_arduino_system, и напишем свою программу, которая после загрузки которой, на плате будет мигать светодиод на определенной частоте. По нажатию на кнопку мигание прекращается, а частота мигание задается через Serial порт.
Для начала подключим библиотеку и определим нужные нам пины. На схеме платы можно увидеть, что светодиод соединен с выводом PA5, а пользовательская кнопка - с PC13. В библиотеке они уже определены как LED2 и USR_BTN, но если мы об этом не помним, можно определить еще раз или присвоить выводам PA5 и PC13 любые другие имена. Делается это с помощью #define.
Далее нам понадобятся несколько переменных - частота мигания светодиода, которую мы будем задавать через Serial порт. Пусть по умолчанию она равна 1 Гц. Нужна переменная, которая покажет выключен ли режим мигания светодиодом - если выключен, то светодиодом не мигаем, переменная, в которую будет записано текущее состояние кнопки и переменная, в которую будет записано предыдущее состояние кнопки. И последнее, что нам понадобится в программе - это таймер, который будет задавать прерывания с заданной частотой.
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, настраиваем таймер, по умолчанию светодиод мигает один раз в секунду.
Подробнее о том, как работать с таймерами и прерываниями можно почитать здесь.
В основном цикле мы проверяем нажата ли кнопка, а также, если пользователь в 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.
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);} //иначе выключим светодиод
}
Вот и вся программа. Далее загружаем ее на плату и тестируем работу. С полным кодом можно ознакомиться ниже.
#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);} //иначе выключим светодиод
}