Обычный таймер.

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

Спойлер

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

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

char mod = 0;
int FixTime = 5400;
volatile uint8_t i;
volatile uint8_t Sec;
int tp = 0; // time pain - âðåìÿ ñêîëüêî áüåò òîêîì.


ISR(TIM0_OVF_vect)
{
   if (!(++i%4)) //period 1s
   {   PORTB ^= (1<<PB0);
      Sec++;
   }
}

int main(void) {
	
	
	sei ();
   
   int RandTime = 3600 + random()%3600;
   
   DDRB |=(1<<2); //òðàíçèñòîð
   DDRB |=(1<<3); //câåòîäèîä Ç
   DDRB |=(1<<4); //câåòîäèîä Ê
   DDRB &=~(1<<1); //êíîïêà
 
while (1)
{
	
	if (mod==0) //åñëè ïåðâûé ðåæèì âêëþ÷åí, òî êîãäà ïðîøåäøåå âðåìÿ ðàâíî RandTime - ïîäàåì íàïðÿæåíèå íà íîæêó.
	{
			if (Sec >= 10)
			{
					PORTB &=~(1<<2);
					_delay_ms(2000);
					PORTB |= (1<<2);
					_delay_ms(1);
					PORTB &=~(1<<2);
					_delay_ms(4000);
					PORTB |= (1<<2);
					_delay_ms(1);
					Sec = 0;
			}
			
			        
				
			
	}
	else //åñëè âòîðîé ðåæèì âêëþ÷åí, òî êîãäà ïðîøåäøåå âðåìÿ ðàâíî FixTime - ïîäàåì íàïðÿæåíèå íà íîæêó.
	{
			if (Sec >= 5)
			{
					PORTB &=~(1<<2);
					_delay_ms(1000);
					PORTB |= (1<<2);
					_delay_ms(1);
					Sec = 0;
			}
			        
						
	}

	if (PINB & (1<<1)) //Åñëè íà íîæêå åñòü íàïðÿæåíèå òî:
	{
		if (mod==0) //Åñëè âêëþ÷åí ðåæèì 0, ìåíÿåì åãî íà 1
		{
			mod = 1;
			
			Sec = 0; //îáíóëÿåì âðåìÿ

			PORTB |= (1<<3);
			_delay_ms(100);
			PORTB &=~(1<<3);



			_delay_ms(1000);
			
			
		}
		else //Åñëè âêëþ÷åí 1 ðåæèì, ìåíÿåì åãî íà 0
		{
			mod = 0;
			
			Sec = 0; //îáíóëÿåì âðåìÿ

			PORTB |= (1<<3);
			_delay_ms(100);
			PORTB &=~(1<<3);
			_delay_ms(500);
			PORTB |= (1<<3);
			_delay_ms(100);
			PORTB &=~(1<<3);


			_delay_ms(1000);
			

		}

	}


}

    
}
Вот такой код пытаюсь использовать. Но почему то он не работает. Я так понимаю - переменная Sec не возрастает со временем, поэтому и циклы не запускаются.
Не подскажите, в чем ошибка?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

Где в коде настройка таймера?
Реклама
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

Спойлер

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

ISR(TIM0_OVF_vect)
{
   if (!(++i%4)) //period 1s
   {   PORTB ^= (1<<PB0);
      Sec++;
   }
}
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Это обработчик прерывания :)
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

А нужно что-то вроде:

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

// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x02;
Это из CV.
Docendo discimus
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Я бы еще заменил
if (!(++i%4)) //period 1s
на
if (!(++i&0x03)) //period 1s

Сложных математических операций надо избегать по возможности, особенно в прерываниях, хотя возможно оптимизатор это сам сделал.
Но еще лучше настроить таймер так, чтобы прерывание возникало сразу с нужным периодом.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

Аlex писал(а):Это обработчик прерывания :)
Ну так понятно, но работает же как часы - каждую секунду, с небольшой погрешностью добавляет к переменной Sec+1. Однако у меня почему то не добавляется. В чем проблема?
Z_h_e писал(а):Но еще лучше настроить таймер так, чтобы прерывание возникало сразу с нужным периодом.
А как бы это выглядело в коде? :oops: И если мой написан хоть и грубо, но правильно, почему он не работает?
pyzhman писал(а):А нужно что-то вроде:

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

// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x02;
Это из CV.
А что такое CV? Не могли бы подсказать, пожалуйста, как бы это выглядело в коде?
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Вам уже указали ошибку в коде. Прочитайте еще раз.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

Z_h_e писал(а):Вам уже указали ошибку в коде. Прочитайте еще раз.
Ну 1.
if (!(++i%4)) //period 1s
на
if (!(++i&0x03)) //period 1s

А 2. вот не понял, что это такое?
СпойлерTCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x02;
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Прочитайте пост Мурика и потом подумайте. А то что я Вам указал, это не ошибка.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

Перед разрешением прерываний поставить:

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

TCCR0B=0x02; // включить таймер
TIMSK0=0x02; // разрешить прерывание при переполнении таймера 0
Docendo discimus
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Нас либо троллят, либо появился человек, у которого напрочь отсутствует логическое мышление :facepalm:
Написал обработку прерывания, причём уверен в том, что он вызывается 1 раз в 250 мс. Только вот откуда такие данный взялись, без настройки таймера, с какого потолка ? :facepalm:
Мало того, подобное гуглится за считанные минуты. В интернете, примеров с применением таймеров - как грязи...
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Да нет, похоже не тролит. Автору кода теперь вопросы задает в соседней ветке.
sTRog, Вам уже сколько раз сказали, что таймер надо запустить. Кроме того надо установить соответствующую маску разрешения прерывания.
pyzhman, Вам кусок кода дал. Если непонятно что это, трудно посмотреть в ДШ для чего регистры? Кроме того, инициализация данных регистров есть там, откуда Вы взяли код.

Ваши вопросы говорят о том, что Вы не имеете малейшего представления как работает МК. Читайте и читайте.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

sTRog писал(а):Вот такой код пытаюсь использовать...
Аlex писал(а):...Написал обработку прерывания...
Использовал совсем не означает, что написал.
upd.
Что интересно, у JackSmith'а всё аккуратно написано.
Docendo discimus
Контактная информация:
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

pyzhman писал(а):
sTRog писал(а):Вот такой код пытаюсь использовать...
Аlex писал(а):...Написал обработку прерывания...
Использовал совсем не означает, что написал.
upd.
Что интересно, у JackSmith'а всё аккуратно написано.
Нет, сего не отрицаю, пользуюсь кодом который любезно предоставил JackSmith. Просто было бы дольше описывать откуда и что я взял. Ну ладно.
Интересный момент, если добавляю таймер написанный JackSmith. У меня перестает работать кнопка переключения режимов. Причем был код,
Спойлер

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

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

char mod = 0;
int FixTime = 5400;
int tp = 0; // time pain - время сколько бьет током.
volatile uint8_t i;
volatile uint8_t Sec;



int main(void) {
	

	


   int RandTime = 3600 + random()%3600;
   
   DDRB |=(1<<2); //транзистор
   DDRB |=(1<<3); //cветодиод З
   DDRB |=(1<<4); //cветодиод К
   DDRB &=~(1<<1); //кнопка
 
while (1)
{
	
	if (mod==0) //если первый режим включен, то когда прошедшее время равно RandTime - подаем напряжение на ножку.
	{
			
					PORTB &=~(1<<2);
					_delay_ms(2000);
					PORTB |= (1<<2);
					_delay_ms(1);
					PORTB &=~(1<<2);
					_delay_ms(4000);
					PORTB |= (1<<2);
					_delay_ms(1);
					Sec = 0;
			
			
			        
				
			
	}
	else //если второй режим включен, то когда прошедшее время равно FixTime - подаем напряжение на ножку.
	{
			
					PORTB &=~(1<<2);
					_delay_ms(1000);
					PORTB |= (1<<2);
					_delay_ms(1);
					Sec = 0;
			
			        
						
	}

	if (PINB & (1<<1)) //Если на ножке есть напряжение то:
	{
		if (mod==0) //Если включен режим 0, меняем его на 1
		{
			mod = 1;
			
			Sec = 0; //обнуляем время

			PORTB |= (1<<3);
			_delay_ms(100);
			PORTB &=~(1<<3);



			_delay_ms(1000);
			
			
		}
		else //Если включен 1 режим, меняем его на 0
		{
			mod = 0;
			
			Sec = 0; //обнуляем время

			PORTB |= (1<<3);
			_delay_ms(100);
			PORTB &=~(1<<3);
			_delay_ms(500);
			PORTB |= (1<<3);
			_delay_ms(100);
			PORTB &=~(1<<3);


			_delay_ms(1000);
			

		}

	}


}
Я в него добавил обработчик секунд - кнопка переключения режимов перестала работать. Хотя больше ничего не менял. Удалил то что добавил, но кнопка работать не начала.
Что за магия такая?
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

Прежде чем добавлять, разберитесь что и как работает в программе и как хотелось бы, чтобы она работала. За вас здесь никто писать не будет. Начните с алгоритма, а не со вставок непонятных (для вас) кусков в непонятные (для вас) программы.
Docendo discimus
Контактная информация:
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

Еще интересный факт этого таймера - что он сам переключает режимы.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Прям таки шайтан-таймер :) . Программа работает именно так, как Вы ее написали.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Встал на лапы
Сообщения: 131
Зарегистрирован: Вс май 08, 2016 22:45:48

Сообщение sTRog »

Удалил строки
PORTB ^= (1<<PB0);
и
DDRB |= (1<<PB0);
Все заработало, переключаться перестало.

Хотя и дает погрешность 1 сек на 10 сек.

Добавлено after 3 hours 11 minutes 20 seconds:
только почему таймер считает 8.5. сек вместо 10, т.е. 1.5 сек погрешность. Как можно исправить?
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

sTRog писал(а):Как можно исправить?
Почитать даташит, раздел таймера, и настроить таймер правильно.
Ответить

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