Страница 1 из 2

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

Добавлено: Сб окт 29, 2016 21:14:26
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 не возрастает со временем, поэтому и циклы не запускаются.
Не подскажите, в чем ошибка?

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

Добавлено: Сб окт 29, 2016 21:51:47
Мурик
Где в коде настройка таймера?

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

Добавлено: Сб окт 29, 2016 22:37:13
sTRog
Спойлер

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

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

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

Добавлено: Сб окт 29, 2016 22:54:15
Аlex
Это обработчик прерывания :)

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

Добавлено: Вс окт 30, 2016 05:13:13
pyzhman
А нужно что-то вроде:

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

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

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x02;
Это из CV.

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

Добавлено: Вс окт 30, 2016 06:03:13
Z_h_e
Я бы еще заменил
if (!(++i%4)) //period 1s
на
if (!(++i&0x03)) //period 1s

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

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

Добавлено: Вс окт 30, 2016 07:57:12
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? Не могли бы подсказать, пожалуйста, как бы это выглядело в коде?

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

Добавлено: Вс окт 30, 2016 08:16:21
Z_h_e
Вам уже указали ошибку в коде. Прочитайте еще раз.

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

Добавлено: Вс окт 30, 2016 09:36:01
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;

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

Добавлено: Вс окт 30, 2016 09:40:03
Z_h_e
Прочитайте пост Мурика и потом подумайте. А то что я Вам указал, это не ошибка.

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

Добавлено: Вс окт 30, 2016 11:07:47
pyzhman
Перед разрешением прерываний поставить:

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

TCCR0B=0x02; // включить таймер
TIMSK0=0x02; // разрешить прерывание при переполнении таймера 0

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

Добавлено: Вс окт 30, 2016 11:15:44
Аlex
Нас либо троллят, либо появился человек, у которого напрочь отсутствует логическое мышление :facepalm:
Написал обработку прерывания, причём уверен в том, что он вызывается 1 раз в 250 мс. Только вот откуда такие данный взялись, без настройки таймера, с какого потолка ? :facepalm:
Мало того, подобное гуглится за считанные минуты. В интернете, примеров с применением таймеров - как грязи...

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

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

Ваши вопросы говорят о том, что Вы не имеете малейшего представления как работает МК. Читайте и читайте.

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

Добавлено: Вс окт 30, 2016 15:40:43
pyzhman
sTRog писал(а):Вот такой код пытаюсь использовать...
Аlex писал(а):...Написал обработку прерывания...
Использовал совсем не означает, что написал.
upd.
Что интересно, у JackSmith'а всё аккуратно написано.

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

Добавлено: Вс окт 30, 2016 15:50:15
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);
			

		}

	}


}
Я в него добавил обработчик секунд - кнопка переключения режимов перестала работать. Хотя больше ничего не менял. Удалил то что добавил, но кнопка работать не начала.
Что за магия такая?

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

Добавлено: Вс окт 30, 2016 16:30:01
pyzhman
Прежде чем добавлять, разберитесь что и как работает в программе и как хотелось бы, чтобы она работала. За вас здесь никто писать не будет. Начните с алгоритма, а не со вставок непонятных (для вас) кусков в непонятные (для вас) программы.

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

Добавлено: Вс окт 30, 2016 16:51:54
sTRog
Еще интересный факт этого таймера - что он сам переключает режимы.

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

Добавлено: Вс окт 30, 2016 16:54:24
Z_h_e
Прям таки шайтан-таймер :) . Программа работает именно так, как Вы ее написали.

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

Добавлено: Вс окт 30, 2016 20:18:03
sTRog
Удалил строки
PORTB ^= (1<<PB0);
и
DDRB |= (1<<PB0);
Все заработало, переключаться перестало.

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

Добавлено after 3 hours 11 minutes 20 seconds:
только почему таймер считает 8.5. сек вместо 10, т.е. 1.5 сек погрешность. Как можно исправить?

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

Добавлено: Вс окт 30, 2016 22:44:46
Аlex
sTRog писал(а):Как можно исправить?
Почитать даташит, раздел таймера, и настроить таймер правильно.