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

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

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

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

Сообщение FAIR »

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

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

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

Сообщение akl »

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

Сообщение FAIR »

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

Сообщение Tolibbass »

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

Сообщение 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, монтажка
Друг Кота
Аватара пользователя
Сообщения: 20093
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

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

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

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

Сообщение 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 раз.
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

Сообщение 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, монтажка
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Ср янв 07, 2015 15:37:52

Сообщение Tolibbass »

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

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

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



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

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

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

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

Сообщение Tolibbass »

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

Сообщение amd9800 »

Tolibbass писал(а):буду дальше мозг насиловать.
не надо это делать - трагически может закончиться

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

Сообщение 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 Правил Форума
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение 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 мгц.
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение 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 КБ) 896 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 6325
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

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

Сообщение DarkWolf »

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

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

    TCCR0B = (1<<CS12)|(0<<CS11)|(1<<CS10); // настраиваем делитель
    TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера
    TCNT0 = 0x98; 
В обработке прерывания меняю состояние порта с 0 на 1. В правильном ли направлении двигаюсь? Строго не ругайте, контроллерами занимаюсь не так давно.
Друг Кота
Аватара пользователя
Сообщения: 20093
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

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

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