__delay_ms() kör INTE med en timer! Det är en ren for-to-next som genererar en kodsnutt som tar en viss tid att fullföra.
Lösningen för dig är att göra en funktion:
Kod: Markera allt
#define true 1
#define false 0
#define Key RA3
#define LED RC3
unsigned char Previous;
while(true)
{
if(!Key && !Previous)
{
// Key has been pressed
Previous = true; // Mark as "Got it!"
if(LED) Led = false;
else LED = true;
}
else Previous = false;
}
Men denna lösning gör att brytaren måste vara utan studs, något som är mycket svårt (omöjligt) med mekaniska brytare. Detta kan antingen lösas vid att avkoppla själva brytaren med någon kondensator eller vid att göra mjukvaran så att den klarar biffen.
Jag föredrar att lösa detta i mjukvara och då är lösningen att läsa fler gångar och när två (eller fler) avläsningar med ett visst tidintervall mellan (50ms?) är identiska är det brytarens status.
Nu börjar det komma in en massa "använd __delay_ms()"-råd men mitt råd är att starta en timer-interrupt med kanske 20-30Hz, då blir resten enkelt.
Jag har som regel att i varje interrupt läsa porten
en enda gång! Ska man använda resultatet fler gångar i samma rutin sparar jag det lästa värde i en variabel. Då undviker man att brytaren studsar mellan första och andra avläsningen. Ska det hela vara 100% bergsäkert använder jag 3 avläsningar efter varandra.
Sedan sparar jag även en variabel med "förra avläsningen" i och först när de två är identiska kollar jag om man har tryckt eller släppt knappen. Efter det är det bara att kolla vad som händer.