Отговори на тема  [ 55 мнения ]  Отиди на страница Предишна  1, 2, 3, 4  Следваща
Zilog - Z8 Encore! F083A Series 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Оценявам ината ти, защото за тези занимания той е нужен.
Но правиш грешката при проблем да регресираш до последното ясно и работещо състояние на програмата. И от там да се опитваш да надграждаш върху него.
Трябва да правиш пренаписване и реорганизации винаги когато се налага за да можеш да надграждаш.

Поради късния час смятам да не ти отговоря сега. Но от пръв поглед се вижда, че си пляснал сметки в прекъсването, които много лесно можеш да изнесеш в основната нишка т.е. while(1) в main(). Възможно е заради претоварване на прекъсването да пропускаш обработка на фронтове.
Каква е честотата на сигнала с която правиш тестовете?

_________________
Най-опасният враг на истината и свободата е мнозинството.


Съб Ное 24, 2018 11:36 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Ами то има известно пренаписване на програмата, но като цяло прилича на старата. В една друга тема ми бяха казали, че код в прекъсване не се пише или поне да не е прекалено много и каквото може да се изнася в основната нишка, както казваш и ти. Друг е моментът обаче, че аз се уча по една книга в която кодът е представен така и не мога да си обясня кой е прав сега и кой крив :)

А като гледам, честотата е приблизително 90 Hz :)


Нед Ное 25, 2018 9:51 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Аааа... ако ще го обръщаме на кой крив кой прав - ще трябва първо да изясним кой-какво разбрал.

С така променената програмка имаш добавена една нова задачка по преконфигурирането на прехващача на таймера - падащ/качващ фронт... Сложил си всичките сметки за изчисление в прекъсването и то преди реда, който извършва преконфигурирацията:
Код:
      {
         t_l = Tcap + overflow_count * Tov;
         T = t_h + t_l;
         k = (t_h * 100) / T;
         
         overflow_count = 0;
         
         T0CTL1 |= 1 << 6; /* Превключване към падащ фронт */
      }

В този блок код, най-спешната задача си я сложил последна. Само с преместване последния ред на първо място в този блок код ще имаш известно подобрение на обработката на събитията. Но като цяло
Код:
...
         T = t_h + t_l;
         k = (t_h * 100) / T;
...

трябва да бъдат изнесени от обработчика на прекъсването в основната нишка. Разбира се не с просто copy-paste, но и известно реорганизиране на програмката.

Задачката е интересна за учебна цел, защото дава възможност да разшириш понятието за atomic.

В случая когато изнесеш в основната нишка смятането на периода и запълването, трябва да осигуриш двойката (t_h,t_l) да бъде прочитана като неделима част.
Дори и ако входния сигнал е с постоянна честота и запълване, заради неизбежния jitter не е допустимо да използваш t_h от един период и t_l от друг период на сигнала. Разбира се въпрос на взимане на решение - дали да е допустимо или не. Но като за учебен пример аз бих взел мерки (t_h,t_l) да бъдат atomic.

Предполагам виждаш, че нито atomic нито "код в прекъсване никога не се пише" са мантри. Ако наистина искаш да учиш, а не просто да се вкопчваш в сигурното, виж следващия примерен код:
Код:
#define Tov                  ((uint16)20000) /* тука знаеш какво да сложиш 20000 е само предположение */
#define T0CAP_LOW      (0)
#define T0CAP_HIGH     (1)
#define FIFO_SIZE        (16)

#define DUTY_VALUE_READING_TIME (25)

volatile uint8 overflow_count = 0;
volatile uint32 t_interval[2][FIFO_SIZE];
volatile uint8 head_i;


void interrupt Timer0_ISR(void) _At TIMER0
{
    uint16 Tcap;

    if(0 == (T0CTL0 & (1 << 0)))
    {
        overflow_count ++;
    }
    else
    {
        Tcap = ((uint32)T0PWMH << 8 | T0PWML);

        if(0 == (T0CTL1 & (1 << 6)))
        {
            T0CTL1 |= 1 << 6;
            t_interval[T0CAP_LOW][head_i % FIFO_SIZE] = Tcap + overflow_count * Tov;
            head_i++;
        }

        else
        {
            T0CTL1 &= ~(1 << 6);
            t_interval[T0CAP_HIGH][head_i % FIFO_SIZE] = Tcap + overflow_count * Tov;
        }

        overflow_count = 0;
    }
}

int main(void)
{
    uint8 i = DUTY_VALUE_READING_TIME;
    uint8 tail_i;
    uint16 DutyCycle = 0;
    uint32 T = 0;
    uint32 t_h;
    uint32 t_l;

    head_i = 0;
    tail_i = 0;

    PortConfig();
    InterruptConfig();
    TimerConfig();

    while(1)
    {
        if(i != 0)
        {
            SendToDisplay(DutyCycle);
            i--;
        }
        else
        {
            if(head_i != tail_i)
            {
                t_h = t_interval[T0CAP_HIGH][tail_i % FIFO_SIZE];
                t_l = t_interval[T0CAP_LOW][tail_i % FIFO_SIZE];
                T  = t_h + t_l;
                if(0 != T)
                {
                    DutyCycle = (t_h * 100) / T;
                }

                tail_i++;
            }

            i = DUTY_VALUE_READING_TIME;
        }
    }
}


пак с уговорката, че това е само подсказка написана на С.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Нед Ное 25, 2018 1:54 pm
Профил
Ранг: Новодошъл
Ранг: Новодошъл
Аватар

Регистриран на: Съб Юни 03, 2017 12:21 pm
Мнения: 163
Мнение Re: Zilog - Z8 Encore! F083A Series
Хареса ми индексирането на FIFO. Доста хитро :)


Нед Ное 25, 2018 2:47 pm
Профил WWW
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Извини ме, но наистина ще съм много благодарен, ако сложиш разяснителни записки срещу новите редове, които си внесъл в кода. Имам в предвид:

- #define FIFO_SIZE (16) - ?
- volatile uint32 t_interval[2][FIFO_SIZE] - ?
- volatile uint8 head_i - ?
- t_interval[T0CAP_LOW][head_i % FIFO_SIZE] = Tcap + overflow_count * Tov - ?
- uint8 tail_i - ?
- t_h = t_interval[T0CAP_HIGH][tail_i % FIFO_SIZE] - ?
- t_l = t_interval[T0CAP_LOW][tail_i % FIFO_SIZE] - ?

Предполагам е нещо на пръв поглед ясно за всички тук във форума (визирам коментара на s.ivanov), но уви не и за мен.

Благодаря ! :)


Нед Ное 25, 2018 10:56 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Аз и да ги напиша май няма много да ти помогнат...

Есенцията е в това че:
volatile uint32 t_interval[2][FIFO_SIZE];
се явява буфер. Това е променлива - двумерен масив.
Този двумерен масив се използва за предаване на прехванатите и първично смлени стойности от нишката на прекъсването към основната нишка - прехвърляне на данни от едно място на друго за да не се задръства канала за предаване.

Между другото, надявах се да си го пробвал и да питаш защо не работи.

Но ще трябва по-подробно да обяснявам, а късно вечер след работа не ми е до това.
head_i, tail_i
са променливи с които се индексира масива. Едната променлива се използва от едната нишка, която вкарва нови данни(head_i), а другата се използва от другата нишка която изважда данните(tail_i). Номерът е: едната само пише - другата само чете, но не трябва да се допуска пишещия да маже върху данните, които в момента се четат.
Забелязал си, че няма забраняване-разрешаване на прекъсвания в основната нишка. Само кода в прекъсването се ползва от тази екстра да се изпълнява със забранени прекъсвания. Основната нишка не му се пречка като ги забранява, а само трябва да изважда постъпилите данни на време...
Защото всяко забраняване на прекъсвания в основната нишка, е възможност за внасяне на закъснение в обработката на събитието от прекъсване.
И тука да разширим мантрата: "код в прекъсване никога не се пише" до "внимавай какъв и колко код слагаш в блок в който прекъсванията са забранени".
Така че има значение и как е написан кода извън "прекъсването". ;)

_________________
Най-опасният враг на истината и свободата е мнозинството.


Пон Ное 26, 2018 11:52 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Извинявам се, просто нямах време да го пробвам, но днес намерих иии...не съм сигурен дали казаното от теб беше шега (...и да питаш защо не работи), но програмката работи безпогрешно 8O Страшно много се зарадвах, но се чувствам тъпо след като не разбирам логиката :oops:

Със сигурност, това което си описал е полезно до някаква степен, но наистина бих се радвал, ако си по-подробен. Оценявам и те разбирам напълно, че след работа не ти се занимава въобще да ми обясняваш. Когато имаш време и желание, можеш да го направиш, ако ли пък не...здраве да е, ще търся други начини и така :)


Вто Ное 27, 2018 6:13 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 03, 2005 1:21 am
Мнения: 10622
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
Извини ме, но наистина ще съм много благодарен, ако сложиш разяснителни записки срещу новите редове, които си внесъл в кода. Имам в предвид:

1. #define FIFO_SIZE (16) - ?
2. volatile uint32 t_interval[2][FIFO_SIZE] - ?
3. t_h = t_interval[T0CAP_HIGH][tail_i % FIFO_SIZE] - ?

Предполагам е нещо на пръв поглед ясно за всички тук във форума (визирам коментара на s.ivanov), но уви не и за мен.

Благодаря ! :)

Ако четеш това което си мисля, виж:
1 - стр. 330
2 - стр. 122, стр. 235
3 - след като видиш горните - стр. 170


Вто Ное 27, 2018 8:56 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3082
Мнение Re: Zilog - Z8 Encore! F083A Series
Стария завет ? :D


Вто Ное 27, 2018 9:27 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 03, 2005 1:21 am
Мнения: 10622
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
Съдейки по микроконтролера който използва, а и по написаното досега, явно използва развойната платка от тук:
http://www.progstarter.com/index.php?lang=bg
Та предполагам че използва и съответните четива...


Вто Ное 27, 2018 9:45 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
..., но днес намерих иии...не съм сигурен дали казаното от теб беше шега (...и да питаш защо не работи), но програмката работи безпогрешно 8O Страшно много се зарадвах, но се чувствам тъпо след като не разбирам логиката :oops


Не, не се шегувах, надявах се да откриеш проблема сам. Или ако не ти някой друг и да поговорим за по-важните неща в това програмче. А не да пишем за декларации на променливи, логика и пр. Трябва да се научиш да разчиташ сорс код писан от друг. Това е половината от това да се научиш да пишеш собствен.
Между другото ето още една мантра: "ако тръгне от раз значи гнилото е заровено по-дълбоко" :)

Дай някаква картинка на платката, която ползваш. Просто ми е любопитно.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Вто Ное 27, 2018 10:25 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Ицо, благодаря ти, ще погледна отново маркираните страници от теб, макар и вече да съм го правил.

Zdrav, абсолютно си прав и те разбирам, ама влез малко и в моите обувки...а те са на човек, който никога не е изучавал програмиране/електроника и т.н.. От няколко месеца се занимавам и то с прекъсвания, като избрах трудния подход, а той е да изучавам С-то и периферията на контролера едновременно. Имам предвид, че ми е двойно по-трудно - първо трябва да разбера как работи таймера да кажем и после как да напиша някоя програмка с таймер на C. Сега, това си е изцяло мой проблем и ми е ясно, че никой не го интересува, но все пак е хубаво да има някаква благосклонност към незнанието ми :)


Прикачени файлове:
Коментар на файл: Ето я платката (всъщност са 2)...
Zilog.jpg
Zilog.jpg [ 235.57 KiB | Прегледано 3392 пъти ]
Вто Ное 27, 2018 11:26 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
...Сега, това си е изцяло мой проблем и ми е ясно, че никой не го интересува, но все пак е хубаво да има някаква благосклонност към незнанието ми

Предполагах че си наясно с използването на паметта и знаеш какво е масив (array). Тук се предполага това да го прочетеш и осмислиш сам.
Нямаше как да знам кой номер обувки носиш :)
Ако масивите не са проблем, дай знак и ще продължим нататък.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Сря Ное 28, 2018 8:55 am
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: Zilog - Z8 Encore! F083A Series
Знам, колко смешно и наивно ще прозвучи, но успях да разчета и осмисля сорс кодът (itso.t, благодаря ти за страниците, които маркира в коментара ти - помогнаха ми) :rolleyes:

Моля, да ме поправите ако греша:

Код:

volatile uint8 overflow_count = 0; /* Брояч на препълванията на таймера*/
volatile uint32 t_interval[2][FIFO_SIZE]; /* Двумерен масив - т.е. 2 едномерни масива с по 16 елемента */
volatile uint8 head_i; /* Индекс на масива, който вкарва нови данни */

void interrupt Timer0_ISR(void) _At TIMER0
{
   uint16 Tcap; /* Прехваната стойност */

    if(0 == (T0CTL0 & (1 << 0))) /* Прекъсване от препълване? */
    {/* Да */
        overflow_count ++; /* Увеличаване на брояча на препълванията */
    }
   
    else
    {/* Не,прекъсване от прехващане */
        Tcap = ((uint32)T0PWMH << 8 | T0PWML); /* Прочитаме записаната стойност в (PWMH,PWML) и я присвояваме на Tcap */

        if(0 == (T0CTL1 & (1 << 6))) /* Прекъсване от нарастващ фронт ? */
        {/* Да */
            T0CTL1 |= 1 << 6; /* Превключване към падащ фронт */
         
            t_interval[T0CAP_LOW][head_i % FIFO_SIZE] = Tcap + overflow_count * Tov; /* Изчислената стойност на ниското
         ниво се записва в 0-ят елемент на едномерният масив (T0CAP_LOW) - 0 % 16 = 0 - Ако левият операнд е по-малък от десния, резултатът е равен на стойността на левия операнд. */
         
            head_i++; /* Увеличаваме индекса на масива, който вкарва данните за да може следващата стойност да се зареди в поредният елемент */
        }

        else
        {/* Не, прекъсване от падащ фронт ? */
            T0CTL1 &= ~(1 << 6); /* Превключване към нарастващ фронт */
         
            t_interval[T0CAP_HIGH][head_i % FIFO_SIZE] = Tcap + overflow_count * Tov; /* Изчислената стойност на високото
         ниво се записва в 0-ят елемент на едномерният масив (T0CAP_HIGH) - 0 % 16 = 0 - Ако левият операнд е по-малък от десния, резултатът е равен на стойността на левия операнд.*/
        }
      
      overflow_count = 0; /* Нулиране на брояча на препълванията*/
    }
}

int main(void)
{
   uint16 DutyCycle = 0; /* Коефициент на запълване */
   uint8 i = DUTY_VALUE_READING_TIME; /* Време за изчитане на нова стойност на DutyCycle */
   uint32 t_h; /* Високо ниво на сигнала */
        uint32 t_l; /* Ниско ниво на сигнала */
   uint8 tail_i; /* Индекс на масива, който изважда данните */
   uint32 T = 0; /* Период на сигнала */
   
   head_i = 0; /* Нулираме индекса, който вкарва нови данни */
        tail_i = 0; /* Нулираме индекса, който изважда данните */
   
   PortConfig();
   InterruptConfig();
   TimerConfig();
   
   while(1)
   {
      if(i != 0)
      {
         SendToDisplay(DutyCycle);
         i--;
      }
      
      else
      {
         if(head_i != tail_i) /* Ако стойността на вкараните данни е различна от стойността на извадените */
                        {
                             t_h = t_interval[T0CAP_HIGH][tail_i % FIFO_SIZE]; /* Стойността, която е в 0-ят елемент на едномерният
            масив (T0CAP_LOW) се присвоява на t_h */
                             t_l = t_interval[T0CAP_LOW][tail_i % FIFO_SIZE]; /* Стойността, която е в 0-ят елемент на едномерният
            масив (T0CAP_LOW) се присвоява на t_h */
                             T  = t_h + t_l; /* Изчисляване на периода */

                             if(0 != T) /* Ако 0 е различно от стойността на периода */
                             {
                                 DutyCycle = (t_h * 100) / T; /* Изчисляване на коефициента на запълване */
                             }

                             tail_i++; /* Увеличаваме индекса на масива, който изважда данните за да може да дойде ред на следващият елемент (стойност) */
                        }

                        i = DUTY_VALUE_READING_TIME; /* Презареждане на времето за изчитане на нова стойност на DutyCycle */
      }
   }
}



Не разбирам само, защото FIFO_SIZE е 16, аз ли си избирам тази стойност?

Сега, друг е въпросът, че кодът работи и аз грешка не мога да открия, но аз не си и мисля, че ще открия при положение, че едва сега осмислих цялата ситуация 8O Мисля си, не трябва ли да нулираме "брояча на препълванията" един път при прекъсването от нарастващ фронт и един път при прекъсването от падащ ? Извинявам се, ако давам глупави идеи :)


Сря Ное 28, 2018 8:53 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Metyyy написа:
Не разбирам само, защото FIFO_SIZE е 16, аз ли си избирам тази стойност?


Да, ти я избираш. Но не се избира произволно. Когато е "степен на двойката" (16=2^4) и ако компилатора е "умен" това ще генерира по-оптимизиран код. Разбирай може да е в пъти по-бавен ако тези две условия не са изпълнени.
Освен това слагайки по-голяма стойност ще бъде заделена повече памет за буфера. В случая 16 е с презапасяване. И 8 и 4 стават, като за пример. Има и други критерии, но това засега стига.

Metyyy написа:
Мисля си, не трябва ли да нулираме "брояча на препълванията" един път при прекъсването от нарастващ фронт и един път при прекъсването от падащ ? Извинявам се, ако давам глупави идеи :)

Погледни добре. Той се нулира и при двата случая. Просто кода за нулиране не е дублиран.

Прегледай отново коментарите около присвояването и четенето от t_interval. Струва ми се имаш нужда или да оправиш терминологията или все още си далеч от истината.

За теб е по-добре ако сам разбереш така наречената "логика". Ако ти се обяснява всичко подробно според мен може да ти се навреди.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Сря Ное 28, 2018 9:54 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 55 мнения ]  Отиди на страница Предишна  1, 2, 3, 4  Следваща

Кой е на линия

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


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

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