Почему светодиод автоматически выключается примерно через 18 секунд?

Я использую Arduino Due и программирую его с помощью Atmel Studio 6.2. Мне пришлось ОГРОМНО научиться пользоваться этой IDE и Atmel ASF. Ничто не является таким простым, как в Arduino IDE. Тем не менее, я хочу включать и выключать светодиод с помощью простого прерывания на настроенной тактильной кнопке. Это мой код:

#include <asf.h>
#include "pio.h"

// Определим контакты светодиода
#define BLUE_LED2 PIO_PC28 // вывод 3 Arduino Due
#define BLUE_LED3 PIO_PC26 // вывод 4 Arduino Due
#define BLUE_LED4 PIO_PC25 // вывод 5 Arduino Due
#define BLUE_LED5 PIO_PC24 // вывод 6 Arduino Due
#define BLUE_LED6 PIO_PC23 // вывод 7 Arduino Due

// Определим контакты кнопки
#define BUTTON_1 PIO_PC22
#define BUTTON_2 PIO_PC21

// Определить прототип функции для прерывания кнопки
void button_press_handler(uint32_t, uint32_t);
void toggle_LED(uint32_t);


int main (void)
{
    /* Initialize the SAM system. */
    sysclk_init();

    // Инициализируем ввод/вывод
    ioport_init();
    pmc_enable_periph_clk(ID_PIOC);
    pmc_enable_periph_clk(ID_PIOB);


    // Устанавливаем контакты светодиодов как выходы и устанавливаем для них значения по умолчанию (выкл.)
    pio_set_output(PIOC, BLUE_LED2, LOW, DISABLE, ENABLE); 
    pio_set_output(PIOC, BLUE_LED3, LOW, DISABLE, ENABLE); 
    pio_set_output(PIOC, BLUE_LED4, LOW, DISABLE, ENABLE); 
    pio_set_output(PIOC, BLUE_LED5, LOW, DISABLE, ENABLE); 
    pio_set_output(PIOC, BLUE_LED6, LOW, DISABLE, ENABLE); 

    // Устанавливаем контакты кнопок как подтягивающие входы
    pio_set_input(PIOC, BUTTON_1, PIO_PULLUP);
    pio_set_input(PIOC, BUTTON_2, PIO_PULLUP); 

    // Настраиваем режим и обработчик прерывания входного контакта кнопки (Falling Edge)
    pio_handler_set(PIOC, ID_PIOC, BUTTON_1,  PIO_IT_RISE_EDGE, button_press_handler);
    pio_handler_set(PIOC, ID_PIOC, BUTTON_2,  PIO_IT_RISE_EDGE, button_press_handler);

    // Включаем прерывания
    pio_enable_interrupt(PIOC, BUTTON_1); 
    pio_enable_interrupt(PIOC, BUTTON_2); 
    NVIC_EnableIRQ(PIOC_IRQn); 

    while(1){
         // Делаем здесь что-то...
    }
}

Тогда это моя процедура прерывания:

// Обработчик прерывания при нажатии кнопки
void button_press_handler(uint32_t a, uint32_t b)
{
    // Включаем или выключаем светодиоды
    toggle_LED(BLUE_LED2);
    toggle_LED(BLUE_LED3);
    toggle_LED(BLUE_LED4);
    toggle_LED(BLUE_LED5);
    toggle_LED(BLUE_LED6);
}

// Функция включения/выключения светодиода
void toggle_LED(uint32_t LED){

    if (pio_get(PIOC, PIO_TYPE_PIO_OUTPUT_0, LED))
    pio_clear(PIOC, LED);
    else
    pio_set(PIOC, LED); 
}

Все работает нормально и как и ожидалось примерно до 18 секунд. Через 18 секунд светодиод гаснет, если он горит. Я проверил это, установив по умолчанию высокий уровень светодиода 2 и полностью удалив прерывание:

pio_set_output(PIOC, BLUE_LED2, HIGH, DISABLE, ENABLE); 

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

, 👍1

Обсуждение

Я понял, что проблема происходит из-за того, что я не инициализировал плату. Все, что мне нужно было сделать, это добавить «board_init();» под моим кодом инициализации системных часов в main(void), и теперь он работает., @Hooplator15

Вы должны ответить себе и отметить это как ответ, чтобы другие люди поняли, что у вопроса есть решение. Это ожидаемое поведение http://arduino.stackexchange.com/help/self-answer., @jdr5ca


3 ответа


1

Описанные вами симптомы соответствуют сбою вашей программы через 18 секунд. Я ожидаю, что вы найдете в этом что-то, что является проблемой:

while(1){
     // Делаем здесь что-то...
}

Чтобы отладить это, добавьте в стартап что-нибудь уникальное или легко идентифицируемое:

  • "сброс" печати на последовательный порт, если он у вас есть
  • в вашем случае мигайте светодиодами в последовательности 2,3,4,5,6

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

// Здесь что-то делаем...

В урезанной программе светодиод должен гореть.

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

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

,

Что касается потребления слишком большого тока, я не думаю, что это так, потому что все светодиоды отлично работают в Arduino IDE. Я не делал абсолютно никаких аппаратных изменений на плате. Он работает в Arduino, но не в Atmel Studio, поэтому я думаю, что это проблема программного обеспечения., @Hooplator15

Кроме того, что касается цикла while, у меня там буквально ничего нет. У меня просто есть комментарий, который напоминает мне, что нужно сделать, как только я разберусь с этой проблемой., @Hooplator15

Неправильная обработка прерываний приведет к сбросу., @Gerben

@JohnAugust Было бы лучше добавить в вопрос то, что вы уже пробовали., @jdr5ca

Я исправил проблему, потому что я не включил «board_init();», @Hooplator15


2

Опять разобрался. Я просто забыл добавить board_init(); Кроме того, поскольку board_init() уже вызывает ioport_init(), мне пришлось отключить это.< /п>

Теперь у меня есть это:

int main (void)
{
    /* Инициализируем систему SAM. */
    sysclk_init(); // Инициализируем системные часы
    board_init();  // Инициализируем плату

....

,

0

Это может быть связано с тем, что чип ATSAM3X8E имеет сторожевой таймер: из раздела 15.1 таблицы данных

Сторожевой таймер можно использовать для предотвращения зависания системы, если программное обеспечение зашло в тупик. Это имеет 12-битный обратный счетчик, обеспечивающий период наблюдения до 16 секунд (медленная тактовая частота 32,768 кГц). Это может генерировать общий сброс или только сброс процессора. Кроме того, его можно остановить, пока процессор находится в режиме режим отладки или режим ожидания.

board_init() почти наверняка отключает сторожевой таймер.

,