Zákmity tlačítek řeším tak, že do registru (nebo do proměnné) shiftuju stav tlačítka (1 když není stisknuto, 0 když je - dávám tlačítko na GND a zapínám interní pull-up). Jakmile se v registru objeví 0x00, tak vím, že se 8x přečetlo jako stisknuté a tím pádem ho beru jako stisknuté. Tlačítko “vypnu” až, když se v registru načte 0xFF. Ostatní mezi se ignoruje a stav tlačítka se pro další zpracování nemění. Druhá varianta je brát hodnotu 0x00 jako stisknuté tlačítko, vše ostatní jako nestisknuté.
Já tlačítka řeším tak, že za platný stisk beru i jakýkoliv zákmit (protože znamená jen nedostatečný kontakt, ale je to stisk), takže používám čítač - jakmile je detekován příznak stisku, nastavím proměnnou čítače tlačítka a beru tlačítko jako stisknuté. V obsluze časovače (přerušení nebo smyčka pro multiplex) čítače dekrementuju a když dosáhne nuly, od té doby beru tlačítko jako nestisknuté. Tedy - stisknuté tlačítko znamená nenulový stav čítače.
[code]#define BTNHOLD 20
char btn1cnt = 0;
char downbtn1() // test drzeni tlacitka
{
if (…stisknuto?..) btn1cnt=BTNHOLD;
return btn1cnt > 0;
}
char pressbtn1() // test stisku tlacitka
{
char up = (btn1cnt == 0);
return downbtn1() && up;
}
…v obsluze timeru:
if (btn1cnt > 0) btn1cnt–;[/code]
No tak toto je poslední verze mých hodin … nechápu jakto že mám t tlačítka tak extrémně nespolehlivá. Dokonce se to občas samo spíná … mám tam pull up, tlačítkama to stahuju k nule. Mám tam funkci IfPinLow, která by měla být spolehlivá … A co hůř, když ty tlačítka mačkám, tak mi to téměř nikdy nereaguje (
Zde kód v pastebin: (možná to tam bude přehlednější
pastebin.com/embed_js.php?i=M5MZq5ma
Zde samotný kód:
/*
* RTC_rev2.c
*
* Created: 28.4.2013 10:32:34
* Author: Slav3k
*/
#define F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lcd1602.h"
volatile uint8_t sek, min, hod; // inty pro uložení času
volatile char time_str [8]; // string pro tisk na displey
ISR (TIMER2_OVF_vect)
{ /*** Přerušení od timeru 2, real time clock 1 sek ***/
sek++;
if (sek >= 60)
{
sek = 0;
min++;
}
if(min >= 60)
{
min = 0;
hod++;
}
if(hod >= 24) hod = 0;
time_show();
}
char IfPinLow (const uint16_t MYPORT, const uint8_t MYPIN )
{
if(MYPORT&MYPIN) return 0;
_delay_ms(2);
if(MYPORT&MYPIN) return 0;
_delay_ms(2);
if(MYPORT&MYPIN) return 0;
_delay_ms(2);
if(MYPORT&MYPIN) return 0;
return 1;
}
void time_init(void)
{
lcdFunc(LCD_FUNC_CLEAR);
lcdFunc(LCD_FUNC_ONOFF);
lcdSetPos(LCD_LINE1);
lcdWrite("Nastavte cas:", 13);
lcdFunc(LCD_FUNC_ONOFF | LCD_VAR_DISPON);
time_show();
// ***NASTAVENÍ HODIN***
while(1)
{
if(IfPinLow(PINC, PC1)) hod++;
while(IfPinLow(PINC, PC1));
if(hod >=24) hod = 0;
_delay_ms(5); //zpomalení, aby neblikal displey
time_show();
if(IfPinLow(PINB, PB2)) break;
}
while(IfPinLow(PINB, PB2));
// ***NASTAVENÍ MINUT***
while(1)
{
if(IfPinLow(PINC, PC1)) min++;
while(IfPinLow(PINC, PC1));
if(hod >=24) min = 0;
_delay_ms(5); //zpomalení, aby neblikal displey
time_show();
if(IfPinLow(PINB, PB2)) break;
}
while(IfPinLow(PINB, PB2));
// ***NASTAVENÍ SEKUND***
while(1)
{
if(IfPinLow(PINC, PC1)) sek++;
while(IfPinLow(PINC, PC1));
if(hod >=24) sek = 0;
_delay_ms(5); //zpomalení, aby neblikal displey
time_show();
if(IfPinLow(PINB, PB2)) break;
}
while(IfPinLow(PINB, PB2));
lcdFunc(LCD_FUNC_ONOFF);
lcdSetPos(LCD_LINE1);
lcdWrite(" ", 16);
lcdSetPos(LCD_LINE1+1);
lcdWrite(":Aktualni Cas:", 14);
lcdFunc(LCD_FUNC_ONOFF | LCD_VAR_DISPON);
Timer2Init();
}
void time_show(void)
{
/*** z intů chary pro tisk ***/
time_str [0] = hod/10 + '0';
time_str [1] = hod%10 + '0';
time_str [3] = min/10 + '0';
time_str [4] = min%10 + '0';
time_str [6] = sek/10 + '0';
time_str [7] = sek%10 + '0';
lcdFunc(LCD_FUNC_ONOFF);
lcdSetPos(LCD_LINE2 +4);
lcdWrite(time_str,8);
lcdFunc(LCD_FUNC_ONOFF|LCD_VAR_DISPON);
}
void Timer2Init(void)
{
TCCR2 |= (1<<CS22) | (1<<CS20);
ASSR |= (1<<AS2);
TIMSK |= (1<<TOIE2);
sei();
}
void PortInit(void)
{
DDRB |= (1<<PB0); //výstup
PORTB |= (1<<PB2); //interní pull up
PORTC |= (1<<PC1); //interní pull up
}
int main(void)
{
lcdInit(); // init displeye
time_str [2] = ':';
time_str [5] = ':';
PortInit(); //innit portů
time_init(); //uvodní menu, kde se nastaví čas
while(1)
{
}
}
administrator: příspěvek byl upraven
Odkaz byl vyjmut z code.
administrator: přiloženy externí soubory
Už to funguje dobře … měl jsem chybu. nešiftoval jsem
if(MYPORT&(1 << MYPIN)) return 0;
tak se nenamáhejte pánové.
díky !
Pánové jak řešíte detekci tlačítka s rozlišením dlouhého(např. 2s) a krátkého(např. 0,5sec) stisku?
Jednoducho.
Ked indikujes stlacenie tlacitka, zacni inkrementovat, napriklad kazdych 10ms nejaku premennu (vsetky stavy treba samozrejme osetrit ako sa patri)
Po pusteni tlacitka vykonas akciu podla toho ci bolo stlacene kratko alebo dlho. Akciu samozrejme nemozes vykonat pri nabeznej hrane (stleceni) ale az na dobeznej hrane (pusteni tlacitka)
Ak chces zvysovat rychlost inkrementu po stlaceni + alebo -, to sa osetruje priebezne napriklad postupnym zvysovanim hodnoty ktoru pripocitavas k editovanej hodnote.
Jako by byl problém přidat nějakou proměnou kde bude doba [ms] jak dlouho bylo něco naposledy stisknuto. Pak stači jen nastavit dělící hranici.
EDIT: Martin byl rychlejší
ps: ty lidi snad nemají žádnou fantazii
FAntazia sa na skolach neuci ale poucky