Ciao e ben venuto nel Forum,
La domanda che hai posto ha diverse soluzioni ma comunque l´idea delle varie soluzioni rimane simile.
Fondamentalmente devi avere una variabile contatore che deve essere periodicamente incrementata in maniera tale che quando raggiunge il valore x hai il ritardo desiderato ed obblighi a compiere una funzione.
Ogni volta che premi un tasto (nel tuo esempio RB1 e RB2) poni zero il contatore in maniera da riavviare il contatore).
Facendo uso del polling potresti per esempio incrementare una variabile ad ogni ciclo e controllare poi il suo valore. Se il valore e´ uguale a limite temporale che hai imposto, allora imponi i tuoi vincoli, altrimenti continui nel polling.
Dentro il tuo ciclo, ogni volta che premi un tasto poni a 0 il contatore.
Non so quanto impiega il tuo ciclo per essere compiuto ma potresti per esempio porre il limite del contatore a 1000 e vedere a quanti secondi corrisponde.
Per il contatore usa una variabile grande del tipo unsigned long int, ma se ottieni il tuo ritardo con piccoli valori, usa anche variabile piu´ piccole.
Se con il valore massimo del contatore non ottieni il ritardo voluto, dovrai usare un secondo contatore che si incrementa quando il primo raggiunge il valore massimo. Il controllo lo dovrai fare sul secondo contattore mentre alla pressione dei tasti devi azzerare entrambi i contatori.
Questa e´ la via del polling, ma potresti usare quella piu´ elegante con le interruzioni e timer.
In ogni modo la filosofia rimarrebbe la stessa. Ad ogni interruzione del timer incrementi un contatore e controlli il suo valore per vedere se e´ passato il tempo voluto. Il contatore deve essere una variabile globale visibile dalla routine delle interruzioni e dal main e dovrebbe essere di tipo volatile (vedi il testo C18 Step by Step cap. VI).
Per mezzo dei timer e le interruzioni hai dei tempi piu´ precisi visto che il ciclo di un "polling" puo´ durare di piu´ o di meno a seconda della pressione di un tasto.
Saluti,
Mauro