Почему же. Если таймер заставить тактироваться от внешнего источника, он как раз-таки будет считать импульсы.rxstart1 писал(а):Глупость пишите таймер не считает импульсы он просто тикает
Таймеры/счётчики в AVR
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- Реклама
- Сообщения: 6
- Зарегистрирован: Пн мар 02, 2015 15:16:00
Так можно ли заставить таймер 2 считать импульсы от внешнего источника?Gudd-Head писал(а):Если таймер заставить тактироваться от внешнего источника, он как раз-таки будет считать импульсы.
Насколько я понял, это можно сделать с пина TOSC1.FAIR писал(а):таймер\счетчик 2 в Atmega88, считал импульсы так,как делает это таймер\счетчик 0 с пина T0
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Да, можно подать на XTAL1/TOSC1/PB6 сигнал. Перевести Т2 в асинхронный режим и тактироваться от встроенного RC-генератора.
- Сообщения: 6
- Зарегистрирован: Пн мар 02, 2015 15:16:00
Всем спасибо за ответы. Получилось, надо было выставить 1 в битах AS2 и EXCLK, и подать сигнал на TOSC1.
- Реклама
- Сообщения: 37
- Зарегистрирован: Ср янв 07, 2015 15:37:52
Есть вопросы.... Везде пушут про прерывания, т.е. настраиваешь таймер и в нужный момент программа прерывается. А если мне надо чтоб какое-то действие(например время работы нагрузки с ПОРТА В) было 10сек???? Но в тоже время есть сигнал который может в любой момент прервать это действие. как тогда прописывается на СИ????
Tolibbass прерываний у МК достаточно много, во например прерывания меги8:
Многие вопросы отпадают сами собой со временем. И конкретно по вашей задаче: откл. портХ по таймеру в 10 секунд.
Еще как вариант можно ввести контрольный бит, и проверять его состояние, как разрешающее в управлении нагрузкой, ну вариантов масса))
Код: Выделить всё
.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
Код: Выделить всё
1) Настраиваем таймер2(16бит) с максимальной задержкой 1024, при 1МГц это даст около 0.25сек(4Гц);
2) По прерыванию таймера делаем Х=Х+1;
4) Если действие=не надо, то Х=0
3) Если Х>40 (10секунд), то ОТКЛ. ножку на портХ
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Без разницы, на Сях это прописывается или на АСМе. Важно понимать алгоритм действий.Tolibbass писал(а):Но в тоже время есть сигнал который может в любой момент прервать это действие. как тогда прописывается на СИ????
Код: Выделить всё
таймер2(16бит) с максимальной задержкой 1024, при 1МГц это даст около[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- Сообщения: 37
- Зарегистрирован: Ср янв 07, 2015 15:37:52
Блин все равно не очень понятно.... Есть такая схемка. надо чтоб при разомкнутом 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;}
вот как раз алгоритма я и не могу понять(((((
#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 раз.
Моя вина, протупил, это 8бит счетчик даст 0,25с при 1024 с 1МГцGudd-Head писал(а):...67 секунд при тактовой 1 МГц и предделителе 1024.
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
[quote
Многие вопросы отпадают сами собой со временем. И конкретно по вашей задаче: откл. портХ по таймеру в 10 секунд.
Еще как вариант можно ввести контрольный бит, и проверять его состояние, как разрешающее в управлении нагрузкой, ну вариантов масса))[/quot
Вот как именно это прописать до меня и не доходит что-то...))
Жаль....что только на АСМЕ
Многие вопросы отпадают сами собой со временем. И конкретно по вашей задаче: откл. портХ по таймеру в 10 секунд.
Код: Выделить всё
1) Настраиваем таймер2(16бит) с максимальной задержкой 1024, при 1МГц это даст около 0.25сек(4Гц);
2) По прерыванию таймера делаем Х=Х+1;
4) Если действие=не надо, то Х=0
3) Если Х>40 (10секунд), то ОТКЛ. ножку на портХ
Вот как именно это прописать до меня и не доходит что-то...))
Жаль....что только на АСМЕ
Ну сами команды для Си и ассемблера одинаковы, но вот языковое оформление будет отличаться. Прерывания таймера позволяет освободить процессор от "тупого счета" задержки, вам вить нужно чтобы двигатели управлялись независимо? Кроме того, в МК вашей версии имеется несколько таймеров, и 16-бит таймер умеет не только считать но и сравнивать с заданным, т.э. можно записать интервал 10с в регистр сравнения счетчика2, и сделать прерывание, так же настроить обнуление по циклу, чтобы он считал только 10с.Здесь хорошо описаны счетчики, с примерами на СИ.
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
- Сообщения: 37
- Зарегистрирован: Ср янв 07, 2015 15:37:52
Спасибо за ответы.... буду дальше мозг насиловать. Мож чего и получится....
- Сообщения: 822
- Зарегистрирован: Вс июн 02, 2013 12:23:03
не надо это делать - трагически может закончитьсяTolibbass писал(а):буду дальше мозг насиловать.
Лучше просто его напрячь и думать.
- Сообщения: 274
- Зарегистрирован: Чт апр 28, 2011 15:08:58
Люди добрые помогите с таймером, не могу заставить его тикать. вот мой код.
Спойлер
Код: Выделить всё
#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 Правил Форума
Причина: Нарушение п.2.5 Правил Форума
- Сообщения: 274
- Зарегистрирован: Чт апр 28, 2011 15:08:58
забыл сказать что код на 8 мгц.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); } }
- Сообщения: 6452
- Зарегистрирован: Пт сен 13, 2013 13:11:31
Когда запрашиваете помощь на форуме, то постить код с инициализацией регистров числовыми значениями это совершенно дурная практика. Вы полагаете, что все дружно должны полезть в мануалы, раскапывая, что значит 0х07 для TCCR1 attiny45 ? Зачем вы подчистили всю побитовую разблюдовку кодвижена? Вы совершили совершенно бессмысленную работу, чтобы запутать себя и практически лишились возможности получить помощь извне. По степени интеллектуальной мощи это ни с чем не сравнимое действие.
Это хорошо, что у меня кодвижен был запущен и я как раз разбирался с таймером меги328, прежде чем зайти сюда. Восстановив по комментариями режим инициализации таймера для тини45 (хорошо еще комментарии почистить у вас ума не хватило), кодвижен у меня сгенирировал несколько отличный от вашего код. Маска прерываний для разрешения прерывания по переполнению должна выглядеть так:
сравните это со своим умопомрачительно лаконичным TIMSK=0x04, которое изначально должно было выглядеть так:
Вы видите, что 0x04 это бит OCIE0B, который разрешает не прерывание по переполнению (на который у вас стоит обработчик), а другое прерывание -- по совпадению счетчика со значением регистра OCR1B. В итоге вы ждете прерывание, которое никогда не может случиться.
Я же сюда зашел совсем по другому поводу. Ситуация несколько двусмысленная и я не знаю, считать это багом или нет. Есть шестнадцатибитный таймер TIMER1 атмеги 328p. Инициализируется он в режиме CTC:
Кодвижен генерирует код, где несколько операций присваивания устанавливают нулевые значения регистрам, которые, если верить атмеловскому букварю, и так находятся при включении в нуле. По сути это лишний код, который не делает осмысленных действий. Но не тут то было. Попытки закомментировать нулевые присвоения приводят к тому, что таймер впадает в некое странное состояние, когда он вроде бы работает, но прерывания начинают выдаваться не периодически и с большей частотой, чем было задумано.
Путем последовательного перебора было вычислено, что виновна во всем строчка инициализации TCCR1A. Если записать туда ноль, то все работает нормально. Если туда ничего не записывать, то получается ерунда. Если бы это была половинка 16-битного регистра, то еще можно было бы подозревать, что должны соблюдаться некие правила обращения к шестнадцатибитным регистрам и они где-то нарушаются. Но этот регистр восьмибитный и ни с каким другим регистром более не связан. Смотрю в букварь и вижу, что регистр после сброса всегда в нуле:

Какое таинство должно совершаться по замыслу атмелов, после записи туда еще одного нуля? Может, конечно, это компилятор где-то самовольничает, но шерстить ассемблерный код всех библиотек мне как-то совсем не хочется.
Это хорошо, что у меня кодвижен был запущен и я как раз разбирался с таймером меги328, прежде чем зайти сюда. Восстановив по комментариями режим инициализации таймера для тини45 (хорошо еще комментарии почистить у вас ума не хватило), кодвижен у меня сгенирировал несколько отличный от вашего код. Маска прерываний для разрешения прерывания по переполнению должна выглядеть так:
Код: Выделить всё
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE1A) | (0<<OCIE1B) | (0<<OCIE0A) | (0<<OCIE0B) | (1<<TOIE1) | (0<<TOIE0);Код: Выделить всё
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE1A) | (0<<OCIE1B) | (0<<OCIE0A) | (1<<OCIE0B) | (0<<TOIE1) | (0<<TOIE0);Я же сюда зашел совсем по другому поводу. Ситуация несколько двусмысленная и я не знаю, считать это багом или нет. Есть шестнадцатибитный таймер 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 скачиваний
Дело не в Баскоме, я думаю ( хотя на нем ни строчки не накропал ) . Просто не нужно полагаться на на установку бит по умолчанию, а прописывать всегда весь регистр целиком. Мне встречалось подобное, причем только на единичных экземплярах МК. Чуть не свихнулся: прога на одном МК пашет, а на другом -- соси лорен. Прописал байт -- и все в полном ажуре. С тех пор врезал себе в мозг алмазным надфилем: НИКОГДА НЕ ПОЛАГАЙСЯ НА УМОЛЧАНИЯ. Может, в одном из многочисленных Bug Errata у них где-то об этом написано пару слов типа "В некоторых изделиях, выпущенных между ХХ.ХХ и УУ.УУ иногда возможна неверная установка..." и т.п.a5021 писал(а): Какое таинство должно совершаться по замыслу атмелов, после записи туда еще одного нуля?
- Сообщения: 117
- Зарегистрирован: Ср ноя 05, 2014 19:04:31
Уважаемые форумчане. Подскажите, в таком вопросе. Необходимо менять состояние ноги PINA.5 c частотой 10кГц. Делаю с помощью таймера Т0.
Настройки такие:
В обработке прерывания меняю состояние порта с 0 на 1. В правильном ли направлении двигаюсь? Строго не ругайте, контроллерами занимаюсь не так давно.
Настройки такие:
Код: Выделить всё
TCCR0B = (1<<CS12)|(0<<CS11)|(1<<CS10); // настраиваем делитель
TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера
TCNT0 = 0x98; В правильном, но долгой и кривой дорогой.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]


