atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Обсуждаем контроллеры компании Atmel.
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

доброго дня.
по поводу большого количества кода в прерывании, вы совершенно правы, спасибо.
atmel studio не находит функцию powerdown. да и не нужно) суть была в невозможности проснуться от прерывания по фронту. Спасибо большое
Вывод UART только для отладки.

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

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

/*
 * theBomb.c
 *
 * Created: 12.03.2015 20:37:09
 *  Author: andre
 */ 
/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#define _IN 0
#define _OUT 1
#define _PULLUP 1
#define _LOW 0
#define _HIGH 1
/* 9600 baud */
#define UART_BAUD_RATE      9600

#define uart_nextline uart_putc(13);


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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "uart/uart.h"

volatile unsigned int cnt = 0;
volatile unsigned int seconds_counter =0;
volatile bool check_pull = false;
volatile unsigned int freq = 30;
volatile bool int0_flag=false;


void enable_timer0(bool enable);
void enable_int0(void);
void disable_int0(void);
void init_timer0(void);
void init_ports(void);
void set_check_led(void);
void do_explode(void);
void read_ports_work(void);
bool is_in_service_mode(void);
void blink(void);

//названия портов в/в

//#define loop_until_bit_is_clear(port,bit) \ __asm__ __volatile__ ( \ "L_%=: " "sbic %0, %1" "\n\t" \ "rjmp L_%=" \ : /* no outputs */ : "I" (_SFR_IO_ADDR(port)), "I" (bit) )

//#define loop_until_bit_is_clear(port,bit) __asm__ __volatile__ ( "1: " "sbic %0, %1" "\n\t" "rjmp 1b" : /* no outputs */ : "I" (_SFR_IO_ADDR(port)), "I" (bit) )
/*
PORTC |= _BV(0);  // Set bit 0 only.
PORTC &= ~(_BV(1));  // Clear bit 1 only.
PORTC ^= _BV(7);  // Toggle bit 7 only.




*/

//Interrupt Service Routine for INT0
ISR(INT0_vect)
{
	uart_puts("in INT0 ISR");
	uart_nextline
	disable_int0();
	enable_timer0(true); // enable timer0
	check_pull=true;
	
}


// Timer 0 overflow interrupt service routine
ISR(TIMER0_OVF_vect) 

{

	cnt++;
	if (cnt>=freq)
	{
		enable_timer0(false); // disable timer0
		cnt=0;
		uart_puts("timer0 interrupt approx 1 sec");
		uart_nextline
		seconds_counter++;
		if (seconds_counter>=30)
			do_explode(); //тут всего лишь взвод ноги и не более, так что выносить ее в основной цикл не имеет смысла
			
		cli();
			TCNT0 = 0;
		sei();
		blink();
		enable_timer0(true);

	}
	
}
void blink(void)
{

        //нагнетаем обстановку)))))))
	PORTB ^= _BV(PB0);  
}

//check all wires to be connected
bool check_system(void)
{
	
	return true;
}

void enable_timer0(bool enable)
{
	if (enable)
		TIMSK |= ( 1 << TOIE0); // enable timer0;
	else 
		TIMSK &= ~( 1 << TOIE0); // disable timer0
	
}

void enable_int0(void)
{
	//initialize interrupts
	GICR = (1<<INT0);					// Enable INT0
	//сбрасываем все биты ISCxx
        //настраиваем на срабатывание INT0 по нмзкому уровню
	
	MCUCR &= ~( (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00) );

	
}

void disable_int0(void)
{
	GICR&= ~(1<<INT0);	
}


void init_timer0(void)
{
	//initialize timers
	// Timer/Counter 0 initialization
	// Clock source: System Clock
	// Clock value: 7,813 kHz     (/255/30 to approx 1 sec) (tim0 ovf even 30 interrupt)
	TCCR0=(1<<CS02) | (0<<CS01) | (1<<CS00);

	// initialize counter
	TCNT0 = 0;
}

void init_ports(void)
{
	// Input/Output Ports initialization
	// Port B initialization
	// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRB=(_IN<<DDB7) | (_IN<<DDB6) | (_IN<<DDB5) | (_IN<<DDB4) | (_IN<<DDB3) | (_IN<<DDB2) | (_IN<<DDB1)| (_OUT<<DDB0);
	// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=P Bit1=P Bit0=P
	PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (_LOW<<PORTB0);

	// Port C initialization
	// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
	DDRC=(_IN<<DDC6) | (_IN<<DDC5) | (_IN<<DDC4) | (_IN<<DDC3) | (_IN<<DDC2) | (_IN<<DDC1) | (_IN<<DDC0);
	// State: Bit6=T Bit5=P Bit4=P Bit3=P Bit2=P Bit1=P Bit0=0
	PORTC=(0<<PORTC6) | (_PULLUP<<PORTC5) | (_PULLUP<<PORTC4) | (_PULLUP<<PORTC3) | (_PULLUP<<PORTC2) | (_PULLUP<<PORTC1) | (_PULLUP<<PORTC0);

	// Port D initialization
	// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRD=(_IN<<DDD7) | (_IN<<DDD6) | (_IN<<DDD5) | (_IN<<DDD4) | (_IN<<DDD3) | (_IN<<DDD2) | (_IN<<DDD1) | (_IN<<DDD0);
	// State: Bit7=0 Bit6=0 Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
	PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
	
	
	
}

void set_check_led(void)
{

	
}

bool is_in_service_mode(void)
{
	
	
	return false;
}


void do_explode(void)
{
	//check service mode
	if (is_in_service_mode())
		return;
		
		
}

void read_ports_work(void)
{
	
	
	
}


int main(void)
{
	
	init_ports();
	enable_int0();
	init_timer0();

	
	//initialize UART on 9600
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	
	//enable interrupts
	sei();
	
	
	uart_puts("Initializing...");
	uart_puts("Ok.");
	uart_nextline
	


	//если тумблер сервисного режима не взаеден
	//ждем взведения
	//потом 
	//checking system wires
	if (check_system())
	{
		set_check_led();
		uart_puts("System check...Ok");
		uart_nextline
			
	}
	//else 
	//ждем снятия сервисного режима
	//чека должна быть установлена для продолжения выполнения
	
	//засыпаем
	
	
	//только в целях отладки подождем UART. Кроме него у нас ничего не должно выполняться асинхронно
	//таймер0 остановлен
	//INT0 инициализирован
	_delay_ms(2000);
	set_sleep_mode(SLEEP_MODE_PWR_DOWN);
	
	sleep_enable();
	sleep_cpu();
	
	
	
	
	//тут мы должны проснуться после сна
	sleep_disable();
	
	uart_puts("Waking up");
	uart_nextline

	
	
	
	
	while(true)
    {
		if (check_pull)
		{
			//working
			//проверяем перерезанные провода
			//взрываемся, ускоряемся или обезвреживаемся
			
		}
	
	
	
				
	}



}




и все же вопрос такой, как в atmel studio отлаживать код, хочется простого step-by-step на уровне си функций. Точки останова не срабатывают у меня нивкакую.
Unable to set requested bp on target. The current selected devise is unable to set bp during runtime.
Реклама
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

вообщем сделал так сервисный режим, как никак а все таки пиротехникака какая-то будет подсоединена.

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

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

/*
 * theBomb.c
 *
 * Created: 12.03.2015 20:37:09
 *  Author: andre
 */ 
/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#define _IN 0
#define _OUT 1
#define _PULLUP 1
#define _LOW 0
#define _HIGH 1

/* 9600 baud */
#define UART_BAUD_RATE      9600

#define uart_nextline uart_putc(13);


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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "uart/uart.h"

volatile unsigned int cnt = 0;
volatile unsigned int seconds_counter =0;
volatile bool check_pull = false;
volatile unsigned int freq = 30;
volatile bool int0_flag=false;
volatile bool exploded = false;
bool service_mode = false;
bool system_check_ok = false;

void enable_timer0(bool enable);
void enable_int0(void);
void disable_int0(void);
void init_timer0(void);
void init_ports(void);
void set_check_led(void);
void do_explode(void);
void read_ports_work(void);
bool is_in_service_mode(void);
void blink(void);
void blink_service_led(void);
void unset_check_led(void);

//названия портов в/в


#define TMR_LED_PIN PB0  //out low
#define CHECK_LED_PIN PB1 //out low
#define RUN_LED_PIN PD4 //out low
#define EXPLODE_OUT_PIN PD7 //out low

#define EXPLODE_IN_PIN PC0 //in pullup
#define NEUTRALIZE_IN_PIN PC1 //in pullup
#define FASTER_IN_PIN1 PC2 //in pullup
#define FASTER_IN_PIN2 PC3 //in pullup
#define FASTER_IN_PIN3 PC4 //in pullup
#define SERVICE_MODE_PIN PC5 //in pullup
#define CHECK_PIN PD2 //in non pullup




//some macro's

//#define loop_until_bit_is_clear(port,bit) \ __asm__ __volatile__ ( \ "L_%=: " "sbic %0, %1" "\n\t" \ "rjmp L_%=" \ : /* no outputs */ : "I" (_SFR_IO_ADDR(port)), "I" (bit) )

//#define loop_until_bit_is_clear(port,bit) __asm__ __volatile__ ( "1: " "sbic %0, %1" "\n\t" "rjmp 1b" : /* no outputs */ : "I" (_SFR_IO_ADDR(port)), "I" (bit) )
/*
PORTC |= _BV(0);  // Set bit 0 only.
PORTC &= ~(_BV(1));  // Clear bit 1 only.
PORTC ^= _BV(7);  // Toggle bit 7 only.




*/

//Interrupt Service Routine for INT0
ISR(INT0_vect)
{
	uart_puts("in INT0 ISR");
	uart_nextline
	disable_int0();
	enable_timer0(true); // enable timer0
	check_pull=true;
	
}


// Timer 0 overflow interrupt service routine
ISR(TIMER0_OVF_vect) 

{

	cnt++;
	if (cnt>=freq)
	{
		enable_timer0(false); // disable timer0
		cnt=0;
		uart_puts("timer0 interrupt approx 1 sec");
		uart_nextline
		seconds_counter++;
		if (seconds_counter>=30)
			do_explode();
			
		cli();
			TCNT0 = 0;
		sei();
		blink();
		enable_timer0(true);

	}
	
}
void blink(void)
{

	PORTB ^= _BV(TMR_LED_PIN);  
}

void blink_service_led(void)
{
	for (int i=0; i<=5; i++)
	{
		PORTB ^= _BV(CHECK_LED_PIN);  
		_delay_ms(1000);
	}
}


//check all wires to be connected
bool check_system(void)
{
	
	if ((PINC & (_BV(EXPLODE_IN_PIN) | _BV(NEUTRALIZE_IN_PIN) | _BV(FASTER_IN_PIN1)| _BV(FASTER_IN_PIN2)| _BV(FASTER_IN_PIN3)))==0 
		&& (PIND & (_BV(CHECK_PIN)) ))
	{

		system_check_ok=true;
		return true;

	}
		
	return false;
	
	
	
	
	
	

}

void enable_timer0(bool enable)
{
	if (enable)
		TIMSK |= ( 1 << TOIE0); // enable timer0;
	else 
		TIMSK &= ~( 1 << TOIE0); // disable timer0
	
}

void enable_int0(void)
{
	//initialize interrupts
	GICR = (1<<INT0);					// Enable INT0
	//сбрасываем все биты ISCxx
	MCUCR &= ~( (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00) );
	//настраиваем на срабатывание INT0 по нмзкому уровню
	//MCUCR |= (1<<ISC01)|(1<<ISC00);
	
	
	//нулевое прерывание настроено на срабатывание по низкому уровню
}

void disable_int0(void)
{
	GICR&= ~(1<<INT0);	
}


void init_timer0(void)
{
	//initialize timers
	// Timer/Counter 0 initialization
	// Clock source: System Clock
	// Clock value: 7,813 kHz     (/255/30 to approx 1 sec) (tim0 ovf even 30 interrupt)
	TCCR0=(1<<CS02) | (0<<CS01) | (1<<CS00);

	// initialize counter
	TCNT0 = 0;
}

void init_ports(void)
{
	// Input/Output Ports initialization
	// Port B initialization
	// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRB=(_IN<<DDB7) | (_IN<<DDB6) | (_IN<<DDB5) | (_IN<<DDB4) | (_IN<<DDB3) | (_IN<<DDB2) | (_OUT<<DDB1)| (_OUT<<DDB0);
	// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=P Bit1=P Bit0=P
	PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (_LOW<<PORTB1) | (_LOW<<PORTB0);

	// Port C initialization
	// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
	DDRC=(_IN<<DDC6) | (_IN<<DDC5) | (_IN<<DDC4) | (_IN<<DDC3) | (_IN<<DDC2) | (_IN<<DDC1) | (_IN<<DDC0);
	// State: Bit6=T Bit5=P Bit4=P Bit3=P Bit2=P Bit1=P Bit0=0
	PORTC=(0<<PORTC6) | (_PULLUP<<PORTC5) | (_PULLUP<<PORTC4) | (_PULLUP<<PORTC3) | (_PULLUP<<PORTC2) | (_PULLUP<<PORTC1) | (_PULLUP<<PORTC0);

	// Port D initialization
	// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRD=(_OUT<<DDD7) | (_IN<<DDD6) | (_IN<<DDD5) | (_IN<<DDD4) | (_IN<<DDD3) | (_IN<<DDD2) | (_IN<<DDD1) | (_IN<<DDD0);
	// State: Bit7=0 Bit6=0 Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
	PORTD=(_LOW<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
	
	
	
}

void set_check_led(void)
{
	PORTB |= _BV(CHECK_LED_PIN);  
}

void unset_check_led(void)
{
	PORTB &=~(_BV(CHECK_LED_PIN));
}

bool is_in_service_mode(void)
{
	if (PINC & _BV(SERVICE_MODE_PIN))
		return true;
	else
		return false;
}


void do_explode(void)
{
	//check service mode
	if (is_in_service_mode())
		return;
	if (system_check_ok!=true)
		return;
		
	uart_puts("Exploding...");
	uart_nextline	
	PORTD |= _BV(PD7);
	disable_int0();
	enable_timer0(false);
	exploded =true;	
}

void read_ports_work(void)
{
	
	
	
}


int main(void)
{
	
	init_ports();

	init_timer0();

	
	//initialize UART on 9600
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	
	//enable interrupts
	sei();
	
	
	uart_puts("Initializing...");
	uart_puts("Ok.");
	uart_nextline
	
	
	//ждем пока не будет установлен сервисный режим
	//моргнем светодиождом 3 раза для его проверки
	
	
	uart_puts("Waiting entering in service mode");
	uart_nextline


	loop_until_bit_is_set(PINC,SERVICE_MODE_PIN);
	//мы в сервисном режиме, поморгаем светодиодом 
	blink_service_led();
	unset_check_led();
	
	while (is_in_service_mode())//in service mode when SERVICE_MODE_PIN is HIGH
	{
		uart_puts("Service mode");
		uart_nextline
		if (check_system())
			set_check_led();
		else 
			unset_check_led();
			
	}
	
	if (!check_system())
	{
		unset_check_led();
		uart_puts("System check not passed. Not working");
		uart_nextline
		//зависаем нахрен если не проходит проверка
		while (true)
		{
			
		}
		
	}
		
	
	
	//если горит светодиод, то все провода на месте и можно убирать сервисный режим , переходить в боевой и засыпать
	uart_puts("Out of initial system check. Waiting for int0 in sleep mode to run");
	uart_nextline

	//разрешаем int0 по низкому уровню
	enable_int0();

	//малька проебываемся, засыпаем
	_delay_ms(2000);
	set_sleep_mode(SLEEP_MODE_PWR_DOWN);
	
	sleep_enable();
	sleep_cpu();
	
	
	
	
	//тут мы должны проснуться после сна
	sleep_disable();
	
	uart_puts("Waking up");
	uart_nextline

	
	
	
	
	while(true)
    {
		if (check_pull && !exploded)
		{
			//working
			//проверяем перерезанные провода
			//взрываемся, ускоряемся или обезвреживаемся
			
		}
	
	
	
				
	}



}
естественно будет физический разрыв вывода EXPLODE_PIN

годно такой тест или нет?
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение ARV »

стиль написания кода ужасающий... :facepalm:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

чем же, пардоньте)?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение ARV »

да многим :)))
1. #define F_CPU 8000000UL - самая порочная практика - задавать рабочую частоту внутри Сишного исходника! частота должна задаваться в makefile либо в параметрах проекта.
2. #define _IN 0 и подобное - с нижнего подчеркивания начинаются макросы и другие имена, имеющие статус "для внутреннего пользования системы" - крайне нежелательно объявлять свои макросы в этом стиле
3. #define uart_nextline uart_putc(13); - это вообще фантастика! точка с запятой в конце макроса - дурной стиль. сам макрос по себе - дичь несусветная, ибо перевод строки делается символом \n! то есть далее вместо несуразного

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

   uart_puts("in INT0 ISR");
   uart_nextline
все нормальные люди пишут uart_puts("in INT0 ISR\n");
4. я уж молчу про то, что в WinAVR строки в ОЗУ - это большой расход памяти, совершенно неоправданный...
5. обращение к нестатическим и не инлайн-функциям из обработчика прерываний?! ну-ну... я уж молчу про то, что из обработчика таймера вызывается ОЧЕНЬ медленная функция вывода по USART...

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

Мой уютный бложик... заходите!
Реклама
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

1 - вполне нормальная практика
2 - смотрится немного убого согласен
3 - совершенно согласен с \n, ну пришла эта дурь с дефайном почему-то первой и далее не трогалась
4 - что вы имеете ввиду под строками в ОЗУ
5- только для отладки, более ничего тяжелого в таймере нет
что вы имеете ввиду под статической функцией?

и спрашивал я про такую манеру самотестирования, что описана выше
Реклама
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

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

/*
 * theBomb.c
 *
 * Created: 12.03.2015 20:37:09
 *  Author: andre
 */ 
/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#define IN 0
#define OUT 1
#define PULLUP 1
#define LOW 0
#define HIGH 1

/* 9600 baud */
#define UART_BAUD_RATE      9600

#define uart_nextline uart_putc(13);


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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "uart/uart.h"

volatile unsigned int cnt = 0;
volatile unsigned int seconds_counter =0;
volatile bool check_pull = false;
volatile unsigned int freq = 30;
volatile bool int0_flag=false;
volatile bool exploded = false;
bool service_mode = false;
bool system_check_ok = false;

void enable_timer0(bool enable);
void enable_int0(void);
void disable_int0(void);
void init_timer0(void);
void init_ports(void);
void set_check_led(void);
void do_explode(void);
void read_ports_work(void);
bool is_in_service_mode(void);
void blink(void);
void blink_service_led(void);
void unset_check_led(void);

//названия портов в/в


#define TMR_LED_PIN PB0  //out low
#define CHECK_LED_PIN PB1 //out low
#define RUN_LED_PIN PD4 //out low
#define EXPLODE_OUT_PIN PD7 //out low

#define EXPLODE_IN_PIN PC0 //in pullup
#define NEUTRALIZE_IN_PIN PC1 //in pullup
#define FASTER_IN_PIN1 PC2 //in pullup
#define FASTER_IN_PIN2 PC3 //in pullup
#define FASTER_IN_PIN3 PC4 //in pullup
#define SERVICE_MODE_PIN PC5 //in pullup
#define CHECK_PIN PD2 //in non pullup




//some macro's

//#define loop_until_bit_is_clear(port,bit) \ __asm__ __volatile__ ( \ "L_%=: " "sbic %0, %1" "\n\t" \ "rjmp L_%=" \ : /* no outputs */ : "I" (_SFR_IO_ADDR(port)), "I" (bit) )

//#define loop_until_bit_is_clear(port,bit) __asm__ __volatile__ ( "1: " "sbic %0, %1" "\n\t" "rjmp 1b" : /* no outputs */ : "I" (_SFR_IO_ADDR(port)), "I" (bit) )
/*
PORTC |= _BV(0);  // Set bit 0 only.
PORTC &= ~(_BV(1));  // Clear bit 1 only.
PORTC ^= _BV(7);  // Toggle bit 7 only.




*/

//Interrupt Service Routine for INT0
ISR(INT0_vect)
{
	#ifdef DEBUG
		uart_puts("in INT0 ISR \n");
	#endif
	disable_int0();
	enable_timer0(true); // enable timer0
	check_pull=true;
	
}


// Timer 0 overflow interrupt service routine
ISR(TIMER0_OVF_vect) 
{
	cnt++;
	if (cnt>=freq)
	{
		enable_timer0(false); // disable timer0
		cnt=0;
		#ifdef DEBUG
			uart_puts("timer0 interrupt approx 1 sec \n");
		#endif
		seconds_counter++;
		if (seconds_counter>=30)
			do_explode();
			
		cli();
			TCNT0 = 0;
		sei();
		blink();
		enable_timer0(true);

	}
	
}
void blink(void)
{

	PORTB ^= _BV(TMR_LED_PIN);  
}

void blink_service_led(void)
{
	for (int i=0; i<=5; i++)
	{
		PORTB ^= _BV(CHECK_LED_PIN);  
		_delay_ms(1000);
	}
}


//check all wires to be connected
bool check_system(void)
{
	
	if ((PINC & (_BV(EXPLODE_IN_PIN) | _BV(NEUTRALIZE_IN_PIN) | _BV(FASTER_IN_PIN1)| _BV(FASTER_IN_PIN2)| _BV(FASTER_IN_PIN3)))==0 
		&& (PIND & (_BV(CHECK_PIN)) ))
	{

		system_check_ok=true;
		return true;

	}
		
	return false;
	
}

void enable_timer0(bool enable)
{
	if (enable)
		TIMSK |= ( 1 << TOIE0); // enable timer0;
	else 
		TIMSK &= ~( 1 << TOIE0); // disable timer0
	
}

void enable_int0(void)
{
	//initialize interrupts
	GICR = (1<<INT0);					// Enable INT0
	//сбрасываем все биты ISCxx
	MCUCR &= ~( (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00) );
	//настраиваем на срабатывание INT0 по нмзкому уровню
	//MCUCR |= (1<<ISC01)|(1<<ISC00);
	
	
	//нулевое прерывание настроено на срабатывание по низкому уровню
}

void disable_int0(void)
{
	GICR&= ~(1<<INT0);	
}


void init_timer0(void)
{
	//initialize timers
	// Timer/Counter 0 initialization
	// Clock source: System Clock
	// Clock value: 7,813 kHz     (/255/30 to approx 1 sec) (tim0 ovf even 30 interrupt)
	TCCR0=(1<<CS02) | (0<<CS01) | (1<<CS00);

	// initialize counter
	TCNT0 = 0;
}

void init_ports(void)
{
	// Input/Output Ports initialization
	// Port B initialization
	// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRB=(IN<<DDB7) | (IN<<DDB6) | (IN<<DDB5) | (IN<<DDB4) | (IN<<DDB3) | (IN<<DDB2) | (OUT<<DDB1)| (OUT<<DDB0);
	// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=P Bit1=P Bit0=P
	PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (LOW<<PORTB1) | (LOW<<PORTB0);

	// Port C initialization
	// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
	DDRC=(IN<<DDC6) | (IN<<DDC5) | (IN<<DDC4) | (IN<<DDC3) | (IN<<DDC2) | (IN<<DDC1) | (IN<<DDC0);
	// State: Bit6=T Bit5=P Bit4=P Bit3=P Bit2=P Bit1=P Bit0=0
	PORTC=(0<<PORTC6) | (PULLUP<<PORTC5) | (PULLUP<<PORTC4) | (PULLUP<<PORTC3) | (PULLUP<<PORTC2) | (PULLUP<<PORTC1) | (PULLUP<<PORTC0);

	// Port D initialization
	// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRD=(OUT<<DDD7) | (IN<<DDD6) | (IN<<DDD5) | (IN<<DDD4) | (IN<<DDD3) | (IN<<DDD2) | (IN<<DDD1) | (IN<<DDD0);
	// State: Bit7=0 Bit6=0 Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
	PORTD=(LOW<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
	
	
	
}

void set_check_led(void)
{
	PORTB |= _BV(CHECK_LED_PIN);  
}

void unset_check_led(void)
{
	PORTB &=~(_BV(CHECK_LED_PIN));
}

bool is_in_service_mode(void)
{
	if (PINC & _BV(SERVICE_MODE_PIN))
		return true;
	else
		return false;
}


void do_explode(void)
{
	//check service mode
	if (is_in_service_mode())
		return;
	if (system_check_ok!=true)
		return;
		
	#ifdef DEBUG
		uart_puts("Exploding... \n");
	#endif
	PORTD |= _BV(PD7);
	disable_int0();
	enable_timer0(false);
	exploded =true;	
}

void read_ports_work(void)
{
	
	
	
}


int main(void)
{
	
	init_ports();

	init_timer0();

	//initialize UART on 9600
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	
	//enable interrupts
	sei();
	
	#ifdef DEBUG
		uart_puts("Initializing...Ok \n");
	#endif

	//ждем пока не будет установлен сервисный режим
	//моргнем светодиождом 3 раза для его проверки
	
	
	#ifdef DEBUG
		uart_puts("Waiting entering in service mode \n");
	#endif

	loop_until_bit_is_set(PINC,SERVICE_MODE_PIN);
	//мы в сервисном режиме, поморгаем светодиодом 
	blink_service_led();
	unset_check_led();
	
	while (is_in_service_mode())//in service mode when SERVICE_MODE_PIN is HIGH
	{
	#ifdef DEBUG
		uart_puts("Service mode \n");
	#endif
		if (check_system())
			set_check_led();
		else 
			unset_check_led();
			
	}
	
	if (!check_system())
	{
		unset_check_led();
	#ifdef DEBUG
		uart_puts("System check not passed. Not working \n");
	#endif

		//зависаем нахрен если не проходит проверка
		while (true)
		{
			
		}
		
	}
	
	//если горит светодиод, то все провода на месте и можно убирать сервисный режим , переходить в боевой и засыпать
	#ifdef DEBUG
		uart_puts("Out of initial system check. Waiting for int0 in sleep mode to run \n");
	#endif


	//разрешаем int0 по низкому уровню
	enable_int0();

	//малька проебываемся, засыпаем
	_delay_ms(2000);
	set_sleep_mode(SLEEP_MODE_PWR_DOWN);
	
	sleep_enable();
	sleep_cpu();
	
	//тут мы должны проснуться после сна
	sleep_disable();
	
	#ifdef DEBUG
		uart_puts("Waking up \n");
	#endif
	
	while(true)
    {
		if (check_pull && !exploded)
		{
			//working
			//проверяем перерезанные провода
			//взрываемся, ускоряемся или обезвреживаемся
			
		}
	
	
	
				
	}



}
Пусть будет годнее) Так вернемся к нашим баранам
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

у меня нормальный код

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

	#ifdef DEBUG
		uart_puts("Initializing...Ok\n");
	#endif

	//ждем пока не будет установлен сервисный режим
	//моргнем светодиождом 3 раза для его проверки
	
	
	#ifdef DEBUG
		uart_puts("Waiting entering in service mode\n");
	#endif
c \n не переводит каретку на новую строку -_- в Proteus

UPD а вот \r\n все отлично переводит
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение ARV »

punxer писал(а):1 - вполне нормальная практика
2 - смотрится немного убого согласен
3 - совершенно согласен с \n, ну пришла эта дурь с дефайном почему-то первой и далее не трогалась
4 - что вы имеете ввиду под строками в ОЗУ
5- только для отладки, более ничего тяжелого в таймере нет
что вы имеете ввиду под статической функцией?

и спрашивал я про такую манеру самотестирования, что описана выше
1 - нет, не нормальная, а порочная.
4 - строки, которые Вы передаете в качестве параметра функции, а так же те, которые инициализированы, как переменные, после компиляции приводят к тому, что во flash хранятся эти самые символы, которые затем в нужный момент копируются в ОЗУ, и лишь затем указатель на строку в ОЗУ передается в функцию. то есть напрасная трата ОЗУ и кода на копирование символов из flash в ОЗУ. если и ОЗУ и flash у вас в избытке - можно не заморачиваться, но вообще-то используют только строки во flash, если содержимое этих строк не меняется по ходу работы программы.
5 - хоть для отладки, хоть для чего - это крайне скользкий прием. обычно в обработчиках прерываний вообще не обращаются к другим функциям, и тем более к тем, которые выполняются долго.

под статической функцией я имею ввиду ровно то, что и описано в стандарте языка Си: static - функция, которая не используется более нигде, кроме текущего модуля.
punxer писал(а):у меня нормальный код

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

	#ifdef DEBUG
		uart_puts("Initializing...Ok\n");
	#endif

	//ждем пока не будет установлен сервисный режим
	//моргнем светодиождом 3 раза для его проверки
	
	
	#ifdef DEBUG
		uart_puts("Waiting entering in service mode\n");
	#endif
c \n не переводит каретку на новую строку -_- в Proteus

UPD а вот \r\n все отлично переводит
обычно uart_putc проверяет выводимый символ на равенство \n, и если он именно такой, принудительно дополняет его символом \r - тогда достаточно в нужных местах выводить только \n, что я вам и рекомендовал. если у вас сделано не так - переделайте, и будет вам счастье.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

спасибо за дельные советы и конструктивную критику)
punxer
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт сен 04, 2008 21:15:02
Откуда: Rzhev (Moscow now)
Контактная информация:

Re: atmega8 proteus проблемы с sleep (SLEEP_MODE_POWER_DOWN)

Сообщение punxer »

а вот про строки во Flash... их разве для работы не нужно сначала в RAM загрузить? Это не накладно?

так в чем суть собственно?

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

то есть сбережем RAM. Так?

Если мы используем строки в RAM то нещадно тратим оную, но выполняемся быстрее
Если мы используем PRGMEM, то мы бережем дефицитную RAM но появляются накдадные расходы для подгрузки данных из FLASH?
Ответить

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