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

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

-> t_interval[T0CAP_LOW][head_i % FIFO_SIZE] = Tcap + overflow_count * Tov; - Сега, аз го разбирам, че изчислената стойност (Tcap + overflow_count * Tov) на ниското ниво се записва в първият елемент (с индекс 0) на едномерният масив (T0CAP_LOW);

-> 0 (head_i) % 16 = 0 - Ако левият операнд е по-малък от десния, резултатът е равен на стойността на левия операнд.

-> t_h = t_interval[T0CAP_HIGH][tail_i % FIFO_SIZE]; - Стойността, която е в първият елемент (с индекс 0) на едномерният масив (T0CAP_HIGH) се присвоява на t_h;

-> 0 (tail_i) % 16 = 0 - Ако левият операнд е по-малък от десния, резултатът е равен на стойността на левия операнд.

И нали после увеличаваме head_i и tail_i с цел да вкарваме и изваждаме поредните елементи - a[0], a[1], a[2]...

Почти съм убеден, че съм прав :))


Чет Ное 29, 2018 12:03 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

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

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


Чет Ное 29, 2018 12:31 am
Профил
Ранг: Минаващ
Ранг: Минаващ

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

Е така и не открих каква би следвало да е грешката за която говориш, а и нали каза, че е време да поговорим за по-важните неща в това програмче :))


Чет Ное 29, 2018 10:33 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

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

И не съм казвал, че има грешка. Има проблем заради който при определени условия ще виждаш омазани данни на дисплея.
Т.е. колкото и да се дзвериш в кода, синтактична грешка няма да откриеш. Но функционално, коректната работа зависи от това колко време отнемат задачките в основната нишка, а те засега са 3.
1. Отброяваш завъртанията на основния цикъл while(1) в main();
2. На всяко 25-то завъртане взимаш двойка (t_l,t_h) от импровизираното FIFO и изчисляваш коеф. на запълване;
3. На всички останали завъртания викаш SendToDisplay() за да изобрази изчислената стойност;

В една от предните подсказки бях разместил малко тези задачки, но явно не схвана идеята. А тя е следната. Защо да викаш постоянно SendToDisplay() ако няма промяна в стойността подавана за изобразяване?
Имам смътното усещане, че SendToDisplay() не си отговаря на името и не праща безусловно това което и подадеш към дисплея. Ами най-вероятно пази последно изобразената стойност и проверява дали новата стойност е различна и само ако е различна я подава на дисплейчето. Или заради опростената индикация времето за изпълнение на SendToDisplay() е много малко.
Интерeсно какъв е сорс кода на SendToDisplay() и какво е времето което отнема всяко нейно извикване, защото заради някаква особеност там, не виждаш (де)ефектите, които са заложени в main().

Ето така би трябвало да изглежда main() след съответно вчесване:
Код:
...

#define DUTY_VALUE_READING_TIME (250)

int main(void)
{
    uint16 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)
        {
            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];
                tail_i++;
            }

            i--;
        }
        else
        {
            T  = t_h + t_l;
            if(0 != T)
            {
                 DutyCycle = (t_h * 100) / T;
            }

            SendToDisplay(DutyCycle);

            i = DUTY_VALUE_READING_TIME;
        }
    }
}


Сега остава да кажеш, че не тръгва от раз и да почна да си дъвча мустака :)

Каква е разликата?
В main() следенето на head_i на всяко завъртане на while(1) освен 250-тото. При 250-тото са събрани времеотнемащите задачи, докато се изпълняват те се предполага FIFO-то да си влезе в ролята на буфер и да поема новите подадени двойки (t_l,t_h) от прекъсването.
В случая не се очаква на екрана да се изобразява всяка последователна стойност, а само последната, веднъж на всяко 250-то превъртане на while(1).

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


Чет Ное 29, 2018 8:59 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

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

Ето го и останалото:

Код:

void SendToDisplay(uint16 value)
{
   SendToIndicator1(value % 10);
   Delay(DELAY_CONSTANT_5_MSEC);
   SendToIndicator2(value / 10 % 10);
   Delay(DELAY_CONSTANT_5_MSEC);
   SendToIndicator3(value / 100 % 10);
   Delay(DELAY_CONSTANT_5_MSEC);
}

void SendToIndicator1(uint8 digit)
{
   PBOUT &= ~((1 << 3) | (1 << 4) | (1 << 5)); /* (Препоръчително) Трябва да изгасим 2 и 3-ти индикатор (4 и 5), а също
   и 1 (3) преди да заредим новата стойност за изобразяване */
   
   PCOUT = ConvertTo7SegIndValue(digit);
   
   PBOUT |= 1 << 3; /* За да се появи цифрата на индикатора обаче, е нужно да свържем катода K1 към маса. За целта трябва
   да включим цифровия ключ Q1. */
}

void SendToIndicator2(uint8 digit)
{
   PBOUT &= ~((1 << 3) | (1 << 4) | (1 << 5)); /* (Препоръчително) Трябва да изгасим 2 и 3-ти индикатор (4 и 5), а също
   и 1 (3) преди да заредим новата стойност за изобразяване */
   
   PCOUT = ConvertTo7SegIndValue(digit);
   
   PBOUT |= 1 << 4; /* За да се появи цифрата на индикатора обаче, е нужно да свържем катода K2 към маса. За целта трябва
   да включим цифровия ключ Q2. */
}

void SendToIndicator3(uint8 digit)
{
   PBOUT &= ~((1 << 3) | (1 << 4) | (1 << 5)); /* (Препоръчително) Трябва да изгасим 2 и 3-ти индикатор (4 и 5), а също
   и 1 (3) преди да заредим новата стойност за изобразяване */
   
   PCOUT = ConvertTo7SegIndValue(digit);
   
   PBOUT |= 1 << 5; /* За да се появи цифрата на индикатора обаче, е нужно да свържем катода K3 към маса. За целта трябва
   да включим цифровия ключ Q3. */
}

static uint8 ConvertTo7SegIndValue(uint8 value)
{
   uint8 arr7SegIndValues[] =
   {
      LED_DIGIT_0,
      LED_DIGIT_1,
      LED_DIGIT_2,
      LED_DIGIT_3,
      LED_DIGIT_4,
      LED_DIGIT_5,
      LED_DIGIT_6,
      LED_DIGIT_7,
      LED_DIGIT_8,
      LED_DIGIT_9
   };
   
   return (value > 9) ? LED_DIGIT_ERROR : arr7SegIndValues[value]; /* Ако параметърът value е по-голям от 9 или по-малък от 0, функцията
   връща код за грешка LED_DIGIT_ERR, в противен случай връща arr7SegIndValues[value] */
}

void Delay(uint32 delay)
{
   for(; delay > 0; delay--);
}



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

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

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


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

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


Съб Дек 01, 2018 10:58 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 8:21 pm
Мнения: 28022
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
Да се включа и аз без време, то като цяло организацията ми се вижда малко странна. Sent to display функцията с тези изчаквания вътре е доста неефективна. Концептуално трябва да бутнеш, доколкото помня от предните страници ти въртиш цикъл и веднъж на 250 извъртания ъпдейтваш дисплея, нали така, предполагам за да имаш време за други задачи. Ако оптимизираш самия рефреш, можеш да го викаш много по-често. Според мен си раздели задачите на две, едното е физическия ъпдейт, сложи го на 50 хц или нещо такова за да не ти мига, дори 100, там не прави конверсията къ, bcd а само рефрешвам. Конверсията я прави другаде, и нея може да я правиш на рядко. Така ъпдейта на дисплея ще ти е с фиксирано време, висока честота но ще отнема много малко ресурс и няма да ти мига. Реално добре написан може да влезе в 10-на инструкции.


Съб Дек 01, 2018 12:21 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

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

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


Съб Дек 01, 2018 1:08 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 03, 2005 1:21 am
Мнения: 10622
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
А може би е хубаво сорсът да се погледне в контекста на четивото от което е взет - за начинаещи. Предполагам че целта му (на сорса, а и на книгата) не е да покаже "върховите постижения", а по скоро е нещо работещо, в "четим" вид от прохождащ.
Вероятно нещо като многозадачност е съвсем извън контекста на тоя етап...


Съб Дек 01, 2018 1:21 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 8:21 pm
Мнения: 28022
Местоположение: София
Мнение Re: Zilog - Z8 Encore! F083A Series
лошото е че показвайки нещо работещо, създава лоши навици. Да това кеото казва Здрав е абсолютно така, таймерче, прекъсвания, това е най-оптималното, но ако това за контекста на книгата е било прекалено сложно и неприложимо, нищо не е пречило да се реализира малко по ефективна структура на кода, най-елементарното, с разделянето на кода на логически части не само според функцията им, а и според начинът им на работа. Да съвместяваш в една функция бързи и бавни процеси не е много добра идея. Ако индикацията беше статична, то тогава в тази организация нямаше нищо лошо, макар и да не ми изглежда ОК. Но при динамична индикация, когато имаш процес който трябва да е бърз, в случая със светодиодите няма нужда да е много синхронен с нещо и с константен цикъл, но в други случаи е задължително, някак не се връзва.
Това не ми е силата, не искам да казвам дали е правилно или не, но казвам че не е логично, не е функционално. Но все пак книгите са книги, имат си тяхната насоченост, лошото е че създават и навици. Ей затова лекциите, ако имаш добър преподавател, са много важни, защото винаги може да ти каже това го правим така за да покажем еди какво си, но то не трябва да се реализира така поради 1,2,3 ... казвам го от опита ми в съвсем друга сфера, много често се налага да показвам нещо, примерно ред на сглобяване на някакъв продукт, и много често за да се ускори процеса на запознаване сглобяването не се прави по най-правилния начин, защото примерно целта е да се запомни къде стои тази пружина, а не как е правилният начин за нейният монтаж, което е съвсем друго обучение .. е примера сигурно не е най-добрия но .. .


Съб Дек 01, 2018 1:44 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

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

Прав си за микроконтролера, че има още един таймер и 3 нива на приоритет. Никога не съм ползвал 2-та таймера наведнъж и тия приоритети. Разбира се, бих се радвал с твоя помощ...да реализираме едно "по-работещо" програмче :))


Съб Дек 01, 2018 3:19 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

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

Според мен, истината е по средата. Както нееднократно е ставало въпрос, освен обучение на начинаещите, има значение и времето за постигане на някакъв практически резултат. Ако трябва да се изчетат 8 книги докато се стигне до заветното "blink.c", има голяма вероятност интересът да изчезне.
Вече като се стигне някакво ниво, ако човек има интерес, ще помисли как могат да се оптимизират нещата. Защо някой "батко в програмирането" го е направил така или иначе. Ще последва опит за разчитане на кода, осмисляне на алгоритъма или конкретен синтаксис, ползите от него и т.н.

Цитат:
...слон се яде на малки хапки...


Съб Дек 01, 2018 4:10 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: Zilog - Z8 Encore! F083A Series
Код:
#define SYS_CLK    ((uint32)20000000)
#define T1_PRES    (0x04)
#define T1_CLK    (SYS_CLK/(1 << T1_PRES))

#define DISPLAY_REFRESH_PERIOD_ms    (20)
#define T1PERIOD    (DISPLAY_REFRESH_PERIOD_ms*T1_CLK/1000)

#define INDICATORS_NUM (3)

const uint8 arr7SegIndValues[10] =
{
    LED_DIGIT_0,
    LED_DIGIT_1,
    LED_DIGIT_2,
    LED_DIGIT_3,
    LED_DIGIT_4,
    LED_DIGIT_5,
    LED_DIGIT_6,
    LED_DIGIT_7,
    LED_DIGIT_8,
    LED_DIGIT_9
};

volatile uint8 Ind_i;
volatile uint8 Ind_digit[INDICATORS_NUM];


void T1_Init(void)
{
    T1CTL0 = (0x03 << 5);
    T1CTL1 = (T1_PRES << 3) | (0x01 << 0);

    T1RH = (T1PERIOD >> 8);
    T1RL = (T1PERIOD & 0xFF);

    /* T1 priority - lev 1("Low") */
    IRQ0ENH &= ~(1 << 6);
    IRQ0ENL |= (1 << 6);

    /* T1 enable */
    T1CTL0 |= (1 << 7);
}

void T1_ISR(void) _At TIMER1
{
    uint8 i;

    PBOUT &= ~((1 << 5) | (1 << 4) | (1 << 3));

    i = Ind_i % INDICATORS_NUM;
    PCOUT = ConvertTo7SegIndValue(Ind_digit[i]);

    PBOUT |= (1 << (i + 3));

    Ind_i = i + 1;
}

static uint8 ConvertTo7SegIndValue(uint8 value)
{
   return (value > 9) ? LED_DIGIT_ERROR : arr7SegIndValues[value];
}

void SendToDisplay(uint16 value)
{
    uint8 i;
    for(i = 0; i < INDICATORS_NUM; i++,value /= 10)
    {
        Ind_digit[i] = value % 10;
    }
}

void Display_Init(void)
{
    uint8 i;
    for(i = 0; i < INDICATORS_NUM; i++)
    {
        Ind_digit[i] = LED_DIGIT_ERROR;
    }

    Ind_i = 0;
}


Трябва в main() да извикаш T1_Init() като за начало я сложи между InterruptConfig() и TimerConfig()
И не задължително, но препоръчително да извикаш Display_Init() преди PortConfig() например. Дори и да не я извикаш предполагам, че линкера и компилатора ще се погрижат Ind_i и Ind_digit[] да са нулирани при стартиране на програмката.

Ind_digit[] има нужда да бъде защитена за да се избегне non-atomic достъп при четене от T1_ISR(). За да е по-кратък и ясен сорс кода, защитата съм я оставил настрана, да не се задави някой със "слона".

И намали DUTY_VALUE_READING_TIME. На 25 например.

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


Съб Дек 01, 2018 9:19 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

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

Код:

#define T1_PRES (0x04) /* (0x04) е 0100 = prescaler 16 */

#define T1_CLK  (FSYS / (1 << T1_PRES)) /* Честота на таймера - 20MHz / 16 (prescaler) = 1 250 000 Hz (1250KHz) */

#define DISPLAY_REFRESH_PERIOD_ms (20) /* Това от къде дойде ?  Може би го избирам аз и това ще бъде стойността, на която ще се опресняват индикаторите ? */

#define T1PERIOD (DISPLAY_REFRESH_PERIOD_ms * T1_CLK / 1000) /* Тук периода на Т1 таймера, защо се смята така ? Не трябва ли да е: 1 / 1 250 000 = 0,0000008 s или 0,8 us.



void Timer1_Config(void)
{
    T1CTL0 = (0x03 << 5); /* Конфигуриране на прекъсването от таймера – Демек, ще имаме прекъсване при презареждане (препълване)/сравнение */
    T1CTL1 = (T1_PRES << 3) | (0x01 << 0); /* Коефициент на деление 16 и continuous mode на таймера */

    T1RH = (T1PERIOD >> 8); /* (97 - записваме в старшата част) - (38824 - стойността, до която ще брои таймера) - Тук мисля, че тотално оплесках нещата, защото не ми е ясно, защото периода на Т1 таймера се смята така */
    T1RL = (T1PERIOD & 0xFF); /* (A8 - записваме в младшата част) - (38824 - стойността, до която ще брои таймера) ) - Тук мисля, че тотално оплесках нещата, защото не ми е ясно, защото периода на Т1 таймера се смята така */

    T1CTL0 |= (1 << 7); /* Стартиране на таймера */
}



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

Кой е на линия

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


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

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