La virgule fixe est ton amie

Au lieu de diviser ta fréquence comme tu le fais, tu utilises une variable compteur que tu incrémentes à chaque interruption.
L'idée c'est que la valeur du compteur va représenter un nombre à virgule (avec un nombre fixe de chiffres après la virgule) au lieu d'une valeur entière. Mais comme les CPU utilisent nativement des entiers, tu vas en fait stocker cette valeur multipliée par un coefficient.
En base 10 ça donnerait par exemple ça, avec 2 chiffres après la virgule, donc une multiplication par 100 :
Imaginons que tu veuilles un jeu qui "avance" à 42% de la fréquence de l'interruption, soit un facteur de 0.42. À chaque interruption, tu vas ajouter 42 (0.42 * 100) à ton compteur.
Tu initialises le compteur à 0.
1ère interruption : le compteur vaut 42, c'est moins de 100, tu ne fais rien.
2ème interruption : le compteur vaut 84, c'est toujours moins de 100, tu ne fais toujours rien.
3ème interruption : le compteur vaut 126, c'est plus que 100, donc tu retranches 100 (ça donne 26) et tu fais "avancer" ton jeu d'un cran.
(note : si ton incrément est plus grand que 100, pour simuler une fréquence plus rapide, le total peut atteindre ou dépasser 200. Dans ce cas il faut retirer 100 autant de fois que nécessaire pour que le compteur reste entre 0 et 99, autrement dit calculer modulo 100).
Etc.
Si tu fais la moyenne, tu trouveras bien une fréquence d'avancement qui vaut 42% de la fréquence de l'interruption.
En binaire c'est encore plus simple : sur les 32 bits de ton registre, tu réserves n bits (supérieurs) pour la partie entière, et le reste pour la partie décimale. Pour récupérer la partie entière, il suffit d'un décalage à droite ; et pour calculer le modulo, d'un masquage.