-=gga=-

Настройка Таймера В Nec Контроллере

10 сообщений в этой теме

-=gga=-    1

Собсна как можно настроить таумер чтобы он выдавал прерывания каждую секурду ?

Вот отрывок кода, из настройки таймера:

void init_TMH1()

{

TMHE1 = 0; //stop timerH1

TMHMD1 = 0x40; //set input clock to fxp / 2^12 = 1953,125 Hz @ 8MHz

CMP01 = 0x62; //set interval time to 50ms

TMIFH1 = 0; //clear interrupt request flag

TMMKH1=0; //enable timerH1 interrupt

}

Скажите плиз какая строчка за что отвечает ?

Да и вот этот коментарий

set input clock to fxp / 2^12 = 1953,125 Hz @ 8MHz

как его понимать ? 2 умноженное на 12 никак не даст 1953,125. а тут равенство какоето....

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Migray    5

На одну секунду сделать задержку одним таймером не получится.

Если конечно говорить о семействе 78K0S

В более навороченных семействах есть больше таймеров, предусмотрены разные режимы тактирования, иногда имеется второй кварц на 32,768 КГц

Вот с помощью этого кварца можно сформировать довольно точную секунду.

Остальные кварцы, не выдающие частоту 2^х, точной секунды сформировать не помогут :(

Теперь конкретнее о твоем примере.

Вообще таймер - просто счетчик, который считает входные импульсы, и при совпадении с заранее заданным числов выставляет флаг и(или) генерирует прерывание. В данном случае таймер настроен на время 50 мСек.

1. Сначала останавливается таймер, что-бы не мешался

2. Непонятная тебе строчка fxp / 2^12 = 1953,125 Hz @ 8MHz говорит о том, что входной частотой для таймера является не частота процессора fxp, которая в примере 8 МГц, а она-же но поделенная на 2 в степени 12.

Т.е. между тактом проца и таймером включили предделитель на 4096.

Соответственно 8 МГц / 4096 = 1953,125 Гц Эта частота является тактовой для таймера.

Предделитель можно выбрать один из ряда 2^2, 2^4, 2^6, 2^12 или вообще подавать на таймер частоту тактирования ядра.

Особый случай fRL / 2^7, тут делится не частота ядра процессора, а дополнительный генератор 240 кГц, т.е. входной частотой для таймера тут будет 1875 Гц

3. В таймер записывается число 0х62 (98 в десятичной системе). Т.е. таймер будет отсчитывать интервалы времени, равные 98 периодам тактовой частоты, по сути 1953,125 / 98 = 19,929846938775510204081632653061 Гц

Период этой частоты будет 0,050176 Сек

От нужного нам интервала 50 мСек, он отличается на 0,352%

Вроде немного, но за сутки такие часы отстанут примерно на 5 минут

4. Сбрасываем флаг прерываний, что-бы не вызвать ложного прерывания сразу после следующей команды

5. Разрешаем прерывания, которые будут вызываться каждые 0,050176 Сек

В программе тебе надо выделить переменную, и в п/п прерывания ее увеличивать.

Как только она станет равной 20, значит прошла секунда, и ты можешь выполнить какое-то действие.

Не забудь при этом сбросить свою переменную.

P.S. Посмотри даташит на русском, страница 111, там более полная информация.

P.P.S. У разных таймеров свои предделители, каждый из них может инициализироваться на свою частоту.

Изменено пользователем Migray

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=gga=-    1

Почемуто твоё объяснение удложилось у меня в голове лучше, чем то что написано в даташите. :)

Зная то что ты сказал, и формулу Т(периуд)=1/частоту. Я подсчитал что если вместо 0х62 записать 0хС5 (196) у меня получиться 1953,125/196=9,96492346938776 а периуд будет равен 0,100352 то есть 0.1с. это покрупнее будет чем 50мс. А если умножить на 255 то я получу здержку в 25.5 секунд, и это вполне удовлетроряет мои потребности. :)

Спасибо тебе, теперь всё работает! :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=gga=-    1

В принципе с таймером я разобрался, но осталась одна неурядица.

Я не понял как настроить регистр TMHMD1 точнее я не могу настроить биты предделителя.

В даташите есть такоеописание

post-17647-1205591709_thumb.jpg

Но дело в том что у меня сецчас в регистр TMHMD1 записано число 0х40 что даёт 00101000

В примере указано что у меня предлелитель на 2^12 а это значит что биты должны быть выстовлены вот так:

CKS12 1

CKS11 0

CKS10 0

Это я взял из даташита.

Но с какой бы стороны я не считал, у меня эти три бита не совпадают с нужными числами. :(

Или может я чтото не правильно делаю ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Migray    5

Ты просто ошибся в переводе в двоичную систему.

0x40 = 40h = 01000000b

Так-что 0100 0000 в регистре TMHMD1 как раз выставляет

CKS12 1

CKS11 0

CKS10 0

при остановленном таймере.

Потом, с годами тренировки, будешь переводить в уме :)

На первых порах можно пользоваться стандартным виндовым калькулятором, переведя его в инженерный вид.

Я и сейчас им иногда пользуюсь, даже на клавиатуре бумажки наклеены, у горячих клавиш.

F5 - "Hex"

F6 - "Dec"

F7 - "Oct"

F8 - "Bin"

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=gga=-    1

Ах вот где собака зарыта. Дело в том что я переводил не так:

0x40 = 40h = 01000000b

а вот так

0x40 = 00101000b

Вот по этому и получал другое число :(

Я тоже пользуюсь калькулятором, но не виндовым а более сложным и удобным. Он имеет три независимых калькулятора в одном окне (их можно переключать) и это очень удобно. Ну и ещё плюс кучи функций, типа синусы, арксинусы и т.п.

Если хочешь могу поделиться, протативная версия :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Migray    5

Все понятно :)

0х40 это всегда 40h, слева - альтернативное обозначение 16-ричной системы

а вот 40 это 40d, в смысле десятичная.

Похоже ты забыл перед набором числа перевести калькулятор в 16-ричный

Вот и получилось что

40 d = 28 h = 0010 1000 b

Калькулятор давай, пригодится, но у виндового есть свое преимущество, он стоит на любой машине.

Когда в командировке заходишь в сеть из инет-кафе, то в случае необходимости калькулятор там есть.

А тебе маленький совет.

Попробуй вообще без калькуляторов пару недель поработать.

16/10 не обещаю, а вот 16/2 выучишь точно.

И еще совет, при записи двоичного числа разбивай его на тетрады, удобней воспринимается и в 16-ричную переводится автоматом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=gga=-    1

Главное что уже разобрался, теперь перейду на тайтер 80.

Калькулятор вот, называется он HEXelon MAX 6.07 версия на данный момент последняя. Размер 1 мб. Протативная. Там есть такие функции как синусы, косинусы и ещё куча всего, чего я не знаю :) Скачать можно тут http://eldigi.ru/site/programms.php

Да и ещё там есть утилита, для перевода знаков в ASCII код.

В уме переводить я не умею, и учить в ближайшие три месяца наверное не буду, сейчас у меня есть куча всего что мине нужнее, в том числе физика и математика....

Это мне особо и не нужно, как ты и скащал виндовый калькулятор всегда под рукой :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Migray    5

Вообще-то с 80 таймера и надо было начинать.

Он как раз предназначен для формирования задержек, и его предделитель обладает большим коэффициентом деления.

2^6

2^8

2^10

2^16

Используя делитель 2^16 при 8 МГц тактовой можно было сформировать задержку до 2 секунд без использования внешних переменных.

А для таймера H1 есть более интересные функции, такие как ШИМ

Можно не просто светодиодом мигать, а еще менять его яркость, или управлять скоростью моторчика.

Изменено пользователем Migray

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=gga=-    1

Воспользовавшись твоим советом, решил менять яркость светодиода, используя ШИМ. Но у меня чтото не работает. Вот алгоритм в двух словах.

После включения у меня светодиод потухший, потом он должен постепенно загореться, достигнув максимума он должен постепенно выключаться. Но у меня с таким кодом светодиод просто моргает, при чём ни частота, ни ,тем более, яркость не меняются :(

Вот куски программы

PM4_bit.no2=0; // делаем порт 42 выходом ШИМ-а

//-----------------------------------------------------------------------------

// Module: init_TMH1

// Function: Initialization of TimerH1

//-----------------------------------------------------------------------------

void init_TMH1()

{

TMHE1 = 0; //stop timerH1

TMHMD1 = 0x49; //set input clock to fxp / 2^12 = 1953,125 Hz @ 8MHz

CMP01 = 0xFF; //Период навен 255

TMIFH1 = 0; //clear interrupt request flag

TMMKH1=0; //enable timerH1 interrupt

}

void main(void)

{

__disable_interrupt(); // global interrupt disable

init_CPU(); // CPU initialization

init_LED(); // LED port initialization

init_TM80(); // initialization of timer80

init_TMH1();

restart_TM80(); // start timer80

restart_TMH1(); // start timerH1

__enable_interrupt(); // global interrupt enable

unsigned char pwm = 1;

unsigned char inc = 1; // inc = 0 - уменьшать, inc = 1 - увеличивать яркость

if (inc == 1)

{

if (pwm < 254)

{

pwm++; // Увеличиваем яркость лампы, пока не достигнем максимума

CMP11 = pwm;

}

else

{

inc = 0;

}

}

else

{

if (pwm > 1)

{

pwm--; // Уменьшаем яркость лампы, пока не остигнем минимума

CMP11 = pwm;

}

else

{

inc = 1;

}

}

}

Вот весь код целиком:

#include "io78f9222.h"	// include LPC header files
#include <intrinsics.h>

//-----------------------------------------------------------------------------
// Definition of Option Byte
//-----------------------------------------------------------------------------
#pragma location = "OPTBYTE"
__root const unsigned char optbyte = 0x98;		

//-----------------------------------------------------------------------------
// Global Defines
//-----------------------------------------------------------------------------

#define LED1   P2_bit.no3    	    // LED D1
#define LED2   P13_bit.no0	    // LED D2
#define LED   P4_bit.no2           
#define LED4   P12_bit.no3	    // LED D4


//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------

__saddr volatile unsigned char Timer80Flag;
__saddr volatile unsigned char IntP0Flag;



//-----------------------------------------------------------------------------
// Module:   init_CPU
// Function: Initialization of CPU
//-----------------------------------------------------------------------------
void init_CPU (void)
{
// stop watchdog timer
 WDTM = 0x70;

//clock gererator settings
 PCC = 0x00;			// set CPU clock to fx
 PPCC = 0x00;
 LSRCM = 0x01;			// low speed ring oscillator stops

 OSTS  = 0x00;			//shortest stabilisation time 2^10/fx

// interrupt setting
  IF0  = 0x00;
  IF1  = 0x00;
  MK0  = 0xFF;
  MK1  = 0xFF;
}

//-----------------------------------------------------------------------------
// Module:   init_LED
// Function: Initialization of LED ports
//-----------------------------------------------------------------------------
void init_LED (void)
{
 PMC2_bit.no3=0;           // set port mode control of P23 to port mode
 PM2_bit.no3=0;            // set port P23 to output mode -> LED1
 PM4_bit.no2=0;            
 PM12_bit.no3=0;           // set port P123 to output mode -> LED4

 LED1=0;     	    // drive LED1
 LED2=0;	    // drive LED2
 LED4=0;	    // switch LED4 off

 LED1=1;	    // switch LED1 off
 LED2=1;	    // switch LED2 off  
 LED4=0;	    // drive LED4


}
//-----------------------------------------------------------------------------
// Module:   init_TM80
// Function: Initialization of Timer80
//-----------------------------------------------------------------------------
void init_TM80 (void)
{
  TCE80 = 0;			//disable timer80
  TMC80 = 0x06;	        //set input clock to fxp / 2^16 = 120 Hz @ 8MHz
  CR80  = 0x78;		//interval time = 1s	
  TMIF80 = 0;			//clear interrupt request flag
  TMMK80=0;			//enable timer80 interrupt
}

//-----------------------------------------------------------------------------
// Module:   restart_TM80
// Function: restarting of Timer80
//-----------------------------------------------------------------------------
void restart_TM80 (void)
{
  Timer80Flag=0;               //Reset status flag Timer80
  TCE80 = 0;			//disable timer80
  TCE80 = 1;			//enable timer80
}

//-----------------------------------------------------------------------------
// Module:   Wait50
// Function: This module delays the program for n * 50 ms.
//-----------------------------------------------------------------------------
void Wait(unsigned char Number)
{
 restart_TM80();
 while(Number>0)
 {
       while(Timer80Flag==0);
       Timer80Flag=0;               // Reset status flag Timer80
       Number--;
 }
 return;
}

//-----------------------------------------------------------------------------
// Module:   init_TMH1
// Function: Initialization of TimerH1
//-----------------------------------------------------------------------------
void init_TMH1()
{
  TMHE1 = 0;           //stop timerH1
  TMHMD1 = 0x49;	//set input clock to fxp / 2^12 = 1953,125 Hz @ 8MHz
  CMP01  = 0xFF;
  TMIFH1 = 0;		//clear interrupt request flag
  TMMKH1=0;		//enable timerH1 interrupt
}

//-----------------------------------------------------------------------------
// Module:   restart_TMH1
// Function: This module restarts TimerH1
//-----------------------------------------------------------------------------
void restart_TMH1 (void)
{
  TMHE1 = 0;
  TMHE1 = 1;
}
//-----------------------------------------------------------------------------
// Module:   main
// Function: main program
//-----------------------------------------------------------------------------
void main(void)
{

 __disable_interrupt();        // global interrupt disable
 init_CPU();           	// CPU initialization
 init_LED();		 	// LED port initialization
 init_TM80();			// initialization of timer80
 init_TMH1(); 	

   restart_TM80();		// start timer80
   restart_TMH1();		// start timerH1

 __enable_interrupt(); 	// global interrupt enable

unsigned char pwm = 1;
unsigned char inc = 1; // inc = 0 - уменьшать, inc = 1 - увеличивать яркость

   if (inc == 1) 
 {
   if (pwm < 254)
   {
     pwm++;  // Увеличиваем яркость лампы, пока не достигнем максимума
     CMP11 = pwm;
   }
   else
   {
     inc = 0;
   }
 }
 else
 {
   if (pwm > 1)
   {
     pwm--;  // Уменьшаем яркость лампы, пока не остигнем минимума
     CMP11 = pwm;
   }
   else
   {
     inc = 1;
   }
 }
 }

//-----------------------------------------------------------------------------
// ISR: 	  isr_INTTM80
// Function: Interrupt service routine of Timer80
//----------------------------------------------------------------------------
#pragma vector=INTTM80_vect
__interrupt void isr_INTTM80(void)
{
 Timer80Flag=0x1;    		 // Set status flag for Timer80
}
//-----------------------------------------------------------------------------
// ISR: 	  isr_INTTMH1
// Function: Interrupt service routine of Timer80
//-----------------------------------------------------------------------------
#pragma vector=INTTMH1_vect
__interrupt void isr_INTTMH1(void)
{
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас