Как повторно включить USB-контроллер 32u4 после спящего режима?
У меня возникла проблема с моим 32u4: я не могу подключить его к компьютеру после выхода из спящего режима!
Итак, у меня есть Arduino Pro Micro с 32u4, и я также разрабатываю проект с автономным 32u4 (я использую Pro Micro в качестве тестовой платформы, прежде чем приступить к созданию своего проекта). Это устройство с батарейным питанием и плавным запуском, поэтому мне нужно, чтобы энергопотребление было минимальным (отсюда и спящие режимы).
После изучения регистров и ознакомления с некоторыми двоичными файлами перевод чипа в спящий режим оказался довольно простым, однако я не могу заставить внутренний USB-интерфейс 32u4 «возобновить пробуждение» или повторно подключиться к компьютеру. Я прикрепил свой код ниже. Я также протестировал этот код на своем Arduino Nano, и он работает отлично, однако с добавленными функциями USB 32u4 я не могу заставить его повторно подключиться к компьютеру, и мне приходится перезагружать чип миллион раз, чтобы IDE наконец заработала. распознайте его и загрузите в него что-нибудь еще.
Вот мой прекрасный код ниже. Все это происходит при запуске, переходе в режим сна, а когда прерывание на выводе 2 переходит в низкий уровень, микросхема снова включается и запускает мигающий скетч. Он засыпает, просыпается и запускает скетч, но он никогда не подключится к моему компьютеру, пока я не выполню аппаратный сброс.
int btn1Pin = 2;
int led1 = 9;
// это «стандартные» конфигурации регистров
byte _SMCR = 0; // отключаем спящий режим
byte _ADCSRA = 0b10000111; // повторно включаем АЦП
int interval = 500;
int ledState = true;
unsigned long ct1 = 0;
unsigned long pt1 = 0;
void setup()
{
pinMode(led1, OUTPUT);
attachInterrupt(digitalPinToInterrupt(btn1Pin), wakeUp, FALLING);
sleep();
}
void loop()
{
ct1 = millis(); // моргаем что-нибудь, чтобы я знал, что ты работаешь
if (ct1 - pt1 >= interval)
{
digitalWrite(led1, ledState);
ledState = !ledState;
pt1 = ct1;
}
}
void wakeUp()
{
SMCR = _SMCR; // отключаем спящий режим
ADCSRA = _ADCSRA; // повторно включаем АЦП
}
void sleep()
{
ADCSRA &= ~(1 << 7); // отключаем АЦП
SMCR |= ( 1<<2 ); // режим выключения
SMCR |= 1; // включаем сон
__asm__ __volatile__("sleep"); // гипнотизер щелкает пальцами, чип остыл!
}
В мозгу Эй-Джея (дополнительные исследования): Информационная таблица 32u4 для быстрого ознакомления
Я добавил быстрое включение светодиода в ISR WakeUp(), чтобы убедиться, что он действительно выполняется, и это действительно так.
Описание регистра USBCON (стр. 267 - 21.13.1) утверждает, что очистка бита 7 отключает и сбрасывает контроллер USB. Я попробовал еще одну итерацию кода, где в Sleep() я очистил бит 7, надеясь, что это сбросит контроллер, а в WakeUp() я установил бит, чтобы снова включить его после сброса, но это не сработало. На самом деле, это доставило мне большие трудности при попытке перепрограммирования (хотя я ЗНАЮ, что ISR WakeUp() выполняется и бит нужно было сбросить).
После некоторого чтения я увидел (Страница 262 - 21.7.2) сообщение о том, что в режиме пониженного энергопотребления (спящий режим, который я использую), "генератор останавливается и останавливает все тактовые сигналы (ЦП и периферийные устройства). USB-контроллер «просыпается». вверх', когда:
- срабатывает прерывание WAKEUPI
- срабатывает прерывание VBUSTI."
Хорошо, это имеет смысл, в режиме отключения питания USB-контроллер останавливается из-за отсутствия генератора, круто! Я понимаю, что это означает, что мне нужно вызвать одно из этих прерываний, чтобы повторно включить контроллер USB. Итак, я поискал первое прерывание «WAKEUPI», и оказалось, что этот бит устанавливается аппаратно (стр. 282). Я предполагаю, что это означает, что вы подключаете USB-кабель? Я написал скетч для чтения этого регистра, и он вернул 00010000, поэтому я предполагаю, что приведенное выше утверждение верно. В нем также говорится, что настройка с помощью программного обеспечения не имеет никакого эффекта, поэтому я оставил это, чтобы изучить следующее прерывание, VBUSTI, которое, по-видимому, является частью автоматического обнаружения подключения USB на основе панели VBUS. Возможно, здесь нужно что-то изменить, но я не могу сказать.
На странице 266 - 21.12 рассказывается о программных режимах работы USB, а последняя — «Возобновление работы интерфейса USB». Четыре пункта, которые помогут проснуться, таковы:
- Включить ФАПЧ
- Подождать блокировку PLL
- Разморозить часы USB
- Очистить информацию о резюме
Я попытался сделать все вышеперечисленное, добавив этот код в ISR WakeUp(). Это все равно не сработало :(. Я знаю, что это жестоко, и ISR должны быть как можно короче, но я все равно попробовал.
PLLCSR = _PLLCSR; // включаем тактовую частоту ФАПЧ
var = bitRead(PLLCSR, 0);
while (var != 1) {} // ждем, пока часы зафиксируются
USBCON = _USBCON; // размораживаем часы USB
UDINT = 0; // очищаем флаг возобновления
Может быть, я все это усложняю, не знаю! Я не могу заставить эту штуку снова подключиться.
@HavocRC, 👍1
1 ответ
Лучший ответ:
Вы слишком сильно к себе относитесь.
Существует способ перезапустить USB, но он работает только в том случае, если USB был правильно остановлен, а метод, который должен это сделать, пуст.
Это небольшой набросок, который работает на моем Леонардо:
#include <LowPower.h>
void setup() {
}
void loop() {
USBCON = 0;
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
USBDevice.attach();
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
delay(10000);
digitalWrite(13, LOW);
}
Он отключает USB (USBCON = 0;
), переходит в режим ожидания на 8 секунд, затем снова запускает USB с нуля (USBDevice.attach();
). Через 10 секунд он снова засыпает.
На компьютере вы получаете (в Linux):
[1242489.000014] usb 2-1.5.2: Product: USB IO Board
[1242489.000015] usb 2-1.5.2: Manufacturer: Arduino LLC
[1242489.000316] cdc_acm 2-1.5.2:1.0: ttyACM0: USB ACM device
[1242498.631563] usb 2-1.5.2: USB disconnect, device number 69
[1242507.068078] usb 2-1.5.2: new full-speed USB device number 70 using ehci-pci
[1242507.199628] usb 2-1.5.2: New USB device found, idVendor=2341, idProduct=0036
[1242507.199630] usb 2-1.5.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1242507.199631] usb 2-1.5.2: Product: USB IO Board
[1242507.199633] usb 2-1.5.2: Manufacturer: Arduino LLC
[1242507.200256] cdc_acm 2-1.5.2:1.0: ttyACM0: USB ACM device
[1242517.063425] usb 2-1.5.2: USB disconnect, device number 70
[1242525.495729] usb 2-1.5.2: new full-speed USB device number 71 using ehci-pci
[1242525.627634] usb 2-1.5.2: New USB device found, idVendor=2341, idProduct=0036
.... etc ....
- Arduino Leonardo/Pro Micro сон и USB
- Arduino Pro Micro не распознается ПК
- Не могу загружать шестнадцатеричные файлы вне Arduino IDE на Pro Micro
- Библиотека джойстиков Arduino не распознается играми (Steam)
- Нет ttyACM0 с Pro Micro в Ubuntu 18.04
- Первое программирование самодельной платы ATMega32U4
- Возобновление последовательного соединения после сна на Arduino M0
- Клоны Pro Micro 3,3 В, мигающие светодиодами после касания со скоростью 1200 бит/с
Сначала я пытался не использовать библиотеки, но забыл, что могу проверить их, чтобы увидеть, что они делают. Я очень ценю это, я определенно потрачу некоторое время на изучение этого., @HavocRC
USBdevice.attach находится в ядре, а не в библиотеке., @Majenko
Я говорил о малой мощности, лол. И действительно? Я этого не осознавал, я предполагал, что это часть малой мощности., @HavocRC
Я просто выразил это [ USBDevice.attach(); ] в мой исходный код в WakeUp ISR, USBCON = 0 в моем Sleep(), и все работает отлично!, @HavocRC
Я использовал низкую мощность только для сна, потому что это было удобно., @Majenko