• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dziwne zachowanie przycisku Tact Switch -mikrokontroler Atmega8A

VPS Starter Arubacloud
0 głosów
212 wizyt
pytanie zadane 31 grudnia 2020 w C i C++ przez tonn204 Mądrala (7,470 p.)

Cześć,  za pomocą mikrokontrolera próbuję zrobić zegar. do nóżek PD2, PD3, PB6, PB7 podłączone 4 przyciski pierwszy ma służyć za wybór godzin/minut/sekund , drugi za zwiększanie wybranej pierwszym przyciskiem wartości, trzeci za zatrzymanie zegara aby móc ustawić czas, czwarty natomiast  za  zatwierdzenie wybranego czasu. Mam już prawie wszystko gotowe, muszę tylko wyeliminować drgania styków. Wiem, że można to robić na wiele sposobów, Z racji, że nie chcę angażować timera ponieważ wykorzystuję go już do liczenia czasu, a innych timerów nie mogę ustawić dokładnie na, np. 60ms to chcę to zrobić sposobem opisanym tutaj. Wtedy przycisku zachowują się dziwnie. Gdy klikam przycisk aby ustawić zegar na daną godzinę / minutę / sekundę to najpierw poprawnie zwiększa się ona co 1, ale gdy chcę kliknąć ponownie nic się nie dzieje. Wygląda to tak jakbym każdego klawisza mógł użyć tylko raz, bo pozostałe zachowują się podobnie: przy pierwszym kliknięciu normalnie działają, a po ponownym nie reagują. Dlaczego tak się dzieje i jak mam to naprawić? Przepraszam za jakość kodu, który tu wstawiam, lecz jest to mój pierwszy większy projekt i dopiero się uczę  dlatego proszę o wyrozumiałość. Dzięki za wszelką pomoc.

/*
     Digital clock
*/

#include <avr/io.h>
#include <avr/interrupt.h>

#include <hd44780.c>

#include <stdio.h>
#include <stdlib.h>

volatile int modeFlag = 1;
volatile int ableToEdit = 1;
volatile int seconds = 0;
volatile int minutes = 0;
volatile int hours = 0;
uint8_t key_lock1;
uint8_t key_lock2;
uint8_t key_lock3;
uint8_t key_lock4;
char secondsBuffer[3];
char minutesBuffer[3];
char hoursBuffer[3];

void key1Pressed()
{
    if(ableToEdit == 1)
    {
        if(!key_lock1 && !(PIND & (1 << PD2)))
        {
            key_lock1 = 1;
            modeFlag++;
            if (modeFlag > 3)
            {
                modeFlag = 1;
            }
        }
        else if(key_lock1 && (PIND & (1 << PD2)))
        {
            key_lock1 ++;
        }
    }
}
void key2Pressed()
{
    if(ableToEdit == 1)
    {
        if(!key_lock2 && !(PIND & (1 << PD3)))
        {
            key_lock2 = 1;
            switch(modeFlag)
            {
            case 1:
                if(hours == 24)
                {
                    hours = 0;
                }
                hours ++;
                break;
            case 2:
                if(minutes == 60)
                {
                    minutes = 0;
                }
                minutes ++;
                break;
            case 3:
                if(seconds == 60)
                {
                    seconds = 0;
                }
                seconds ++;
                break;
            }
        }
        else if(key_lock2 && (PIND & (1 << PD3)))
        {
            key_lock2 ++;
        }
    }
}
void key3Pressed()
{
    if(!key_lock3 && !(PINB & (1 << PB6)))
    {
        key_lock3 = 1;
        ableToEdit = 1;
        TCCR1B &= ~(1 << CS12);
        TCCR1B &= ~(1 << CS10);
    }
    else if(key_lock3 && (PINB & (1 << PB6)))
    {
        key_lock3 ++;
    }

}
void key4Pressed()
{
    if(!key_lock4 && !(PINB & (1 << PB7)))
    {
        key_lock4 = 1;
        ableToEdit = 0;
        TCCR1B |= (1 << CS12) | (1 << CS10);
    }
    else if(key_lock4 && (PIND & (1 << PB7)))
    {
        key_lock4 ++;
    }
}

ISR(TIMER1_COMPA_vect)
{
    seconds++;
    if(seconds == 60)
    {
        seconds = 0;
        minutes ++;
        if(minutes == 60)
        {
            seconds = 0;
            minutes = 0;
            hours ++;
            if(hours == 24)
            {
                hours, minutes, seconds = 0;
            }
        }
    }

}

int main(void)
{
    DDRD &= ~(1 << PD2);
    DDRD &= ~(1 << PD3);
    DDRB &= ~(1 << PB6);
    DDRB &= ~(1 << PB7);

    PORTD |= (1 << PD2);
    PORTD |= (1 << PD3);
    PORTB |= (1 << PB6);
    PORTB |= (1 << PB7);

    _delay_ms(20);

    // LCD init
    LCD_Initalize();

    // Timer init
    TCCR1B |= (1 << WGM12);
    OCR1A = 977;
    TIMSK |= (1 << OCIE1A);

    sei();

    while(1)
    {

        key1Pressed();
        key2Pressed();
        key3Pressed();
        key4Pressed();

        if(hours == 24)
        {
            hours = 0;
        }
        if(minutes == 60)
        {
            minutes = 0;
        }
        if(seconds == 60)
        {
            seconds = 0;
        }

        itoa(seconds, secondsBuffer, 10);
        itoa(minutes, minutesBuffer, 10);
        itoa(hours, hoursBuffer, 10);

        LCD_Clear();
        LCD_GoTo(0, 0);
        LCD_WriteText("Aktualna godzina");
        LCD_GoTo(4, 1);
        switch(hours)
        {
            case 24:
                LCD_WriteText("00");
                break;
            case 0:
                LCD_WriteText("00");
                break;
            case 1:
                LCD_WriteText("01");
                break;
            case 2:
                LCD_WriteText("02");
                break;
            case 3:
                LCD_WriteText("03");
                break;
            case 4:
                LCD_WriteText("04");
                break;
            case 5:
                LCD_WriteText("05");
                break;
            case 6:
                LCD_WriteText("06");
                break;
            case 7:
                LCD_WriteText("07");
                break;
            case 8:
                LCD_WriteText("08");
                break;
            case 9:
                LCD_WriteText("09");
                break;
            default:
                LCD_WriteText(hoursBuffer);
        }
        LCD_GoTo(6, 1);
        LCD_WriteText(":");
        LCD_GoTo(7, 1);
        switch(minutes)
        {
            case 0:
                LCD_WriteText("00");
                break;
            case 1:
                LCD_WriteText("01");
                break;
            case 2:
                LCD_WriteText("02");
                break;
            case 3:
                LCD_WriteText("03");
                break;
            case 4:
                LCD_WriteText("04");
                break;
            case 5:
                LCD_WriteText("05");
                break;
            case 6:
                LCD_WriteText("06");
                break;
            case 7:
                LCD_WriteText("07");
                break;
            case 8:
                LCD_WriteText("08");
                break;
            case 9:
                LCD_WriteText("09");
                break;
            default:
                LCD_WriteText(minutesBuffer);
        }
        LCD_GoTo(9, 1);
        LCD_WriteText(":");
        LCD_GoTo(10, 1);
        switch(seconds)
        {
            case 0:
                LCD_WriteText("00");
                break;
            case 1:
                LCD_WriteText("01");
                break;
            case 2:
                LCD_WriteText("02");
                break;
            case 3:
                LCD_WriteText("03");
                break;
            case 4:
                LCD_WriteText("04");
                break;
            case 5:
                LCD_WriteText("05");
                break;
            case 6:
                LCD_WriteText("06");
                break;
            case 7:
                LCD_WriteText("07");
                break;
            case 8:
                LCD_WriteText("08");
                break;
            case 9:
                LCD_WriteText("09");
                break;
            default:
                LCD_WriteText(secondsBuffer);
        }
        _delay_ms(200);
    }

    return 0;
}

 

komentarz 31 grudnia 2020 przez adrian17 Ekspert (349,240 p.)
(nie chcesz tego zrobić przez kondensator?)
komentarz 31 grudnia 2020 przez Oscar Nałogowiec (29,300 p.)
Co to za dziwna instrukcja w linii 126? Powinieś tam podstawić 0 do zmiennej hour.

Kiedy zerujesz zmienne key_lock1,2,3 i 4? Ustawiasz je jak wykryjesz wciśniety przycisk, a kiedy zerujesz? Bo teraz jest zerowana tylko jak się przepełni. Nie jestem też pewny, czy taki algorytm zadziała. W sumie śledzisz przycisk, nie ma tam żadnego timeoutu. Chyba po inkrementacji powinno być jakieś sprawdzenie, czy osiągnięto odpowiednią wartość.
komentarz 1 stycznia 2021 przez tonn204 Mądrala (7,470 p.)
edycja 1 stycznia 2021 przez tonn204

W funkcji naciśnięcia klawisza sprawdzałem jeszcze warunek czy zmienna jest równa 255 i wtedy zerowałem, ale teraz chyba wolę wykorzystać timer czy to powinno wyglądać mnie więcej tak, że najpierw sprawdzam czy przycisk jest naciśnięty potem czekam, np. 20ms i tutaj już w funkcji obsługi przerwania sprawdzam czy klawisz dalej jest naciśnięty i jeżeli tak to wykonuje to co ma zrobić naciśnięcie przycisku? Coś takiego zadziała poprawnie?

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define timer_start 226

uint8_t key_pressed;

ISR(TIMER0_OVF_vect)
{
    TCNT0 = timer_start;
    if(key_pressed == 0)
    {
        PORTB ^= (1 << PB1);
    }
    TCCR0 &= ~(1 << CS02);
    TCCR0 &= ~(1 << CS00);
}

int main(void)
{
    DDRD &= ~(1 << PD2);
    DDRB |= (1 << PB0);
    DDRB |= (1 << PB1);

    PORTD |= (1 << PD2);
    PORTB |= (1 << PB0);

    _delay_ms(10);

    TIMSK |= (1<<TOIE0);
    TCNT0 = timer_start;

    sei();

    while(1)
    {
        if(!(PIND & (1 << PD2)))
        {
            key_pressed = 1;
            TCCR0 |= (1<<CS02) | (1<<CS00);
        }
        else if(PIND & (1 << PD2))
        {
            key_pressed = 0;
        }
    }

    return 0;
}

 

komentarz 2 stycznia 2021 przez tonn204 Mądrala (7,470 p.)

@Oscar, Po paru testach w skrócie przekonałem się, że moja metoda działa tylko w nie wielu przypadkach dlatego postanowiłem zrobić to za pomocą timera i napisałem coś takiego:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define timer_start 226

ISR(TIMER0_OVF_vect)
{
    TCNT0 = timer_start;
    if(!(PIND & (1 << PD2)))
    {
        PORTB ^= (1 << PB1);
    }
    TCCR0 &= ~(1 << CS02);
    TCCR0 &= ~(1 << CS00);
}

int main(void)
{
    DDRD &= ~(1 << PD2);
    DDRB |= (1 << PB0);
    DDRB |= (1 << PB1);
    PORTB &= ~(1 << PB0);
    PORTD |= (1 << PD2);

    _delay_ms(10);

    TIMSK |= (1<<TOIE0);
    TCNT0 = timer_start; // Przerwanie co 30ms//1MHz//Preskaler 1024

    sei();

    while(1)
    {
        if((PIND & (1 << PD2)))
        {
            TCCR0 |= (1<<CS02) | (1<<CS00);
        }
    }

    return 0;
}

Wygląda na to, że działa dziękuję za pomoc.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
0 odpowiedzi 73 wizyt
pytanie zadane 30 stycznia 2021 w C i C++ przez tonn204 Mądrala (7,470 p.)
0 głosów
1 odpowiedź 354 wizyt
0 głosów
0 odpowiedzi 149 wizyt
pytanie zadane 7 grudnia 2020 w C i C++ przez tonn204 Mądrala (7,470 p.)

92,973 zapytań

141,937 odpowiedzi

321,173 komentarzy

62,301 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...