Das Hauptproblem liegt darin, daß Du die Zeiten nicht berücksichtigst, welche für die eigentlichen Programmzeilen benötigt werden.
Der Timer selbst läuft schon absolut exakt.
Das ist bei tiefen Freuqenzen nicht ganz so tragisch, je höher aber deine Frequenz wird, desto mehr
geht diese zusätzliche Zeit mit ein, bzw. macht sich negativ bemerkbar.
Zwischen deiner "Sprungmarke" und dem Setzen des Ports auf Low, liegt ja deine Tastenabfrage, während dieser
Zeit ist der Portpin weiterhin auf LOW. Während deiner Entprellzeiten ebenfalls.


Um eine exakte Frequenz zu erzeugen gäbe es folgende Möglichkeit.
Ich hoffe, daß ich es nicht zu schwierig erkläre, weil das ist nicht ganz so einfach zu verstehen.
mit dem PIC16F628:

Der RB3/CCP1 Pin ist dein Ausgang für die Frequenz.
Timer 1 wird ganz normale als aufwärtszähler benutzt. Also von 0..65535 mit internem Takt
Das Capture Compare Register CCP1L sowie CCP1H wird als Vergleichsregister benutzt,
also der "Compare Mode" hier muss ein Wert rein, welcher irgendwie deiner Frequenz entspricht.
Wenn der Timer 1 und das Vergleichsregister übereinstimmen, wird etwas ausgelöst.
Hier gibt es einen sogenannten "Special Event Trigger"
Der kann dann den PIN RB3 automatisch entweder auf High oder auf Low setzen.
Das Timer Register wird dann automatisch wieder gelöscht und der Timer fängt wieder an von 0 zu zählen.
So bekommst Du ein einwandfreies Timing. Wenn dann deine Tasten betätigt werden, muss der Wert in den
Registern CCP1L und CCP1H verändert werden.

Prinzipeller Ablauf:
Timer 1 wird auf Asynchron Counter Mode gesetzt.
Du setzt im CCP1M Register den Wert so, daß bei einer Übereinstimmung der Ausgangspin RB3/CCP1 auf High gesetzt wird.
also CCPM BITS = 1000
Wenn ein Interrupt ausgelöst wird, stellt sich der Timer automatisch wieder auf 0 zurück, darum brauchst Du Dich nicht kümmern.
nun stellst Du in aller Ruhe das CCP1M Register so ein, daß bei der nächsten Übereinstimmung der Ausgangspin RB3/CCP1
auf Low geschaltet wird. Also CCPM Bits = 1001
Wenn der nächste Interrupt kommt, stellst Du die CCPM Bits wieder auf 1000 wie am Anfang.
So bekommst Du ein "einwandfreies Timing" für deinen Pin.

Info: Das geht nur mit Timer 1.
Der Inhalt des Zählerregisters vom Timer 1 ist in diesem Falle völlig unwichtig.
In den Registern CCP1L und CCP1H muss der Vergleichswert stehen, wann der PIN umschalten soll.
Also im Prinzip die halbe Frequenz, da der Pin mit jedem Ablauf des Timers umgeschaltet wird.

nicht einfach, gebe ich zu.
ich hoffe, ich konnte Dir damit etwas helfen.

mfg Siro