Таймеры/счётчики в AVR

Обсуждаем контроллеры компании Atmel.
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

fulky писал(а):сделать по вектору TIMER1_COMPA и через сравнение с OCR1A??
Да. Правда непонятно зачем задействовать ещё одно прерывание.
Как записать в ваших кыржиках не знаю, но сделал бы так

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

F_CPU=8000000
OCR0A=250*F_CPU/1000000/8-1; задание 250мкс интервала

T_HOUR=3600*1000000/250
T_MIN=60*1000000/250
T_SEC=1000000/250
T1=HOUR1*T_HOUR+MIN1*T_MIN+SEC1*T_SEC
T2=HOUR2*T_HOUR+MIN2*T_MIN+SEC2*T_SEC
Похожая задача была здесь
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

Есть у кого функция задержки времени без _delay_ms ,на таймере если еще и на нулевом то вобще гуд ). камень мк atmega8. Задержки до от 100ms до 10s.
andrei23061996@gmail.com
.................................................................................................................
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Задержка на T0 ATmega8
Спойлер

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

.include "m8def.inc"
.equ F_CPU=8000000	;тактовая частота 8 МГц

.equ	D=100000*F_CPU/1000000	; для примера 100мс

.equ	D_HIGH=$70	; ячейки, хранящие задержку D/256
.equ	D_MIDL=$71	; ячейки, хранящие задержку D/256
.equ	D_LOW =$72	;

.cseg
.org 0
	RJMP START         ;переход на обработку сброса

.org 9
T0_OVER:
	SUBI	R27,BYTE1(1)
	SBCI	R26,BYTE2(1)
	SBCI	R25,BYTE3(1)
	BRNE	NO_DELAY
	RET
NO_DELAY:
	RETI

START:
	LDI ZH, high(RAMEND)      ;Инциализация стека
	LDI ZL, low(RAMEND)       ;
	OUT SPH,ZH               ;
	OUT SPL,ZL               ;

	LDI	R25,BYTE3(D/256)	; для примера
	LDI	R26,BYTE2(D/256)	; для примера
	LDI	R27,BYTE1(D/256)	;
	STS	D_HIGH,R25			;
	STS	D_MIDL,R26			;
	STS	D_LOW,R27			;
GO:
	LDS	R25,D_HIGH	; загрузка D/256
	LDS	R26,D_MIDL	;
	LDS	R27,D_LOW
	
	LDI	R21,1<<SE
	OUT	MCUCR,R21

	LDI	R21,1<<TOIE0
	OUT	TIMSK,R21
	OUT	TIFR,R21

	LDI	R21,1<<CS00	;F_CPU/1
	OUT	TCCR0,R21

	SEI
WAIT:
	SLEEP
	BRIE	WAIT
	RJMP	GO
.EXIT
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

Наверно гуд задержка реализована) , асм просто не знаю (. ее можно как ассемблерную вставку в си использовать ?
andrei23061996@gmail.com
.................................................................................................................
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Таймеры/счётчики в AVR

Сообщение ARV »

7seg писал(а):Есть у кого функция задержки времени без _delay_ms ,на таймере если еще и на нулевом то вобще гуд
а самому написать - не гуд?

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

заводите себе глобальную переменную-стетчик, например delay. размер этой переменной должен вмещать нужную вам предельно большую задержку. т.е. если вы хотите до 10 секунд, а период тиков таймера 1 мс, максимальная задержка будет 10000 тиков таймера, т.е. переменная будет uint16_t delay; если счетчик вышел больше 1 байта, то дополнительно заводите себе переменную-флаг timeout (однобайтную!), которая и будет означать истечение задержки.

ну и теперь делаете обработчик прерываний таймера

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

ISR(TIMER0_OVF_vect){ // я дли примера взял по переполнению, можно любое иное прерывание
   if(delay){
    delay--;
    timeout = 1;
   }
}
еще делаете функцию установки задержки

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

#include <util/atomic.h>
void set_delay(uint16_t ms){
   timeout = 0;
   ATOMIC_BLOCK(ATOMIC_RESTORE_STATE){
      delay = ms;
   }
}
вот почти и все. в нужном вам месте вызываете эту функцию set_delay и затем время от времени проверяете timeout - как только эта переменная станет не равна нулю - задержка истекла.

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

while(1){ // главный цикл
   if(timeout){
      PORTB ^= _BV(PB0); // мигаем светодиодом на порту PB0
      set_delay(1000); // с периодом 2 секунды
   }
   // а тут занимается остальными делами в главном цикле
}
если delay у вас однобайтным вышел, то timeout не требуется, можно смотреть сразу на delay: обнулилась - время вышло. ну и atomic.h в этом случае не требуется
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Таймеры/счётчики в AVR

Сообщение Demiurg »

[uquote="7seg",url="/forum/viewtopic.php?p=3218815#p3218815"]Есть у кого функция задержки времени без _delay_ms ,на таймере если еще и на нулевом то вобще гуд ). камень мк atmega8. Задержки до от 100ms до 10s.[/uquote]
1-ый вариант:автоматное программирование и программные таймеры. Почитайте цикл статей. Будет очень полезно. Я многое почерпнул там.

2-ой вариант: настраивается самый ненужный таймер на 1 мс. В основном цикле проверять признак того, что таймер оттикал 1 мс и дальше работает ваша фантазия.

soft_timer.h
Спойлер

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

//==================
#ifndef SOFT_TIMERS_H

#define SOFT_TIMERS_H

#include "soft_timers.h"

#include "main_def_func.h"
//==================

//==================
#define ST_TCNT         TCNT2
#define ST_TIMSK        TIMSK
#define ST_OCIE         OCIE2
#define ST_OCR          OCR2
#define ST_TCCR         TCCR2
#define CS0             CS20
#define CS1             CS21
#define CS2             CS22
//==================

//==================
typedef struct soft_timer
{
   bool status;
   u08 sys_tick_prev;
   u16 cnt;       // Counter.
   u16 period;    // Period.
} soft_timer;
//==================

//==================
void init_soft_timers (void);

#define handle_soft_timer(a) _handle_soft_timer (&a)
bool _handle_soft_timer (void *ptr_timer);

#define set_soft_timer(a,b,c) _set_soft_timer (&a, b, c)
void _set_soft_timer (void *ptr_timer, u16 time, u16 period);

#define reset_soft_timer(a) _reset_soft_timer (&a)
void _reset_soft_timer (void *ptr_timer);
//==================

//==================
extern bool tick;

void Main_Timer_Init (void);
bool Main_Get_Tick (void);
//==================

#endif
soft_timer.c
Спойлер

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

//==================
// Реализация программных таймеров.
// Примечание. Важно!!!!!!!!!!!!!!!
// При смене состояния конечного автомата нужно сбросить
// все таймеры, которые используются в этом состоянии. Иначе может быть
// следующая ситуация: если таймер уже использовался в
// текущем состоянии и флаг EN установлен, то по окончании времени
// выполнится соответствующий код.
//--------------------- Пример использования -----------------------------
// set_soft_timer (ST_LED_2_BLINK, 50, 50); // Установка таймера.
// if (handle_soft_timer (ST_LED_2_BLINK))  // Проверка таймера.
//==================

//==================
#include "soft_timers.h"
//==================

//==================
static u08 sys_tick;
//==================

//==================
#pragma vector = TIMER2_COMP_vect
__interrupt void SysTimerComp (void)
{
   ST_OCR += 250;
   sys_tick++;
}
//==================

//==================
void init_soft_timers (void)
{
   sys_tick = 0;
   ST_TCNT = 0;
   ST_OCR = 250;
   ST_TCCR |= (1<<CS2);
   set_bit (ST_TIMSK, ST_OCIE);
}
//------------------------------------------------------------------------
void _set_soft_timer (void *ptr_timer, u16 time, u16 period)
{
   struct soft_timer *ptr = ptr_timer;

   ptr -> status = true;

   if (time == 0)
      ptr -> sys_tick_prev = ~sys_tick;
   else
      ptr -> sys_tick_prev = sys_tick;

   ptr -> cnt = time;
   ptr -> period = period;
}
//------------------------------------------------------------------------
bool _handle_soft_timer (void *ptr_timer)
{
   struct soft_timer *ptr = ptr_timer;

   if (ptr -> status)
   {
      if (ptr -> sys_tick_prev != sys_tick)
      {
         ptr -> sys_tick_prev = sys_tick;

         if (ptr -> cnt == 0)
         {
            if (ptr -> period != 0) ptr -> cnt = ptr -> period;
            return true;
         }
         else
         {
            ptr -> cnt--;

            if (ptr -> cnt == 0)
            {
               if (ptr -> period != 0) ptr -> cnt = ptr -> period;
               return true;
            }
         }
      }
   }

   return false;
}

void _reset_soft_timer (void *ptr_timer)
{
   struct soft_timer *ptr = ptr_timer;

   ptr -> status = 0;
   ptr -> sys_tick_prev = 0;
   ptr -> cnt = 0;
   ptr -> period = 0;
}
//==================
Примеры использования тут.
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

[uquote="7seg",url="/forum/viewtopic.php?p=3218952#p3218952"]... ее можно как ассемблерную вставку в си использовать ?[/uquote] Если выдержать соглашение использования вставок, можно.
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

Все таки решил попробовать что нибудь свое сотворить.)
Создал таймер прерывание каждую ms, в нем и соответственно подсчет ms,ss,mm. ( на самом деле таймера допустимы и с условным временем,то есть 1s может быть примерно равна 1s ).

Также написал пару функций OffAfterTimeSS и OnAfterTimeSS ,ВключитьЧерезУказаноеВремя и выключить соответственно.
Но есть одна переменная которая отвечает за фиксирование времени отсчета TimeCountingON и очевидно что при вызове функции более чем одного раза она изменяться и функция OnAfterTimeSS/OffAfterTimeSS перестает работать коректо.
Как более правильно зафиксировать время TimeCountingON фиксировать ?

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

ISR (TIMER0_OVF_vect)
{
	TCNT0=125;
	VarMS++;
	if(VarMS==1000)
	{
		VarSS++;
		VarMS=0;
	}
	if (VarSS==60)
	{
		VarMM++;
		VarSS=0;
	}
	if (VarMM==60)
	{
		VarMM=0;
	}
}
uint8_t FlagTImeON=0; //Флаг для захвата времени отсчета.
uint8_t TimeCountingON=0;//Время Отсчета
uint8_t FlagTImeOff=0;
uint8_t TimeCountingOff=0;
uint8_t OnAfterTimeSS(uint8_t TimeSS,uint8_t CurrentFlag)
{
	if (FlagTImeON==0)
	{
		TimeCountingON=VarSS;			//Время Отсчета
		FlagTImeON=1;
	}
	uint8_t TimeCurrent=VarSS;			//Текущие время
	uint8_t OutFlag=0;
	if ((TimeCurrent-TimeCountingON) == TimeSS)
	{
		OutFlag=1;
	}
	else OutFlag=CurrentFlag;
	return OutFlag;
}

uint8_t OffAfterTimeSS(uint8_t TimeSS,uint8_t CurrentFlag)
{
	if (FlagTImeOff==0)
	{
		TimeCountingOff=VarSS;			//Время Отсчета
		FlagTImeOff=1;
	}
	uint8_t TimeCurrent=VarSS;			//Текущие время
	uint8_t OutFlag=0;
	if ((TimeCurrent-TimeCountingOff) == TimeSS)
	{
		OutFlag=0;
		FlagTImeON=0;
	}
	else OutFlag=CurrentFlag;
	return OutFlag;
}
}
andrei23061996@gmail.com
.................................................................................................................
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Таймеры/счётчики в AVR

Сообщение Ivanoff-iv »

попробуй как в ардуинах - переменная (R.O.) отсчитывает время от включения, а когда нужен интервал - берешь свою переменную, в момент начала интервала записываешь в неё значение "часов", а продолжительность интервала = "часы"-"момент начала интервала". этих моментов можно сколько угодно наделать, не сбивая "часов".
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

Я примерно по такому принципу выше и делал. но как в функции организовать "момент начала интервала" ?) что бы при повторном вызове функции (пока к примеру первый ее вызов еще не отработал) этот момент не перезаписался.
andrei23061996@gmail.com
.................................................................................................................
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Таймеры/счётчики в AVR

Сообщение Ivanoff-iv »

сорри пропустил, с телефона неудобно ког понимать, увидел...
а до скольки раз планируется запускать функции?
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

неизвестно.(
andrei23061996@gmail.com
.................................................................................................................
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Таймеры/счётчики в AVR

Сообщение Ivanoff-iv »

[uquote="7seg",url="/forum/viewtopic.php?p=3219833#p3219833"]неизвестно.([/uquote] тут динамическим выделением памяти попахивает... а хоть максимально сколько?
взять по максимуму и раздуть массив, по мне, будет проще.
хотя... может кто чего и насоветует
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

А работает ли функция malloc() на avr си ?
andrei23061996@gmail.com
.................................................................................................................
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Таймеры/счётчики в AVR

Сообщение Ivanoff-iv »

да, но память контроллера не безгранична
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
7seg
Потрогал лапой паяльник
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Re: Таймеры/счётчики в AVR

Сообщение 7seg »

Уже почитал что использовать функции динамического выделения опасно на мк.
примерно прикинул что одновременно таймеров больше5 шт работать не будет. Поэтому пробую загонять данные в массив из 10 элементов(двух кратный запас).
Но пока как то коряво получается (.
Код:

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

volatile uint16_t VarMS=0;
volatile uint8_t VarSS=0;
volatile uint8_t VarMM=0;
ISR (TIMER0_OVF_vect)
{
	TCNT0=125;
	VarMS++;
	if(VarMS==1000)
	{
		VarSS++;
		VarMS=0;
	}
	if (VarSS==60)
	{
		VarMM++;
		VarSS=0;
	}
	if (VarMM==60)
	{
		VarMM=0;
	}
}
volatile uint8_t FlagTIme[10]={0};
volatile uint8_t TimeCountingON[10]={0};

uint8_t OnAfterTimeSS(uint8_t TimeSS,uint8_t CurrentFlag)
{
	uint8_t NumberTimer=0;
	if (CurrentFlag==0)
	{
		if (FlagTIme[NumberTimer]==0)
		{
			TimeCountingON[NumberTimer]=VarSS;			//Время Отсчета
			FlagTIme[NumberTimer]=1;
		}
		else
		{
			NumberTimer++;
			if (NumberTimer==10)
			{
				NumberTimer=0;
			}
		}
	}
	uint8_t TimeCurrent=VarSS;			//Текущие время
	uint8_t OutFlag=0;
	if ((TimeCurrent-TimeCountingON[NumberTimer]) == TimeSS)
	{
		OutFlag=1;
	}
	else 
	{
		OutFlag=CurrentFlag;
	}
	return OutFlag;
}
andrei23061996@gmail.com
.................................................................................................................
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Таймеры/счётчики в AVR

Сообщение Ivanoff-iv »

а может тогда как в микроволновке - обратный отсчет

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

ISR (TIMER0_OVF_vect)
{
for (i=0,i<10,i++)
  {
  if (M[i]) 
     {
     M[i]--;
     if (!(M[i])) "действие";     
     };
  };
}
тут М - массив на 10 элементов
при каждом переполнении цикл пробегает по массиву, находит элементы !=0 их убавляет, и если среди них есть "дотикавшие" выполняет действие. (для включения и выключения разные циклы).
функцию для внесения задания: перебор до первого "0" и внесение в ячейку M значения задержки (в количестве переполнений)
и часы общие не понадобятся.

Добавлено after 1 hour 4 minutes 24 seconds:

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

void set_t (unsigned int time)
{
for (i=0,i<10,i++)
   {
    if (!(M[i])) {M[i]=time; break;};
   };
}
примерно так. тоже для включения и выключения разные функции. если будут перебраны все 10 таймеров и не найдётся свободного - изменения в расписание внесены не будут.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
vispower
Нашел транзистор. Понюхал.
Сообщения: 181
Зарегистрирован: Ср фев 18, 2009 13:59:46

Re: Таймеры/счётчики в AVR

Сообщение vispower »

братцы, подскажите неучу, научился кексы закачивать в аруину уно, следующий этап написать простенькую прогу на Ассемблере. в пробнике проинициализировал Т2 на сравнение, прерывание приходит, идет на обработку по вектору, но в стеке записан какой то левый адрес т.е. по ret возвращается не в цикл-ожидание окуда вылетел по прерыванию, а гораздо выше. Почему так?
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Таймеры/счётчики в AVR

Сообщение Demiurg »

1 - Скорее всего не инициализирован стек.
2 - Вольфганг Трамперт - AVR-RISC микроконтроллеры фирмы ATMEL.
vispower
Нашел транзистор. Понюхал.
Сообщения: 181
Зарегистрирован: Ср фев 18, 2009 13:59:46

Re: Таймеры/счётчики в AVR

Сообщение vispower »

[uquote="Demiurg",url="/forum/viewtopic.php?p=3220868#p3220868"]1 - Скорее всего не инициализирован стек.
2 - Вольфганг Трамперт - AVR-RISC микроконтроллеры фирмы ATMEL.[/uquote]
стек проинициализировал по мануалу, а вот второе не понял.
Вложения
MyOneProj.asm
(18.24 КБ) 233 скачивания
Ответить

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