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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

rxstart1 писал(а):Глупость пишите таймер не считает импульсы он просто тикает
Почему же. Если таймер заставить тактироваться от внешнего источника, он как раз-таки будет считать импульсы.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
FAIR
Родился
Сообщения: 6
Зарегистрирован: Пн мар 02, 2015 15:16:00

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

Сообщение FAIR »

Gudd-Head писал(а):Если таймер заставить тактироваться от внешнего источника, он как раз-таки будет считать импульсы.

Так можно ли заставить таймер 2 считать импульсы от внешнего источника? :)
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

FAIR писал(а):таймер\счетчик 2 в Atmega88, считал импульсы так,как делает это таймер\счетчик 0 с пина T0
Насколько я понял, это можно сделать с пина TOSC1.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

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

Сообщение akl »

Да, можно подать на XTAL1/TOSC1/PB6 сигнал. Перевести Т2 в асинхронный режим и тактироваться от встроенного RC-генератора.
FAIR
Родился
Сообщения: 6
Зарегистрирован: Пн мар 02, 2015 15:16:00

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

Сообщение FAIR »

Всем спасибо за ответы. Получилось, надо было выставить 1 в битах AS2 и EXCLK, и подать сигнал на TOSC1.
Tolibbass
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Ср янв 07, 2015 15:37:52

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

Сообщение Tolibbass »

Есть вопросы.... Везде пушут про прерывания, т.е. настраиваешь таймер и в нужный момент программа прерывается. А если мне надо чтоб какое-то действие(например время работы нагрузки с ПОРТА В) было 10сек???? Но в тоже время есть сигнал который может в любой момент прервать это действие. как тогда прописывается на СИ????
Аватара пользователя
Flash.#13
Держит паяльник хвостом
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

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

Сообщение Flash.#13 »

Tolibbass прерываний у МК достаточно много, во например прерывания меги8:

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

.equ   INT0addr=$001   ; External Interrupt0 Vector Address
.equ   INT1addr=$002   ; External Interrupt1 Vector Address
.equ   OC2addr =$003   ; Output Compare2 Interrupt Vector Address
.equ   OVF2addr=$004   ; Overflow2 Interrupt Vector Address
.equ   ICP1addr=$005   ; Input Capture1 Interrupt Vector Address
.equ   OC1Aaddr=$006   ; Output Compare1A Interrupt Vector Address
.equ   OC1Baddr=$007   ; Output Compare1B Interrupt Vector Address
.equ   OVF1addr=$008   ; Overflow1 Interrupt Vector Address
.equ   OVF0addr=$009   ; Overflow0 Interrupt Vector Address
.equ   SPIaddr =$00a   ; SPI Interrupt Vector Address
.equ   URXCaddr=$00b   ; USART Receive Complete Interrupt Vector Address
.equ   UDREaddr=$00c   ; USART Data Register Empty Interrupt Vector Address
.equ   UTXCaddr=$00d   ; USART Transmit Complete Interrupt Vector Address
.equ   ADCCaddr=$00e   ; ADC Interrupt Vector Address
.equ   ERDYaddr=$00f   ; EEPROM Interrupt Vector Address
.equ   ACIaddr =$010   ; Analog Comparator Interrupt Vector Address
.equ   TWIaddr =$011   ; Irq. vector address for Two-Wire Interface
.equ   SPMaddr =$012   ; SPM complete Interrupt Vector Address
.equ   SPMRaddr =$012  ; SPM complete Interrupt Vector Address


Многие вопросы отпадают сами собой со временем. И конкретно по вашей задаче: откл. портХ по таймеру в 10 секунд.

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

1) Настраиваем таймер2(16бит) с максимальной задержкой 1024, при 1МГц это даст около 0.25сек(4Гц);
2) По прерыванию таймера делаем Х=Х+1;
4) Если действие=не надо, то Х=0
3) Если Х>40 (10секунд), то ОТКЛ. ножку на портХ

Еще как вариант можно ввести контрольный бит, и проверять его состояние, как разрешающее в управлении нагрузкой, ну вариантов масса))
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

Tolibbass писал(а):Но в тоже время есть сигнал который может в любой момент прервать это действие. как тогда прописывается на СИ????
Без разницы, на Сях это прописывается или на АСМе. Важно понимать алгоритм действий.

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

таймер2(16бит) с максимальной задержкой 1024, при 1МГц это даст около
Странно. У меня получилось 67 секунд при тактовой 1 МГц и предделителе 1024.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Tolibbass
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Ср янв 07, 2015 15:37:52

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

Сообщение Tolibbass »

Блин все равно не очень понятно.... Есть такая схемка. надо чтоб при разомкнутом D1 подавался сигнал на В0. при этом В0 отключается при замыкании D1 или при работе больше 10 сек. потом также со вторым двигателем.
вот как раз алгоритма я и не могу понять(((((



#include <tiny2313.h>
#include <delay.h>

void main(void)
{

PORTB=0x00;
DDRB=0xFF;

PORTD=0x7F;
DDRD=0x00;

ACSR=0x80;
while (1)
{
while (PIND.0==1){}
delay_ms(500);
if(PIND.1==1)
{PORTB.0=1;}

while(PIND.1==1){}
delay_us(500);
if(PIND.1==0)
{PORTB.0=0;}
Вложения
1.rar
(14.6 КБ) 176 скачиваний
Последний раз редактировалось Tolibbass Пт мар 06, 2015 14:32:31, всего редактировалось 1 раз.
Аватара пользователя
Flash.#13
Держит паяльник хвостом
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

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

Сообщение Flash.#13 »

Gudd-Head писал(а):...67 секунд при тактовой 1 МГц и предделителе 1024.

Моя вина, протупил, это 8бит счетчик даст 0,25с при 1024 с 1МГц :facepalm:

Tolibbass Лично мне в такой ситуации удобнее пользоваться байтом состояния, в котором отдельные биты будут разрешать ножки порта (двигатели). SBRC и SBRS позволяют легко проверять и организововать переходы по битах в регистре, а ORI и ANDI записывать в нужный бит регистра нули или единицы.

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

sbrc R16, x         ;if pinX,n='1' then do
sbrs R16, x         ;if pinX,n='0' then do

ori R16,  0b00010000                        ;sbiR16/4, контроль, запишет "1"
andi R16, 0b11101111                        ;cbiR16/4, контроль, запишет "0"
*Но к сожалению код пишу исключительно на ассемблере...
Последний раз редактировалось Flash.#13 Пт мар 06, 2015 14:45:37, всего редактировалось 1 раз.
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Tolibbass
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Ср янв 07, 2015 15:37:52

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

Сообщение Tolibbass »

[quote
Многие вопросы отпадают сами собой со временем. И конкретно по вашей задаче: откл. портХ по таймеру в 10 секунд.

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

1) Настраиваем таймер2(16бит) с максимальной задержкой 1024, при 1МГц это даст около 0.25сек(4Гц);
2) По прерыванию таймера делаем Х=Х+1;
4) Если действие=не надо, то Х=0
3) Если Х>40 (10секунд), то ОТКЛ. ножку на портХ

Еще как вариант можно ввести контрольный бит, и проверять его состояние, как разрешающее в управлении нагрузкой, ну вариантов масса))[/quot



Вот как именно это прописать до меня и не доходит что-то...))

Жаль....что только на АСМЕ
Аватара пользователя
Flash.#13
Держит паяльник хвостом
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

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

Сообщение Flash.#13 »

Ну сами команды для Си и ассемблера одинаковы, но вот языковое оформление будет отличаться. Прерывания таймера позволяет освободить процессор от "тупого счета" задержки, вам вить нужно чтобы двигатели управлялись независимо? Кроме того, в МК вашей версии имеется несколько таймеров, и 16-бит таймер умеет не только считать но и сравнивать с заданным, т.э. можно записать интервал 10с в регистр сравнения счетчика2, и сделать прерывание, так же настроить обнуление по циклу, чтобы он считал только 10с.Здесь хорошо описаны счетчики, с примерами на СИ.
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Tolibbass
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Ср янв 07, 2015 15:37:52

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

Сообщение Tolibbass »

Спасибо за ответы.... буду дальше мозг насиловать. Мож чего и получится....
amd9800
Опытный кот
Сообщения: 822
Зарегистрирован: Вс июн 02, 2013 12:23:03

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

Сообщение amd9800 »

Tolibbass писал(а):буду дальше мозг насиловать.

не надо это делать - трагически может закончиться

Лучше просто его напрячь и думать.
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

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

Сообщение kotriks »

Люди добрые помогите с таймером, не могу заставить его тикать. вот мой код.
Спойлер

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


#include <tiny45.h>
#include <delay.h>

eeprom unsigned char Tim[10];

#define TIME_CONSTANT 488

unsigned char  hours=0,minutes=0,seconds=0;
unsigned int constant=TIME_CONSTANT;

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
    if((constant--)==0){ 
        constant=TIME_CONSTANT;
        if((seconds++)==59){
            seconds=0; 
            if((minutes++)==59){
                minutes=0;
                hours++;
            }
        }
    }

}

void timers() {
Tim[0]=hours;
Tim[1]=':';
Tim[2]=minutes;
Tim[3]=':';
Tim[4]=seconds;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=0xFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Timer1 Overflow Interrupt: On
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
PLLCSR=0x00;

TCCR1=0x07;
GTCCR=0x00;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x04;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
timers();
delay_us(500);

      }
}

Последний раз редактировалось Gudd-Head Пт мар 27, 2015 14:45:09, всего редактировалось 1 раз.
Причина: Нарушение п.2.5 Правил Форума
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

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

Сообщение kotriks »

kotriks писал(а):Люди добрые помогите с таймером, не могу заставить его тикать. вот мой код.
Спойлер

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


#include <tiny45.h>
#include <delay.h>

eeprom unsigned char Tim[10];

#define TIME_CONSTANT 488

unsigned char  hours=0,minutes=0,seconds=0;
unsigned int constant=TIME_CONSTANT;

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
    if((constant--)==0){ 
        constant=TIME_CONSTANT;
        if((seconds++)==59){
            seconds=0; 
            if((minutes++)==59){
                minutes=0;
                hours++;
            }
        }
    }

}

void timers() {
Tim[0]=hours;
Tim[1]=':';
Tim[2]=minutes;
Tim[3]=':';
Tim[4]=seconds;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=0xFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Timer1 Overflow Interrupt: On
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
PLLCSR=0x00;

TCCR1=0x07;
GTCCR=0x00;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x04;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
timers();
delay_us(500);

      }
}


забыл сказать что код на 8 мгц.
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

Когда запрашиваете помощь на форуме, то постить код с инициализацией регистров числовыми значениями это совершенно дурная практика. Вы полагаете, что все дружно должны полезть в мануалы, раскапывая, что значит 0х07 для TCCR1 attiny45 ? Зачем вы подчистили всю побитовую разблюдовку кодвижена? Вы совершили совершенно бессмысленную работу, чтобы запутать себя и практически лишились возможности получить помощь извне. По степени интеллектуальной мощи это ни с чем не сравнимое действие.

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

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

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE1A) | (0<<OCIE1B) | (0<<OCIE0A) | (0<<OCIE0B) | (1<<TOIE1) | (0<<TOIE0);


сравните это со своим умопомрачительно лаконичным TIMSK=0x04, которое изначально должно было выглядеть так:

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

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE1A) | (0<<OCIE1B) | (0<<OCIE0A) | (1<<OCIE0B) | (0<<TOIE1) | (0<<TOIE0);


Вы видите, что 0x04 это бит OCIE0B, который разрешает не прерывание по переполнению (на который у вас стоит обработчик), а другое прерывание -- по совпадению счетчика со значением регистра OCR1B. В итоге вы ждете прерывание, которое никогда не может случиться.


Я же сюда зашел совсем по другому поводу. Ситуация несколько двусмысленная и я не знаю, считать это багом или нет. Есть шестнадцатибитный таймер TIMER1 атмеги 328p. Инициализируется он в режиме CTC:

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

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 1 ms
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: On
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x3E;
OCR1AL=0x7F;
OCR1BH=0x01;
OCR1BL=0x00;


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

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

Изображение

Какое таинство должно совершаться по замыслу атмелов, после записи туда еще одного нуля? Может, конечно, это компилятор где-то самовольничает, но шерстить ассемблерный код всех библиотек мне как-то совсем не хочется.
Вложения
2015-03-29_162702.JPG
(14.55 КБ) 894 скачивания
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

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

Сообщение Jack_A »

a5021 писал(а):Какое таинство должно совершаться по замыслу атмелов, после записи туда еще одного нуля?

Дело не в Баскоме, я думаю ( хотя на нем ни строчки не накропал ) . Просто не нужно полагаться на на установку бит по умолчанию, а прописывать всегда весь регистр целиком. Мне встречалось подобное, причем только на единичных экземплярах МК. Чуть не свихнулся: прога на одном МК пашет, а на другом -- соси лорен. Прописал байт -- и все в полном ажуре. С тех пор врезал себе в мозг алмазным надфилем: НИКОГДА НЕ ПОЛАГАЙСЯ НА УМОЛЧАНИЯ. Может, в одном из многочисленных Bug Errata у них где-то об этом написано пару слов типа "В некоторых изделиях, выпущенных между ХХ.ХХ и УУ.УУ иногда возможна неверная установка..." и т.п.
DarkWolf
Встал на лапы
Сообщения: 117
Зарегистрирован: Ср ноя 05, 2014 19:04:31

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

Сообщение DarkWolf »

Уважаемые форумчане. Подскажите, в таком вопросе. Необходимо менять состояние ноги PINA.5 c частотой 10кГц. Делаю с помощью таймера Т0.
Настройки такие:

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

    TCCR0B = (1<<CS12)|(0<<CS11)|(1<<CS10); // настраиваем делитель
    TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера
    TCNT0 = 0x98;


В обработке прерывания меняю состояние порта с 0 на 1. В правильном ли направлении двигаюсь? Строго не ругайте, контроллерами занимаюсь не так давно.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

В правильном, но долгой и кривой дорогой.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Ответить

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