Attiny13a sleep и interrupt по int0

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 2
Зарегистрирован: Сб окт 13, 2018 13:59:49

Сообщение caidu »

Добрый день. Только начал осваивать AVR, поэтому хочу задать вам кучу глупых вопросов.

Попросили меня сделать реквезит - фонарик на трехцветном светодиоде, который умеет по кнопке выбирать цвет свечения, запоминать его и отключаться. Задача, собственно, простая, программатор и запас 13а у человека был, программку я на основе примеров сварганил. Но оказалось, что attiny13a, если не заморачиваться с энергоэффективностью очень неплохо кушает - фонарика на 300 мАч батарейке хватало на сутки в выключенном состоянии, потому как работало все на delay. Начал вникать в сон, interrupt и wdr - набил себе граблями огромную шишку.

Проблема 1 - начинал я это делать в CVAVR, но у меня происходит что-то непонятное с библиотеками. Просто нет ни sleep.h, ни interrupt.h, ни wdr.h. Как их к нему прилепить я не понял.

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

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

Код: Выделить всё

#include <avr/io.h>         
#include <avr/sleep.h>      
#include <avr/interrupt.h>   
#include <util/delay.h>      

typedef unsigned char byte;
unsigned char trig, count;
unsigned short pushtime;                                        
		     
			     
SIGNAL(SIG_INTERRUPT0) 
{   
   disable_int0(); 
}


int main() 
{
   
count = 0;   
   
   while(1)
   {
	 
     if ((PINB & (1<<PB1))==0)    
       {
        pushtime++;  
        if ( pushtime>15)  
         {
           
               
          pushtime=0;
	  while ((PINB & (1<<PB1))==0)
	  {
	     delay_ms(10);
	  }
	  sleep_power_down();
	  
         }                                                                            
       }
       else
       {
	  if (pushtime>2 & pushtime<=15)
	  {
	    PORTB |= _BV(PB2);
	    delay_ms(500);
	    PORTB &= ~_BV(PB2);
	    delay_ms(100);
	    PORTB |= _BV(PB2);
	    delay_ms(500);
	    PORTB &= ~_BV(PB2);
	  }
	  pushtime=0;
       }
       if(count==10)
       {
	  PORTB |= _BV(PB0);
       }
       if (count==20)
       {
	  PORTB &= ~_BV(PB0);
	  count=0;
       }
       
       
      count++; 
      delay_ms(100);
   
      
   }
}
Но она выдает ошибки

Код: Выделить всё

avr-gcc.exe -mmcu=attiny13  -o "./Debug.elf" "main.o"
main.o: In function `main':
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:35: undefined reference to `delay_ms'
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:37: undefined reference to `sleep_power_down'
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:46: undefined reference to `delay_ms'
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:48: undefined reference to `delay_ms'
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:50: undefined reference to `delay_ms'
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:67: undefined reference to `delay_ms'
main.o: In function `__vector_1':
C:\Users\nikollor\AppData\Local\Temp\d2d5e583d4a14410bb8265b98c3f5f3c\ATtiny13\Debug/../main.c:13: undefined reference to `disable_int0'
make: *** [Debug.elf] Error 1

Error code 2
и я их абсолютно не понимаю. Ткните носом, пожалуйста. Можно даже тапком.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

Неопределенные функции delay_ms и т.д.
В WINAVR они по-другому пишутся. Посмотрите библиотеки изнутри или хелпы по этим библиотекам.
Docendo discimus
Контактная информация:
Реклама
Родился
Сообщения: 2
Зарегистрирован: Сб окт 13, 2018 13:59:49

Сообщение caidu »

[uquote="pyzhman",url="/forum/viewtopic.php?p=3483726#p3483726"]Неопределенные функции delay_ms и т.д.
В WINAVR они по-другому пишутся. Посмотрите библиотеки изнутри или хелпы по этим библиотекам.[/uquote]

Спасибо. Как ни странно, даже просмотрев библиотеки не заметил что delay в WinAVR через "_" пишется.

Еще проблема - исправил функции, заработало, уходит в сон и будится, но:

При первом уходе в сон зажигается индикатор сна, все гаснет, при пробуждении индикатор сна мигает и гаснет. (прописано в interrupt)
Но при втором и последующих уходах в сон сразу после ухода в сон индикатор сна мигает и гаснет но тем не менее девайс уходит в сон, то есть сразу после ухода в сон исполняется то, что прописано в interrupt'е, но сон не прерывается. Прерывания сразу после пробуждения отключаются и включаются перед сном. Что я забыл?

Код: Выделить всё

#define F_CPU 1000000UL
#include <avr/io.h>         
#include <avr/sleep.h>      
#include <avr/interrupt.h>   
#include <util/delay.h>      

typedef unsigned char byte;
unsigned int trig, count;
unsigned short pushtime;                                        
		     
			     
ISR(PCINT0_vect) //мигаем лампочкой sleep
{
   PORTB &= ~_BV(PB4);
   _delay_ms(100);
   PORTB |= _BV(PB4);
   _delay_ms(200);
   PORTB &= ~_BV(PB4);
   _delay_ms(100);
   PORTB |= _BV(PB4);
   _delay_ms(200);
   PORTB &= ~_BV(PB4); 
}


int main() 
{
   
 DDRB=0b00011101;
PORTB=0b00000010;
   
count = 0;   
   
   while(1)
   {
	 
     if ((PINB & (1<<PB1))==0)    
       {
        pushtime++;  
        if ( pushtime>15)  //длинное нажатие - уход в сон
         {
           
               
          pushtime=0;
	  while ((PINB & (1<<PB1))==0)
	  {
	     _delay_ms(10);
	  }
	  PORTB |= _BV(PB4);  //все лампочки выключаем, лампочку sleep включаем
	  PORTB &= ~_BV(PB2);
	  PORTB &= ~_BV(PB0);
	  
	  GIMSK |= (1<<PCIE);                    // Enable Pin Change Interrupts
	  PCMSK |= (1 << PB1);
	  
	  sei ();
	  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
	  sleep_enable ();
	  
	  sleep_cpu ();
	  sleep_disable ();
	  cli ();
         } 
	 _delay_ms(10);
       }
       else
       {
	  if (pushtime>2 & pushtime<=15) //короткое нажатие
	  {
	    PORTB |= _BV(PB2);  //мигаем лампочкой кнопки
	    _delay_ms(500);
	    PORTB &= ~_BV(PB2);
	    _delay_ms(100);
	    PORTB |= _BV(PB2);
	    _delay_ms(500);
	    PORTB &= ~_BV(PB2);
	  }
	  pushtime=0;
       }
       if(count==10)   //перемигиваемся светодиодом "работа"
       {
	  PORTB |= _BV(PB0); 
       }
       if (count>=20)
       {
	  PORTB &= ~_BV(PB0);
	  count=0;
       }
       
       
      count++; 
      _delay_ms(100);
   
      
   }
}
Добавлено after 6 minutes 35 seconds:
При прерывании, выводящем из сна, кстати, код из interrupt'а исполняется еще раз.
Ответить

Вернуться в «AVR»