Перейти к содержанию
    

Таймер с обратным отсчетом на AVR atmega 128

Доброго времени суток!
Прошу помощи. Занялся изучением мк. Попытался написать таймер обратного отсчета.
Суть следующая написал исходник где переменные должны меняться по достижению определенного значения. Важный момент, таймер МК настроен на децесекунды, и итерации кнопкой проходят по 10 децесекунд, то есть +1 секунда
Но когда таймер получает первую минуту, то при дальнейшей итерации - увеличение минут не происходит, а продолжается наращивание секунд, уверен что ошибся в написании функции. ПРошу помощи как лучше реализовать данную функцию.
Видео поведения таймера прикладываю

https://youtu.be/8j1sTrgwCcw

Spoiler

//-------------------------------------------------------------------------------------------------------------------------
unsigned int d_min = 0, min = 0, d_sec = 0, sec = 0, dsec = 0, z = 0, desec = 0;            // Создаю переменные для разрядов на дисплее (тысячи, сотни, десятки, еденицы)
//-------------------------------------------------------------------------------------------------------------------------
void chislo (unsigned int tiki)                         // Создаю функцию для дробления 5х значного числа на разряды
{
    d_min = tiki/10000;                         // десятки минут
    min = tiki/1000;                            // минуты
    d_sec = tiki%1000/100;                      // сотни
    sec = tiki%100/10;                          // десятки
    dsec = tiki%10;                             // единицы
    
    if (dsec==10){sec++; dsec=0;}
    
    if (sec==10){d_sec++; sec=0;}
    
    if (d_sec==6){min++; d_sec=0;}
    
    if (min==10){d_min++; min=0;}
}
 
 
//-------------------------------------------------------------------------------------------------------------------------
void timer1_ini(void)                                   //настройка таймера счетчика первого
{
    TCNT1 = 0;                                          // обнуляем счетный регистр
    OCR1A = 3125;                                       // Указываем число для сравнения в регистр сравнения
    TIMSK |= (1<<OCIE1A);                               // Включаем бит разрешения сравнения с OCR1A
}
//-------------------------------------------------------------------------------------------------------------------------
void timer1_start(void)                                 //Запуск первого таймера счетчика с предделителем на 256 и разрешением сравнения
{
    TCCR1B |= (1<<WGM12)|(1<<CS12);
}
//-------------------------------------------------------------------------------------------------------------------------
void timer1_stop(void)                                  //Остановка первого таймера
{
    TCCR1B &= ~((1<<WGM12)|(1<<CS12));
}
//-------------------------------------------------------------------------------------------------------------------------
ISR(TIMER1_COMPA_vect)                                  // Создаю макрос тиканья таймера
{
        if (--desec<=0)
        {
            desec = 0;
            PORTF |= (1<<4);
            TCCR1B &=~(1<<CS12);
        }
}
//-------------------------------------------------------------------------------------------------------------------------
void button_on(void)                                    // Активирую порты D и Е на выход, что бы использовать кнопки
{
    DDRD = 0x00;
    PORTD |= (1<<6) | (1<<7);
    DDRE  |= (0<<6) | (0<<7);
    PORTE |= (1<<6) | (1<<7);
}
//-------------------------------------------------------------------------------------------------------------------------
void rele(void)                                         // Активирую Порт F на выход, для того что бы активировать реле
{
    DDRF |= (1<<4);
    PORTF = 0x00;
}
//-------------------------------------------------------------------------------------------------------------------------
void displey_port(void)                                 // Активирую Порт B на выход, для того что бы активировать реле
{
    DDRB  = 0xff;
    PORTB = 0x00;
}
//-------------------------------------------------------------------------------------------------------------------------
 
int main(void)
{
    timer1_ini();
    timer1_start();
    timer1_stop();
    button_on();
    rele();
    displey_port();
    sei();                      // глобальные прерывания включены
    Lcd_init();
    Lcd_clear();
    Lcd_update();
    LcdContrast(62);
    while (1) 
    { 
        chislo(desec);
        if (~PIND&(1<<6))
        {
            desec+=10;
            if(desec>=66526) desec = 66526;
            _delay_ms(150);
        }
        
        if (~PIND&(1<<7))
        {
            desec-=10;
            if(desec<=0) desec = 0;
            _delay_ms(150);
        }
        
        if (~PINE&(1<<6))
        {
            timer1_start();
            PORTB &= ~(1<<4);
            _delay_ms(150);
        }
        
        if (~PINE&(1<<7))
        {
            timer1_stop();
            PORTB |= (1<<4);
            _delay_ms(150);
        }
        Lcd_clear();
        char buff[20];
        itoa(d_min, buff, 10);
        Lcd_print(0, 1, FONT_2X,(unsigned char *)buff);
                
                itoa(min, buff, 10);
                Lcd_print(2, 1, FONT_2X,(unsigned char *)buff);
                Lcd_prints(4, 1, FONT_2X,(unsigned char *)PSTR(":"));
                 
                        itoa(d_sec, buff, 10);
                        Lcd_print(6, 1, FONT_2X,(unsigned char *)buff);
                                               
                                                itoa(sec, buff, 10);
                                                Lcd_print(8, 1, FONT_2X,(unsigned char *)buff);
                                                Lcd_prints(10, 1, FONT_2X,(unsigned char *)PSTR(":"));
                                                                                                itoa(dsec, buff, 10);
                                                                                                Lcd_print(12, 1, FONT_2X,(unsigned char *)buff);
        Lcd_update();
    }
}

 

Изменено пользователем haker_fox
Отформатировал текст, спрятал длинный код в спойлер.

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


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

3 минуты назад, codenamehawk сказал:

Разрядность посмотрите для

unsigned int

if(desec>=66526) desec = 66526;

 if(desec<=0) 

Так он имеет от -32768 до 32767. но если сделать без знаковым, то должен вмещать 65534. Да и разрядность тут не причем. я не переполняю переменную. Я пишу о том что таймер не так отрабатывает.

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


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

4 minutes ago, Devil Byte said:

то должен вмещать 65534

Никогда не видел в конце 4.

В вы сколько туда пытаетесь засунуть?

 

1 hour ago, Devil Byte said:
 d_min = tiki/10000;                         // десятки минут
    min = tiki/1000;                            // минуты
    d_sec = tiki%1000/100;                      // сотни
    sec = tiki%100/10;                          // десятки
    dsec = tiki%10;                             // единицы
  

Этот ряд сбивается.

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

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


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

1 минуту назад, codenamehawk сказал:

В вы сколько туда пытаетесь засунуть?

 

Этот ряд сбивается.

Это ни как на софт не влияет, до исполнения этого if не дайдет. Не понял вашей фразы- ряд сбивается

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


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

5 минут назад, codenamehawk сказал:

Идиде снизу вврех,  min выделяются как-то не так.

 

одна минута это 600 децесекунд... так? подскажите.. я уже голову третий день ломаю)

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


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

28 minutes ago, codenamehawk said:
min = tiki/1000;  

Вы не видите разницы, между тем как получаются  sec, d_sec и min ?

17 minutes ago, Devil Byte said:

одна минута это 600 децесекунд... так?

Так, а теперь вы её делите на 1000, и что получите?

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

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


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

11 минут назад, codenamehawk сказал:

Вы не видите разницы, между тем как получаются  sec, d_sec и min ?

Так, а теперь вы её делите на 1000, и что получите?

 

ну получу 0.6. Я же говорю яч использовал эту функкцию что бы дробить число для сигментного индикатора, но может стоить ее убрать и  например мне конвертировать время исходя из того что в секунде 10 децесекунд, в минуте 60 секунд и так далее. 
просто я не понимаю как мне это написать и обрабатывать это сразу в переменных?

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


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

Только что, codenamehawk сказал:

И еще я не увидел высчитывания минут, когда после 60 секунды.

 

я попытался решить эту проблему через иф    if (dsec==10){sec++; dsec=0;}
    
    if (sec==10){d_sec++; sec=0;}
    
    if (d_sec==6){min++; d_sec=0;}
    
    if (min==10){d_min++; min=0;}

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


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

1 minute ago, Devil Byte said:

ну получу 0.6

Вы может и получите, считая калькулятором, а в проц не получит, вернее не сможет поместить её в uint

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


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

1 минуту назад, codenamehawk сказал:

Вы может и получите, считая калькулятором, а в проц не получит, вернее не сможет поместить её в uint

ну ок а как тогда ? создать переменную long int total? наращивать ее кнопкой по 10

А потом писать так \

int sec=total==10;

int min=sec/60;

а потом ээти переменные выводить?

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


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

Надо составить алгоритм перевода целого числа во время.

2 hours ago, Devil Byte said:
dsec = tiki%10;                             // единицы
    
    if (dsec==10){sec++; dsec=0;}

проверьте какое значение может быть в dsec  и может ли сработать условие if

 

Поставьте себе протеус с можете пошагово отлаживать программу.

17 minutes ago, Devil Byte said:

А потом писать так \

int sec=total==10;

int min=sec/60;

а потом ээти переменные выводить?

Похоже, если исправить ошибку и пересчитывать секунду больше 60 в минуты.

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

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

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


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

11 минут назад, codenamehawk сказал:

Надо составить алгоритм перевода целого числа во время.

проверьте какое значение может быть в dsec  и может ли сработать условие if

 

Поставьте себе протеус с можете пошагово отлаживать программу.

Похоже, если исправить ошибку и пересчитывать секунду больше 60 в минуты.

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

 

почему линукс то? время считается от внутреннего счетчика таймера МК

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


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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...