Попробовал с помощью циклов с delay_ms(), но оказалось, что точность "хода" вообще никакая, отстает даже за 1 мин на несколько сек. Следовательно надо тактировать прерывания внешним генератором и уже в процедуре обработки прерываний сделать RTC. У attiny13 нет возможности подключить кварц напрямую, подскажите как наиболее просто организовать внешние прерывания с частотой 32678 гц?
Attiny13 и формирование задержки
- Сообщения: 11
- Зарегистрирован: Ср янв 22, 2014 20:26:04
Всем привет! Изучать МК начал недавно, появилась задача сделать простой таймер от 1 мин до нескольких часов, который включает и отключает нагрузку по заданным интервалам.
Попробовал с помощью циклов с delay_ms(), но оказалось, что точность "хода" вообще никакая, отстает даже за 1 мин на несколько сек. Следовательно надо тактировать прерывания внешним генератором и уже в процедуре обработки прерываний сделать RTC. У attiny13 нет возможности подключить кварц напрямую, подскажите как наиболее просто организовать внешние прерывания с частотой 32678 гц?
Попробовал с помощью циклов с delay_ms(), но оказалось, что точность "хода" вообще никакая, отстает даже за 1 мин на несколько сек. Следовательно надо тактировать прерывания внешним генератором и уже в процедуре обработки прерываний сделать RTC. У attiny13 нет возможности подключить кварц напрямую, подскажите как наиболее просто организовать внешние прерывания с частотой 32678 гц?
- Реклама
Не обязательно 32768. Можно любой частоты. Любой внешний генератор. А самим мк уже пересчитать.
Docendo discimus
- Сообщения: 11
- Зарегистрирован: Ср янв 22, 2014 20:26:04
Вот бы посоветовали наиболее простой и стабильный генератор для МК
На делеях у вас и с кварцевым генератором ничего толкового не выйдет) Там точность плюс-минус километр.
Делайте на прерываниях по переполнению таймера - даже на внутреннем RC генераторе за час пара-тройка секунд уход будет.
Делайте на прерываниях по переполнению таймера - даже на внутреннем RC генераторе за час пара-тройка секунд уход будет.
Если нужна точность, используйте спец микросхему PCF8583 или подобные.
Если точность +-5% то можно и в мк все сделать
Если точность +-5% то можно и в мк все сделать
- Реклама
Сделайте так, чтобы у вас срабатывало прерывание таймера каждые Х мс, а в прерывании декремируйте какую-нибудь переменную Y. Тогда у вас получится делей длительностью X*Y мс. Кроме того, такой делей не будет мешать работе основной программы.
- Сообщения: 11
- Зарегистрирован: Ср янв 22, 2014 20:26:04
Ок, буду пробовать на прерываниях по переполнению таймера на внутреннем RC генераторе, если уход будет небольшим, то подойдет.
Спасибо всем за оперативную помощь
Спасибо всем за оперативную помощь
- Сообщения: 11
- Зарегистрирован: Ср янв 22, 2014 20:26:04
Всем Hi.
Попробовал разобраться с прерываниями от таймера/счетчика, с помощью мастера CodeVision, сделал пограммку, которая меняет состояние 0-го пина порта B на противоположное (к нему подключен светодиод) как только таймер достиг значения #FF 15 раз (это должно соответствовать интервалу 1 с.)
int perepoln=0;
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
if (perepoln>15)
{perepoln=0;
PINB.0=~PINB.0;}
else {perepoln++;}
}
// 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=Out
// State5=T State4=T State3=T State2=T State1=T State0=0
PORTB=0x00;
DDRB=0x01;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 3,906 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x02;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0xFF;
OCR0B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;
// 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)
{
// Place your code here
}
}
собственно возник трабл: возникает прерывание, состояни светодиода меняется 1 раз и все! как-будто второе прерывание не возникает. Прошу помощи, укажите что не так?
Попробовал разобраться с прерываниями от таймера/счетчика, с помощью мастера CodeVision, сделал пограммку, которая меняет состояние 0-го пина порта B на противоположное (к нему подключен светодиод) как только таймер достиг значения #FF 15 раз (это должно соответствовать интервалу 1 с.)
Спойлер
#include <tiny13a.h>int perepoln=0;
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
if (perepoln>15)
{perepoln=0;
PINB.0=~PINB.0;}
else {perepoln++;}
}
// 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=Out
// State5=T State4=T State3=T State2=T State1=T State0=0
PORTB=0x00;
DDRB=0x01;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 3,906 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x02;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0xFF;
OCR0B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;
// 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)
{
// Place your code here
}
}
У вас ошибка. В регистр PORTx выводим, из регистра PINx читаем.
Ставим плюсы: )
- Сообщения: 11
- Зарегистрирован: Ср янв 22, 2014 20:26:04
Вместо
пишите сразу
Код: Выделить всё
if (perepoln>15)
{perepoln=0;
...}
else {perepoln++;}Код: Выделить всё
if (++perepoln>15)
{perepoln=0;
...}Docendo discimus


