Отговори на тема  [ 25 мнения ]  Отиди на страница 1, 2  Следваща
Zilog - Z8 Encore! F083A Series 
Автор Съобщение
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Zilog - Z8 Encore! F083A Series
Здравейте,

В момента разучавам таймера на горе посоченият микроконтролер. Искам да го конфигурирам в one-shot mode. Според спецификацията:

One-Shot Mode Time-Out Period (s) = (Reload Value – Start Value) * Prescale / System Clock Frequency (Hz)

След заместване: (65535 - 0) * 128 / 20MHz = 420ms (приблизително).

"От горните изчисления излиза, че максималното време на препълване на таймера е 419424μs или приблизително 420ms, т.е.. периодът на правоъгълните импулси ще бъде 420ms * 2 = 840ms (1.2Hz)."

Не разбирам, защо трябва да умножаваме 420ms * 2 ? Ако приемем, че T (период) = 420ms =>, че f = 1 / T => 1 / 0,42s (420ms) = 2,4Hz, но ако умножим 420ms * 2 = 840ms =>, че f = 1 / T => 1 / 0,84s (840ms) = 1,2Hz. Явно бъркам максималното време за препълване на таймера със периода?

Наясно съм, че питам елементарни и глупави неща, но много бих се радвал, ако някой ми разясни как точно се случват нещата. Ами, ако искам да направя диода да свети на 5 или 10s ? Мисля, че няма да стане, тъй като максималния делител е 128?

Благодаря, предварително! :rolleyes:


Вто Юни 05, 2018 2:53 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10368
Местоположение: Добрич
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
Не разбирам, защо трябва да умножаваме 420ms * 2 ?


Не познавам въпросния таймер, но това си е обща болест...

При едно извъртане на таймера имаш 1 събитие. Ако искаш второ събитие се налага още веднъж да извъртиш или таймер с повече compare регистри.

От друга страна за да генерираш правоъгълен импулс ти трябват две събития (по едното правиш преден фронт, по другото заден). И те така, първия път таймера като каже "щрак" имаш единия фронт. Втория път като каже "щрак" имаш и другия фронт. Както и да ги броим това са 2 щракания за един период ;-)

Metyyy написа:
Ами, ако искам да направя диода да свети на 5 или 10s ?

Когато надскочиш възможностите на хардуера се налага да пишеш софтуер. Демек софтуерно си правиш един брояч колко пъти е казал "щрак" таймера. За удобство може таймера да го настроиш на по-кръгло число, да кажем 100ms. И така като софтуерния брояч стане 25, палиш диода, след още 25 щракания гасиш. Ето ти ги 5s. За 10s ще се сетиш сам ;-)


Вто Юни 05, 2018 3:22 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 03, 2005 1:21 am
Мнения: 10610
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
...Ами, ако искам да направя диода да свети на 5 или 10s ? Мисля, че няма да стане, тъй като максималния делител е 128...

Виж тая тема - http://www.mcu-bg.com/mcu_site/viewtopi ... =2&t=15883
Там са обсъждани различни начини да си мигаш и светкаш.


Вто Юни 05, 2018 5:25 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пет Фев 04, 2005 8:59 pm
Мнения: 6019
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
Онази тема само ще го обърка още повече, особено ако сега почва.

_________________
Warriors of the Night, ASSEMBLER!!!


Вто Юни 05, 2018 10:41 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 7:04 pm
Мнения: 2586
Местоположение: Велико Търново / София
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
Не разбирам, защо трябва да умножаваме 420ms * 2 ?

Ами на 420ms ти се променя (обръща) изходното ниво (състояние). 420ms лог.1 420ms лог.0 . Получава се период на честотата 840ms или 1.19Hz.
Повечето системи където има делене на честотата работят така. Всъщност това нещо което обръща изхода е примерно един JK тригер, който реално дели на две. Предимството както се вижда е, че при какъвто и да е коефициент на делене на брояча, се получава 50/50 коефициент на запълване, нещо което няма как да стане иначе при произволен коефициент.

_________________
https://github.com/slav4ocom/


Вто Юни 05, 2018 11:02 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Благодаря на всички ! Може би, отговора на miro_atc е най-близко разбираем за моите възможности в момента :rolleyes:

Опитах се да направя delay 5s, но честно да си призная софтуерната част (Delay_Counter_5s == 11) с избора на числово 11 беше чисто и просто налучкване. Не мога да разбера, как получих 5s delay, при положение, че имам първоначално 0.82s и после 11? Съжалявам, ако отговора е очевиден.

Откровено казано, темата пратена от itso.t, наистина ме обърка и все пак благодаря !

#include<ez8.h> /* Този хедър позволява да достъпваме вътрешните регистри като всички останали, чрез имената им. */

#define DD0_OFFSET (0)

#define IRQE_OFFSET (7)
#define TENH_OFFSET (5)
#define TENL_OFFSET (5)

#define TH_OFFSET (0)
#define TL_OFFSET (0)

#define TRH_VALUE (65535)
#define TRL_VALUE (65535)

#define TEN_BIT (7)
#define TPOL_BIT (6)
#define PRES_BIT_5 (5)
#define PRES_BIT_4 (4)
#define PRES_BIT_3 (3)
#define TMODE_BIT_2 (2)
#define TMODE_BIT_1 (1)
#define TMODE_BIT_0 (0)

#define TMODEHI_BIT (0)
#define TCTL1_VALUE ((1<<TEN_BIT) | (0<<TPOL_BIT) | (1<<PRES_BIT_5) | (1<<PRES_BIT_4) | (1<<PRES_BIT_3) | (0<<TMODE_BIT_2) | (0<<TMODE_BIT_1) | (0<<TMODE_BIT_0))

#define POUT0_VALUE (0)

typedef unsigned char u08;

int main(void)
{
PADD &= ~(1<<DD0_OFFSET); /* За да конфигурираме извод PA0 като изход, трябва да нулираме бит 0
на регистър PADD */

IRQCTL |= 1<<IRQE_OFFSET; /* Прекъсванията се разрешават с глобалния бит IRQE в регистър IRQCTL. Бит IRQE
се установява в 1 */

IRQ0ENL |= 1<<TENL_OFFSET; /* Достатъчно е да установим единия от двата или и двата бита. Младши бит 5 e за
разрешаване на прекъсване от Таймер0. Всеки източник на прекъсване има локален механизъм за разрешаване. Този
механизъм също се използва за задаване и на софтуерен приоритет на прекъсванията. Тъй като имаме само един
източник на прекъсване в програмата, е без значение какво ниво на приоритет ще изберем. */

IRQ0ENH |= 1<<TENH_OFFSET; /* Достатъчно е да установим единия от двата или и двата бита. Младши бит 5 e за
разрешаване на прекъсване от Таймер0. Всеки източник на прекъсване има локален механизъм за разрешаване. Този
механизъм също се използва за задаване и на софтуерен приоритет на прекъсванията. Тъй като имаме само един
източник на прекъсване в програмата, е без значение какво ниво на приоритет ще изберем. */

T0H = TH_OFFSET; /* Записваме начална стойност на таймера в броячните регистри TxH и TxL, т.е. ги нулираме */
T0L = TL_OFFSET; /* Записваме начална стойност на таймера в броячните регистри TxH и TxL, т.е. ги нулираме */

T0RH = TRH_VALUE; /* Регистрите съдържат макс. 16-битова броячна стойност до която брои таймера и тя е 65535 */
T0RL = TRL_VALUE; /* Регистрите съдържат макс. 16-битова броячна стойност до която брои таймера и тя е 65535 */

/* One-shot mode: T = (65535 - 0) * 128 / 20MHz = 419424 микросекунди = 420ms (приблизително)
За да генерираме правоъгълен импулс ни трябват две събития (по едното правим преден фронт, по другото заден),
затова и трябва да умножим 420ms * 2 = 840ms = 0.84s; T = 1 / 0,84 = 1.2Hz */

T0CTL0 = TMODEHI_BIT; /* Еднократен режим */
T0CTL1 = TCTL1_VALUE; /* Коефициент на деление 128 и стартиране на таймера */

while(1);
}

void interrupt Timer0_ISR(void) _At TIMER0
{
static u08 Delay_Counter_5s = 0;

if (Delay_Counter_5s == 11)
{
PAOUT ^= 1<<POUT0_VALUE; /* Превключване на нивото на извод PA0 */

Delay_Counter_5s=0;
}

else
{
Delay_Counter_5s++;
}

T0CTL1 |= 1<<TEN_BIT; /* Стартиране на таймера отново */
}


Сря Юни 06, 2018 12:23 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пет Фев 04, 2005 8:59 pm
Мнения: 6019
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:

След заместване: (65535 - 0) * 128 / 20MHz = 420ms (приблизително).

420ms * 11 = 4620ms = 4.62s

_________________
Warriors of the Night, ASSEMBLER!!!


Сря Юни 06, 2018 6:48 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
По скоро 420 * 10 = 4200ms = 4.2s


Сря Юни 06, 2018 7:21 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 7:04 pm
Мнения: 2586
Местоположение: Велико Търново / София
Мнение Re: Zilog - Z8 Encore! F083A Series
Не знам какво си направил. По принцип като изтече периода 420ms се вдига някакъв флаг. Ти или трябва да го проверяваш достатъчно често, или да викаш прекъсване. Когато видиш че е вдигнат флага, го изчистваш и правиш нещо, каквото ти е необходимо. Ако обръщаш изхода на всяко вдигане на флага ще имаш 420ms ниско и 420ms високо ниво. Реално честотата е двойно по-ниска от тази на вдигането на флага. От там идва това 2.
Ако броиш 10 пъти вдигане на флага, да 10х420мс и си правиш там нещо като изброиш до 10, т.е. като мине закъснението от 4.2ms. Ако искаш може да броиш до 10 и да обръщаш изхода, така ще поучиш период 8.4s или 0.119Hz, което всъщност няма почти никакво смислено приложение. :)

_________________
https://github.com/slav4ocom/


Сря Юни 06, 2018 7:27 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10368
Местоположение: Добрич
Мнение Re: Zilog - Z8 Encore! F083A Series
Не знам, не съм гледал и не искам да гледам документацията на твоя чеп...

Но съм видял стотици други и навсякъде таймер се прави с един брояч и един компаратор, които клокваш с някакъв клок. Когато компараторът види еднакви стойности броячът се презарежда и имаш прекъсване.
Елементарно е, само че сметките са малко по-различни от тия дето си дал. Ако приемем че броячът брои от 0 и се ресетва до 0, то най-малката стойност дето може да сложиш в компаратора е също нула. При това на всеки такт ще имаш прекъсване и броячът ще брои 0, 0, 0, 0, 0... Изходната честота ще ти е точно 2 пъти по-ниска.
Ако сложиш 1 в компаратора, броячът ще брои 0,1,0,1,0,1.... демек ще имаш прекъсване на всеки два такта или с други думи изходната честота е 4 пъти по-ниска.

Така че формулата би трябвало да е нещо от сорта:
One-Shot Mode Time-Out Period (s) = (Reload Value +1 – Start Value) * 2* Prescale / System Clock Frequency (Hz)

Нека да приемем prescale=1 и системен клок 1MHz
Тогава в първия пример когато reload value=0 и start value=0 имаш
X = (0+1-0)*2*1/1000000 = 2/1000000 = 2us

Сега в твоя случай ако брои от 0 до 11, това са си 12 стойности или 12 клока за едно прекъсване
или по друг начин казано 12 * 420ms =5.04s

толкова получаваш нали?


Пет Юни 08, 2018 8:27 am
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Сигурен съм, че моите сметки са правилни, точно до графиката с прекъсванията. Така, искам 5 секунди, в случая съм сложил 100 ms, но тогава ще имам 50 прекъсвания, а за да ги намаля, трябва да избера максималното число, кратно на 5 и по малко от 420 ms (0.42s) и то е 200 =>, че графиката се променя и там вместо 100 ms, ще имаме 200 ms. Тук ми е 1-ят въпрос (10 прекъсвания ли ще имам или 11 или 12), макар, че като го сметна е едно и също, тъй като при всички случаи се получава, че за 1 секунда ще имам 5 прекъсвания т.е. за 5 секунди ще имам 25 прекъсвания. А, 2-ят ми въпрос е, колко трябва да бъде началната стойност, от която таймера брои - 65335 т.е. (65535 - 200)? Мисля, че нещата са доста по прости от това което смятам и правя, ама айде де, не мога да го измисля и това е.

Сега, по-случайност избрах за начална стойност на таймера 64753 =>, че 782 * 0.0000064 = 5.0048 секунди.

Предполагам, че досаждам вече, но не виждам друг изход.

Благодаря!


Прикачени файлове:
0-02-05-63159c1ae933be43ee7845654a8e7f1d3b2876537f7424533798effbdc810640_9b2dce3f.jpg
0-02-05-63159c1ae933be43ee7845654a8e7f1d3b2876537f7424533798effbdc810640_9b2dce3f.jpg [ 218.22 KiB | Прегледано 4645 пъти ]
0-02-05-75ba120d612998baf62b6c4777321604659af8ec86094e09ff3bc57d8ef87137_cc32bbbc.jpg
0-02-05-75ba120d612998baf62b6c4777321604659af8ec86094e09ff3bc57d8ef87137_cc32bbbc.jpg [ 135.95 KiB | Прегледано 4645 пъти ]
Пет Юни 08, 2018 2:56 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 7:04 pm
Мнения: 2586
Местоположение: Велико Търново / София
Мнение Re: Zilog - Z8 Encore! F083A Series
Хм аз пък си мисля, че 250ms x 20 = 5s.
Тааака избрал си все пак 200ms.
Първо трябва да разбереш откъде взема тактов сигнал този таймер. Имаш прескалер, което значи че входната честота се дели. В случая тя се дели на 128 :
20MHz/128 = 156,25kHz. Периода е 1/156,25 = 6,4uS.
Така.
За да получиш заветните 200ms, брояча трябва да изброи:
200 000 / 6,4 = 31 250пъти (периода). Това ти е коефициента на брояча.
Сега. Процесора ти не знам какъв е , но на PIC-овете първо се настройва таймера и се пуска да си цъка прекъсвания постоянно. Тук ако е така пускаш си го и ще ти генерира прекъсванията.
Дотук добре.
Ти си харесел период 200ms, което значи че трябва да изброиш 25 пъти докато направиш 5 секунди. Значи във прекъсването трябва да инкрементираш един брояч, който ще ти брои до 25. Да го кръстим unsigned char intcnt;
Сега идва ключовият момент.
Искаш да кажеш старт на хронометъра и да почнеш да отчиташ заветните 5 секунди.
Понеже не знаеш какво число държи брояча на прекъсвания и какво брояча на таймера (понеже си вървят свободно) трябва да ги нулираш.
Първо нулираш брояча на таймера , после брояча на прекъсвания, после пак брояча на таймера.
Код:
void start chronometer(void)
{
T0H = 0;
T0L = 0;
intcnt = 0;
T0H = 0;
T0L = 0;
}

Умишлено го нулирам два пъти, първият път може брояча да е на 31 249. Това ми гарантира, че докато нулирам intcnt няма да се извика прекъсването (и да го инкрементира). След това нулирам отново брояча и забележи нулирам последно младшия байт. Така се получава минимално натрупване, докато почнеш да изпълняваш чакането на 5те сек. т.е. максимално точно да е.

Така вече имаш функция с която стартираш хронометъра. Остава и да разбереш кога ти е изтекло времето.
Код:
void interrupt ISR (void)
{
  timerflag = false; // При теб не зная как е кръстен флага
  intcnt++; // инкрементираме брояча на прекъсвания (пакети по 200ms)
  if( intcnt == 25 ) // това нещо може да го проверяваш и в основния цикъл
     IztekloWreme(); // ако не е критично към точността на времето
}


Код:
void IztekloWreme(void)
{
NeshtoSi(); // Тука си прайкаш каквото искаш, след като изтекат заветните 5 сек.
}

Има и други начини, със стартиране и спиране на таймера. Аз обаче в моите програми не ги ползвам, тъй като таймера дава тайминги и на други процеси. Освен това не ми са критични толкова времената.
Има и други варианти PICовете имат постскалери, постскалера е това което е intcnt. Само, че може да се настрои автоматично да брои примерно до 16 и тогава да ти се генерира прекъсване. Този процесор обаче е друг и не зная дали има. Пък и за теб е важно да знаеш принципно как се прави, а към съответния процесор ще се нагодиш лесно. Ако не ти трябва точност, може да се нулира само intcnt, т.е. софтуерният ти постскалер.

_________________
https://github.com/slav4ocom/


Пет Юни 08, 2018 11:25 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 7:04 pm
Мнения: 2586
Местоположение: Велико Търново / София
Мнение Re: Zilog - Z8 Encore! F083A Series
Всъщност те подведох, intcnt ще се инкрементира винаги и след като се превърти, ще ще вика IztekloWreme();
затова ще използваме семафор BOOL timeout = true; с който ще указваме кога да се работи
Код:
void interrupt ISR (void)
{
timerflag = false;
if( !timeout) // ако таймаута не е изтекъл,
  intcnt++;   // инкрементираме постскалера.
if(intcnt == 25)
  IztekloWreme();
}


Код:
void StartChronometer(void)
{
  T0H = 0;
  T0L = 0;
  intcnt = 0;
  timeout = false;
  T0H = 0;
  T0L = 0;
}


Код:
void IztekloWreme(void)
{
  timeout = true; // изтекъл таймаут
  NeshtoSi();
}

когато влезеш в IztekloWreme(); "светваш" семафора и в прекъсванията ти няма да се броят пакетите от 200ms.
Така докато не стартираш отново хронометъра.

_________________
https://github.com/slav4ocom/


Съб Юни 09, 2018 12:02 am
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Благодаря ти за отговора !

Това е което аз направих:

Имам системна честота - 20MHz => Честота на таймера - 20MHz / 128 (prescaler) = 156250Hz => Периода на таймера - 1 / 156250 = 0.0000064s или 6.4us => Таймера се увеличава с 1 на всеки 6.4us.

"За да получиш заветните 200ms, брояча трябва да изброи: 200 000 / 6,4 = 31 250 пъти (периода). Това ти е коефициента на брояча." - Благодаря ти за това изречение ! Точно това исках да разбера. Също така си абсолютно прав, че трябва да избера 250ms, а не 200ms, защото за 5s при 200ms, ще имам 25 прекъсвания, а за 5s при 250ms, ще имам 20 прекъсвания, което са си 5 по-малко :)

=> началната стойност на таймера ще е 250 00 / 6.4 = 39062.5 пъти (периода) => ще брои от 39062.5 до 65535 => прекъсване и следния код:

void interrupt Timer0_ISR(void) _At TIMER0
{
static u08 Delay_Counter_5s = 1;

if (Delay_Counter_5s == 11)
{
PAOUT ^= 1<<POUT0_VALUE; /* Превключване на нивото на извод PA0 */

Delay_Counter_5s=0;
}

else
{
Delay_Counter_5s++;
}

T0CTL1 |= 1<<TEN_BIT; /* Стартиране на таймера отново (One-shot mode) */
}

Логиката ми е:

Таймера почва да брои до 65535 => прекъсване - 1=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 2=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 3=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 4=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 5=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 6=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 7=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 8=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 9=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 10=11 (false) - брояча се увеличава => Таймера почва да брои до 65535 => прекъсване - 11=11 (true) - светва диода и нулираме брояча

Така, имаме 10 прекъсвания на таймера и 10 на софтуерния броят, демек общо 20 прекъсвания. Това ли трябва да ми е логиката ? Надявам се да, защото уж на пръв поглед един прост таймер ми отне толкова време за разбиране, че ужас :rolleyes: :rolleyes: :rolleyes:

Сега, като засека с хронометъра уж са 5s, но все пак не мога да съм абсолютно сигурен.


Нед Юни 10, 2018 11:23 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 10:53 pm
Мнения: 4194
Местоположение: Brussels / Пловдив
Мнение Re: Zilog - Z8 Encore! F083A Series
Вземи си един евтин логически анализатор за няма и $10 и ще може да го измериш достатъчно точно + ще ти е в полза и в бъдеще.

_________________
Мразя да мразя ...


Нед Юни 10, 2018 1:15 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 25 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 6 госта


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

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни