Добрый день форумчане. Как еще только начинающий электронщик хочу спросить совета бывалых) Итак поехали:
Задача. Необходимо запрограммировать таймер на задержку в 2 часа после чего на PORTB.0=0.
Что сделал: частота 4МГц, взял таймер 16разрядн. макс делитель 1024, с такими настройками максимальная задержка составляет 2.4мин (16000/0,256=62500). Мне этого мало, подумал над реализацией, выход взять задержку в 1 мин и циклически накручивать по +1 до нужного мне времени. Но столкнулся с незнанием реализации данного действия. Или же существует более простой способ реализации? Прошу помощи у бывалых котов=)
PS забыл добавить, пишу в CodeVisionAVR на языке С. Ну и сразу часть кода.
Но, что касается точности:
лишними в моем коде это загрузка таймера;
при условии, что в тиньке одна команда один такт (почти все команды) т.е. при частоте 4000000 Гц команда выполняется на 1 : 4000000 = 0,00000025 сек
за 7200 циклов мы теряем
7200 * 2 команды * 0,00000025 сек = 0,0036 сек
и это при точных 4000000 Гц генератора
Да. Для двухчасовой выдержки это не существенно. Но надо сразу привыкать всё делать правильно. Ведь в один прекрасный момент вдруг окажется, что 3,6 мс это много.
4Danko 16000 это милисекунды = 2,4 минуты. В книге "Белов А.В. - Создаём устройства на микроконтроллерах" именно так приводился пример для рассчета коэфициента деления. Кстати интересный момент по этому поводу в его книге указана 200мс в примере главы 1.7 (коэф деления 200/0,256=780) в реальной же программе вбив его пример у меня вышло 2 секунды. Долго думал куда мог затерыяться этот 0 и почему 200мс превращаются в протеусе в 2. Не нашел ответа=)
По поводу кода, решил воспользоваться вашим примером (прочитав дальнейшие советы пришел к выводу что, погрешность в 0.0036 для меня не играет сейчас роли). Но видимо из-за нехватки скила и наточенности рук промоделировать его не удалось. (i >= 7200) менял на 5сек для удобства тестирования, диод в протеусе висел мертвым грузом и гореть не желал(
И еще возник следом ламерский вопрос в программе я использую 2 задержки, 2 и 5 часов соответственно. Для тестирования программы сейчас срабатывание стоит на 5 и 10 сек, и все работает корректно. Пожалуй надо было и начинать с того что выкладывать весь код ранее. Именно эти значения мне и надо увеличить до 2 и 5 часов соответственно. Это будет 2 разных прерывания или можно реализовать все через 1 переменную сравнения i, которой присваивается по ходу программы сначала 7200 (2 часа) и далее 18000 (5 часов)?
Таймер 1 максимально отсчитает 15 секунд до переполнения (Tim1OVF) при тактовой частоте 4Мгц. Сделать прерывание по переполнению таймера и вызвать его необходимое количество раз. Эти разы подсчитывать в каком то счетчике. Как только значение счетчика достигнет заранее заданной константы, выдается сигнал на выключение таймера и запрещение прерываний. По-моему, так...
Товарищи коты, помогите найти нубу ошибку. Никак не получается правильно написать таймер. Взял для изучения простешую задачу. Через 30секунд после включения, включить 1й выходной порт, после чего осуществить задержку на 15 минут и вкл 2й выходной порт.
К портам выхода 1 и 2 подключены светодиоды.
Проблема в следующем, при включении (моделирую в Proteus, схема собрана верно) загораются оба светодиода одновременно после delay_ms(30000);, т.е вся процедура с таймераом просто пропускается и не функционирует.
И еще в категорически не понимаю, как delay_ms(30000) при моделировании превращаются не в 30секунд а в 300, а если записать delay_ms(3000) это и будет ровно 30 секунд. Как и почему, убирается 0 из милисекунд? Я уже даже усомнился в своих знаниях, но википедия, также считаает, что в 1 секунде 100мс. Чем это может быть вызвано?
delay_ms(30000); //задежка в 30сек
PORTB.0=0; // зажечь 1й выходной порт
TCCR1B=0x05; // запустить таймер
PORTB.1=0; // зажечь 2й выходной порт
У тебя после задержки включается первый светодиод, включается таймер и включается второй светодиод. Они и должны зажигаться одновременно.
TCCR1B=0x05; - это, как видно, не функция, а присваевание переменной.
Зажигать второй светодиод тебе нужно в прерывании по переполнению таймера.
А на счёт неправильной задержки, то тебе нужно переопределить значение тактовой частоты твоего контролера, что бы правильно расчитать задержку. Где? не помню... Вроде в F_CPU.
Т.е. тебе нужно перед #include -ами, вставить
IfoR писал(а):А на счёт неправильной задержки, то тебе нужно переопределить значение тактовой частоты твоего контролера, что бы правильно расчитать задержку. Где? не помню... Вроде в F_CPU.
В CodeVision тактовая частота контроллера для правильного вычисления задержек выставляется в проекте, путь: Project\Configure, вкладка C Compiler
Veidimadr писал(а):Товарищи коты, помогите найти нубу ошибку. Никак не получается правильно написать таймер.
Выше я давал ссылки как "правильно написать таймер". Сходить по третьей сверху ссылке http://radiokot.ru/forum/viewtopic.php?p=199397#199397 где разжёван пример, как управлять нагрузками от таймера, религия не позволяет?
Ув. коты вот добрались руки вновь заняться таймерами, собрал устройство и начал на реальном железе отлаживать. И столкнулся с такой проблемой, что ни ф-ию delay ни мой таймер контроллер просто не запускает. Проскакивает этот код и сразу переходит к следующему.
[quote]#include <tiny2313>
#include <delay>
volatile unsigned int sec_counter; // счётчик секунд
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// сюда попадаем каждую секунду
// проверяем счётчик секунд. если досчитал до нуля, то ничего не делаем
// если не ноль, то уменьшаем на единичку
if(sec_counter)
{
// не ноль
sec_counter--; // уменьшаем на единичку
}
}
void main(void)
{
// Declare your local variables here
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0xFF;
DDRB=0xFF;
// Port D initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTD=0x7F;
DDRD=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 3,906 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0D;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x0F;
OCR1AL=0x42;
OCR1BH=0x00;
OCR1BL=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x00;
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
// Global enable interrupts
#asm("sei")
delay_ms(5000);
//Задержка 30 секунд
sec_counter = 30; // счётчик секунд устанавливаем на 30 секунд
// ждём, пока эти самые 30 секунд оттикают
while(sec_counter)
{
// пока sec_counter не дотикал до нуля, болтаемся в пустом цикле
// не забудьте, что каждую секунду в прерывании он уменьшается на единичку
}
PORTB.0=1; //перекл реле2 в сост 0
PORTB.1=1; //замыкание реле 3 по 1[/quote]
В итоге при включении, сразу переключаются реле, никакой задержки по таймеру нет, как и через delay. В чем может быть проблема? Помогите разобраться плз. В протеусе задержки возникают в реальном железе нет.
CodeVisionAVR частота tiny2313 установлена в свойствах проэкта в 4,000000MHz