Программирование таймера на 2 часа (tiny2313)

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Родился
Сообщения: 8
Зарегистрирован: Чт ноя 05, 2009 08:23:56

Сообщение Veidimadr »

Добрый день форумчане. Как еще только начинающий электронщик хочу спросить совета бывалых) Итак поехали:

Задача. Необходимо запрограммировать таймер на задержку в 2 часа после чего на PORTB.0=0.

Что сделал: частота 4МГц, взял таймер 16разрядн. макс делитель 1024, с такими настройками максимальная задержка составляет 2.4мин (16000/0,256=62500). Мне этого мало, подумал над реализацией, выход взять задержку в 1 мин и циклически накручивать по +1 до нужного мне времени. Но столкнулся с незнанием реализации данного действия. Или же существует более простой способ реализации? Прошу помощи у бывалых котов=)

PS забыл добавить, пишу в CodeVisionAVR на языке С. Ну и сразу часть кода.

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

void wait1 (void)
{
TCNT1=0;
while (TCNT1<23438) {};  // ~ 1 минута  
}
.....
wait1();
PORTB.0=0; 
.....
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай

Сообщение Danko »

Veidimadr писал(а):...(16000/0,256=62500)...
Что такое 16000?

Если что то непонятно у меня пишите

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

// Declare your global variables here
unsigned int i;

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

// 3906 Гц : 65536 = 0.06 Гц
// 3906 Гц : 3906 = 1 Гц
// 65536 - 3906 =  61630 = 0xF0BE
// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
  // Reinitialize Timer 1 value 
  TCNT1H=0xF0;
  TCNT1L=0xBE;
  i++;
  if (i >= 7200) {i = 0; PORTB.0=0; } // 2 часа = 60 * 60 * 2 = 7200 сек
}

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

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 3,906 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0xF0;
TCNT1L=0xBE;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

Граждане бандиты! (в смысле программисты) Для отсчёта времени используйте в таймерах режим CTC !!! Он не требует программной перезагрузки таймера. Поэтому не набегают задержки!
http://radiokot.ru/forum/viewtopic.php?p=329033#329033
http://radiokot.ru/forum/viewtopic.php?p=209981#209981
http://radiokot.ru/forum/viewtopic.php?p=199397#199397
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай

Сообщение Danko »

Барсик, спасибо за ссылки.

Но, что касается точности:
лишними в моем коде это загрузка таймера;
при условии, что в тиньке одна команда один такт (почти все команды) т.е. при частоте 4000000 Гц команда выполняется на 1 : 4000000 = 0,00000025 сек

за 7200 циклов мы теряем
7200 * 2 команды * 0,00000025 сек = 0,0036 сек
и это при точных 4000000 Гц генератора :))
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

Да. Для двухчасовой выдержки это не существенно. Но надо сразу привыкать всё делать правильно. Ведь в один прекрасный момент вдруг окажется, что 3,6 мс это много. :beer:
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай

Сообщение Danko »

Целиком и полностью согласен.
Контактная информация:
Реклама
Нашел транзистор. Понюхал.
Сообщения: 155
Зарегистрирован: Вт авг 19, 2008 23:39:59
Откуда: г.Смоленск

Сообщение Saadov »

я сделал так

Настраиваем таймер на 1 сек, каждое переполнение ставим прерывание

пример:

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

//структура
typedef struct
{
    char sec;                    //секунды
    char min;                    //минуты
    char hour;                   //часы
}time_struct;

time_struct time;
в прерывание вставляем(пример)

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

interrupt [TIM3_COMPA] void timer3_compa_isr(void)
{

if(++time.sec==60) { time.sec = 0;            //секунды
    if(++time.min==60) { time.min = 0;           //минуты
       if(++time.hour==24) {time.hour = 0;}}}         //часы

if(time.hour== 2 ) {.......}; //делаем, что то
}
инициализация

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

void Init(void)  {
// Input/Output Ports initialization
//*******
//инициализируем выводы
// инициализируем таймеры

time.sec = 0;
time.min = 0;
time.hour = 0;

}

И опять же имеем возможность проследить сколько времени с момента запуска/отключения нагрузки, завести часы, таймера и т.д.[/code]
Родился
Сообщения: 8
Зарегистрирован: Чт ноя 05, 2009 08:23:56

Сообщение Veidimadr »

Всем большое спасибо за ответы.

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 часов)?

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

#include <tiny2313>
#include <delay> 

void wait1 (void)
{
TCNT1=0;
while (TCNT1<1803) {};    //5сек
}

void wait2 (void)
{
TCNT1=0;
while (TCNT1<3906) {};   //10 сек
}

void main(void)
{ 
PORTB=0xFF;
DDRB=0xFF;

PORTD=0x7F;
DDRD=0x00;

TCCR1A=0x00;
TCCR1B=0x05;

ACSR=0x80;

PORTB.0=1;
PORTB.1=0;

delay_ms(200); 

back1: if (PIND.0==1) 
    { 
    wait1();
    PORTB.0=0; 
    }
else goto back1;

back2: if (PIND.0==1) 
    {
    wait2();
    PORTB.1=1;
    }
else goto back2; 
}  

Код предложенный Danko, который я тестировал.

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

#include <tiny2313>

unsigned int i;

interrupt [TIM1_OVF] void timer1_ovf_isr(void) 
{ 
  // Reinitialize Timer 1 value 
  TCNT1H=0xF0; 
  TCNT1L=0xBE; 
  i++; 
  if (i >= 5) {i = 0; PORTB.0=0; } // 2 часа = 60 * 60 * 2 = 7200 сек 
}

void main(void)
{ 
PORTB=0xFF;
DDRB=0xFF;

PORTD=0x7F;
DDRD=0x00;

TCCR1A=0x00; 
TCCR1B=0x05; 

ACSR=0x80;
}
Электрический кот
Аватара пользователя
Сообщения: 1051
Зарегистрирован: Вт окт 21, 2008 11:46:23
Откуда: Барнаул

Сообщение Igor_67 »

Таймер 1 максимально отсчитает 15 секунд до переполнения (Tim1OVF) при тактовой частоте 4Мгц. Сделать прерывание по переполнению таймера и вызвать его необходимое количество раз. Эти разы подсчитывать в каком то счетчике. Как только значение счетчика достигнет заранее заданной константы, выдается сигнал на выключение таймера и запрещение прерываний. По-моему, так... 8)
Цапу крутить надо!!! Ку или не ку?
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай

Сообщение Danko »

вопрос:

от точки А до точки В сначала отсчитывает 2 часа
потом от точки В до точки С еще 5 часов?

или

от точки А до точки В сначала отсчитывает 2 часа
и далее до точки С еще 3 часа (итого 5 часов) ?
Контактная информация:
Родился
Сообщения: 8
Зарегистрирован: Чт ноя 05, 2009 08:23:56

Сообщение Veidimadr »

4Danko
от точки А до точки В сначала отсчитывает 2 часа
потом от точки В до точки С еще 5 часов?
Этот вариант. Только с поправкой ""потом от точки C до точки D еще 5 часов"".
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай

Сообщение Danko »

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

i++;
if (i == 7200)  { /*точка В*/; } // 2 часа = 60 * 60 * 2 = 7200 сек 
if (i == 25200) { /*точка С*/; } // 2+5 часов = 60 * 60 * 7 = 25200 сек 
if (i == 43200) { /*точка D*/; i=0; } // 2+5+5 часов = 60 * 60 * 12 = 43200 сек 
если прописать i=0; то цикл начнет отсчитывать сначала
если все нужно остановить то за i=0; нужно прописать:

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

TCCR1A=0x00;
TCCR1B=0x00;
если опять запустить то:

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

TCCR1A=0x00;
TCCR1B=0x05;
TCCR1A=0x00; при желании можно не писать (указал для наглядности).
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай

Сообщение Danko »

Контактная информация:
Родился
Сообщения: 8
Зарегистрирован: Чт ноя 05, 2009 08:23:56

Сообщение Veidimadr »

Товарищи коты, помогите найти нубу ошибку. Никак не получается правильно написать таймер. Взял для изучения простешую задачу. Через 30секунд после включения, включить 1й выходной порт, после чего осуществить задержку на 15 минут и вкл 2й выходной порт.
К портам выхода 1 и 2 подключены светодиоды.

Проблема в следующем, при включении (моделирую в Proteus, схема собрана верно) загораются оба светодиода одновременно после delay_ms(30000);, т.е вся процедура с таймераом просто пропускается и не функционирует.
И еще в категорически не понимаю, как delay_ms(30000) при моделировании превращаются не в 30секунд а в 300, а если записать delay_ms(3000) это и будет ровно 30 секунд. Как и почему, убирается 0 из милисекунд? Я уже даже усомнился в своих знаниях, но википедия, также считаает, что в 1 секунде 100мс. Чем это может быть вызвано?

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

#include <tiny2313>
#include <delay>

unsigned int i;

interrupt [TIM1_OVF] void timer1_ovf_isr(void) 
{ 
  i++; 
  if (i == 15000) {i=0; TCCR1B=0x00; }
} 

void main(void) 
{ 
PORTB=0xFF; 
DDRB=0xFF; 

ACSR=0x80; 

delay_ms(30000); //задежка в 30сек

PORTB.0=0; // зажечь 1й выходной порт
 
TCCR1B=0x05; // запустить таймер 

PORTB.1=0; // зажечь 2й выходной порт
}
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Ну так у тебя же в коде прям так и написано:

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

delay_ms(30000); //задежка в 30сек 
PORTB.0=0; // зажечь 1й выходной порт 
TCCR1B=0x05; // запустить таймер 
PORTB.1=0; // зажечь 2й выходной порт 
У тебя после задержки включается первый светодиод, включается таймер и включается второй светодиод. Они и должны зажигаться одновременно.
TCCR1B=0x05; - это, как видно, не функция, а присваевание переменной.
Зажигать второй светодиод тебе нужно в прерывании по переполнению таймера.

А на счёт неправильной задержки, то тебе нужно переопределить значение тактовой частоты твоего контролера, что бы правильно расчитать задержку. Где? не помню... Вроде в F_CPU.
Т.е. тебе нужно перед #include -ами, вставить

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

#define F_CPU 8000000UL
Где 8000000 - тактовая частота контроллера в герцах. :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 151
Зарегистрирован: Пт май 01, 2009 08:58:42
Откуда: г. Коломна

Сообщение evgeniy66 »

IfoR писал(а):А на счёт неправильной задержки, то тебе нужно переопределить значение тактовой частоты твоего контролера, что бы правильно расчитать задержку. Где? не помню... Вроде в F_CPU.
В CodeVision тактовая частота контроллера для правильного вычисления задержек выставляется в проекте, путь: Project\Configure, вкладка C Compiler
RK3DUQ
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

Veidimadr писал(а):Товарищи коты, помогите найти нубу ошибку. Никак не получается правильно написать таймер.
Выше я давал ссылки как "правильно написать таймер". Сходить по третьей сверху ссылке http://radiokot.ru/forum/viewtopic.php?p=199397#199397 где разжёван пример, как управлять нагрузками от таймера, религия не позволяет?
Родился
Сообщения: 8
Зарегистрирован: Чт ноя 05, 2009 08:23:56

Сообщение Veidimadr »

ув. Барсик, ходил, позволяет, опыт еще не позволяет разобраться во всем с первой попытки) Спасибо за советы.
Родился
Сообщения: 8
Зарегистрирован: Чт ноя 05, 2009 08:23:56

Сообщение Veidimadr »

Ув. коты вот добрались руки вновь заняться таймерами, собрал устройство и начал на реальном железе отлаживать. И столкнулся с такой проблемой, что ни ф-ию 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
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

Veidimadr писал(а):В протеусе задержки возникают в реальном железе нет.
Схему реального железа - в студию!
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»