Watchdog и прерывания
- Войдите на сайт для отправки комментариев
Втр, 26/05/2020 - 19:25
Здравствуйте. Суть такая, три положения на передатчике. Attiny 13спит.Ставлю тумблер в положение 1-приемник принимает сигнал PWM(длительность 1500мс) . Пытаюсь сделать так, чтобы она спала, а как только пришел этот сигнал она просыпалась, выполняла какое то действие и снова засыпала. Аналогично и далее, тумблер в положение 2( длительность сигнала 2000мс)-опять проснулась и сделала что то и снова в спячку.Код написал но не работает(((
//Установить частоту платы 9.6МГц
#include <avr/io.h> // принято подключать
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#define F_CPU 9600000UL // 9.6 MHz
#define PPM_pin 1
int PPM;
unsigned long time;
unsigned long previoustime=0;
int count=0;
ISR (WDT_vect) { // данна функция вызывается по прерыванию при срабатывании wdt
// если wdt не сбросить, то будет резет
wdt_reset(); // сбрасываем wdt сторож
WDTCR |= _BV(WDTIE); // разрешение прерываний от сторожевого таймера
count++;
}
ISR(PCINT0_vect)
{
watch();
}
void setup()
{
DDRB &= ~(1<<1);
DDRB |= (1<<0);
DDRB |= (1<<2);
DDRB |= (1<<4);
GIMSK |= (1<<PCIE); // Разрешаем внешние прерывания PCINT0.
PCMSK |= (1<<1); // Разрешаем по маске прерывания на ногак кнопок (PCINT3, PCINT4)
sei(); // Разрешаем прерывания глобально: SREG |= (1<<SREG_I)
wdt_enable(WDTO_8S); // разрешаем ватчдог каждые 8сек.
WDTCR |= _BV(WDTIE); // разрешаем прерывания по ватчдогу. Иначе будет резет.
sei(); // разрешаем прерывания
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
wdt_reset(); // сбрасываем
}
void loop()
{
PPM_read();
watch();
wdt_reset(); // перед сном сбрасываем, чтобы спать все отведенное время
sleep_enable(); // разрешаем сон
sleep_cpu(); // спать!
}
//=============================================================================
// Считывание сигнала PPM
//=============================================================================
void PPM_read(){
while (!(PINB & (1<<PINB1))); //когда на пине РВ1 0
time = micros();
while (PINB & (1<<PINB1)); //когда на пине РВ1 1
time = micros()-time;
if (time>980 && time<3000) PPM = time;
}
//========================================================
//если произощло прерывание на PB1////////////////////////////
//==================================================
void watch() // должна проснуться если пришел сигнал на PB1
{
if (PPM <1200 )
{
PORTB &= ~(1<<0);
PORTB &= ~(1<<2);
PORTB &= ~(1<<4);
}
if (PPM < 1550 && PPM> 1200)
{
unsigned long time1=micros();
if ( time1-previoustime>25000)
{
previoustime=time1;
PORTB ^= (1 << PB0);
PORTB ^= (1 << PB2);
PORTB ^= (1 << PB4);
}
}
if (PPM > 2020) {
PORTB |= (1<<0);
PORTB |= (1<<2);
PORTB |= (1<<4); //digitalWrite (0, HIGH);
}
if(count>=20) спим 160 сек.
{
count=0;
}
}
Здравствуйте. Суть такая, три положения на передатчике. Attiny 13спит.Ставлю тумблер в положение 1-приемник принимает сигнал PWM(длительность 1500мс) . Пытаюсь сделать так, чтобы она спала, а как только пришел этот сигнал она просыпалась, выполняла какое то действие и снова засыпала. Аналогично и далее, тумблер в положение 2( длительность сигнала 2000мс)-опять проснулась и сделала что то и снова в спячку.Код написал но не работает(((
//Установить частоту платы 9.6МГц #include <avr/io.h> // принято подключать #include <avr/wdt.h> // здесь организована работа с ватчдогом #include <avr/sleep.h> // здесь описаны режимы сна #include <avr/interrupt.h> // работа с прерываниями #define F_CPU 9600000UL // 9.6 MHz #define PPM_pin 1 int PPM; unsigned long time; unsigned long previoustime=0; int count=0; ISR (WDT_vect) { // данна функция вызывается по прерыванию при срабатывании wdt // если wdt не сбросить, то будет резет wdt_reset(); // сбрасываем wdt сторож WDTCR |= _BV(WDTIE); // разрешение прерываний от сторожевого таймера count++; } ISR(PCINT0_vect) { watch(); } void setup() { DDRB &= ~(1<<1); DDRB |= (1<<0); DDRB |= (1<<2); DDRB |= (1<<4); GIMSK |= (1<<PCIE); // Разрешаем внешние прерывания PCINT0. PCMSK |= (1<<1); // Разрешаем по маске прерывания на ногак кнопок (PCINT1) sei(); // Разрешаем прерывания глобально: SREG |= (1<<SREG_I) wdt_enable(WDTO_8S); // разрешаем ватчдог каждые 8сек. WDTCR |= _BV(WDTIE); // разрешаем прерывания по ватчдогу. Иначе будет резет. sei(); // разрешаем прерывания set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную wdt_reset(); // сбрасываем } void loop() { PPM_read(); watch(); wdt_reset(); // перед сном сбрасываем, чтобы спать все отведенное время sleep_enable(); // разрешаем сон sleep_cpu(); // спать! } //============================================================================= // Считывание сигнала PPM //============================================================================= void PPM_read(){ while (!(PINB & (1<<PINB1))); //когда на пине РВ1 0 time = micros(); while (PINB & (1<<PINB1)); //когда на пине РВ1 1 time = micros()-time; if (time>980 && time<3000) PPM = time; } //======================================================== //если произощло прерывание на PB1//////////////////////////// //================================================== void watch() // должна проснуться если пришел сигнал на PB1 { if (PPM <1200 ) { PORTB &= ~(1<<0); PORTB &= ~(1<<2); PORTB &= ~(1<<4); } if (PPM < 1550 && PPM> 1200) { unsigned long time1=micros(); if ( time1-previoustime>25000) { previoustime=time1; PORTB ^= (1 << PB0); PORTB ^= (1 << PB2); PORTB ^= (1 << PB4); } } if (PPM > 2020) { PORTB |= (1<<0); PORTB |= (1<<2); PORTB |= (1<<4); //digitalWrite (0, HIGH); } if(count>=20) спим 160 сек. { count=0; } }Что значит "Сигнал PWM длительность 1500 мс"?. Какая частота PWM, какая скважность? Или это одиночный импульс?
Надо чтобы был режим POWER DOWN и контроллер выходил из этого режима по сигналу на PB0(PCINT0). А работает либо спящий режим если закомментировать строку GIMSK |= (1<<PCIE); или PCCMSK |= (1<<0); или если раскомментировать эти строки , то работает прерывание на PB0 но не работает режим POWER DOWN. Подсобите светом что не так, люди добрые)
//Установить частоту платы 9.6МГц #include <avr/io.h> // принято подключать #include <avr/wdt.h> // здесь организована работа с ватчдогом #include <avr/sleep.h> // здесь описаны режимы сна #include <avr/interrupt.h> // работа с прерываниями #define F_CPU 9600000UL // 9.6 MHz #define PPM_pin 1 int PPM; unsigned long time; unsigned long previoustime=0; int count=0; ISR (WDT_vect) { // данна функция вызывается по прерыванию при срабатывании wdt // если wdt не сбросить, то будет резет wdt_reset(); // сбрасываем wdt сторож WDTCR |= _BV(WDTIE); // разрешение прерываний от сторожевого таймера PORTB ^= (1 << 3); //это для проверки WATCHDOG } ISR(PCINT0_vect) { watch(); } void setup() { DDRB &= ~(1<<0); DDRB |= (1<<1); DDRB |= (1<<2); DDRB |= (1<<4); DDRB |= (1<<3); MCUCR |= (0 << ISC01) | (0 << ISC00); MCUCR |= (1<<SM1); // power-down mode MCUCR &= ~(1<<SM0); // power-down mode GIMSK |= (1<<PCIE); // Разрешаем внешние прерывания PCINT0. PORTB |= (1<<3); //PCMSK |= (1<<0); // Разрешаем по маске прерывания на ногак кнопок (PCINT0) PRR = (1<<PRADC); // shut down ADC sei(); // Разрешаем прерывания глобально: SREG |= (1<<SREG_I) ADCSRA &= ~(1 << ADEN); wdt_reset(); // сбрасываем wdt_enable(WDTO_4S); // разрешаем ватчдог каждые 8сек. WDTCR |= _BV(WDTIE); // разрешаем прерывания по ватчдогу. Иначе будет резет. sei(); // разрешаем прерывания set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную } void loop() { PPM_read(); wdt_reset(); // перед сном сбрасываем, чтобы спать все отведенное время sleep_enable(); // разрешаем сон sleep_cpu(); // спать! } //============================================================================= // Считывание сигнала PPM //============================================================================= void PPM_read(){ while (!(PINB & (1<<0))); //когда на пине РВ1 0 time = micros(); while (PINB & (1<<0)); //когда на пине РВ1 1 time = micros()-time; if (time>980 && time<3000) PPM = time; } //======================================================== //если произощло прерывание на PB1//////////////////////////// //================================================== void watch() // должна проснуться если пришел сигнал на PB0 { if (PPM <1200 ) { PORTB &= ~(1<<1); PORTB &= ~(1<<2); PORTB &= ~(1<<4); } if (PPM < 1550 && PPM> 1200) { unsigned long time1=micros(); if ( time1-previoustime>25000) { previoustime=time1; PORTB ^= (1 << 1); PORTB ^= (1 << 2); PORTB ^= (1 << 4); } } if (PPM > 2000) { PORTB |= (1<<1); PORTB |= (1<<2); PORTB |= (1<<4); //digitalWrite (0, HIGH); } }Или я туплю и режим POWER DOWN работает.
Меряю тестером,ток без sleep enable 4.4мА, добавляю эти строки ток составляет 0.27мА, т.е как я понимаю спящий режим работает? Но вот в скетче BLINK ток в спящем режиме составляет 7мкА, сам измерял. Почему же в моем скетче ток потребления выше?
Или я туплю и режим POWER DOWN работает.
Меряю тестером,ток без sleep enable 4.4мА, добавляю эти строки ток составляет 0.27мА, т.е как я понимаю спящий режим работает? Но вот в скетче BLINK ток в спящем режиме составляет 7мкА, сам измерял. Почему же в моем скетче ток потребления выше?
послушайте, а нафига две одинаковых ветки?
админы. предлагаю эту ветку снести. у нее есть полная копия в другом разделе