Die Helligkeit der LEDs ändert sich halt mit der Anzeigedauer und der gewünschten Refresh-Rate.
Die LEDs ohne Pause durchrattern zu lassen gibt die meisten FPS, aber wenn der µC vor jeder Zeile ein paar Zyklen rumkramen muss, dann wird das Bild schnell dunkel, weil er länger nachdenkt als das Bild zu zeigen.

Ein paar Waitms vor der nächsten Zeile kehren das Verhältnis dann um, die FPS werden aber weniger.

Am saubersten wirds mit einem Timer-Interrupt, der dem µC Raum für eventulle Berechnungen läßt und für eine feste Framrate sorgt.

Ganz wichtig ist auf jeden Fall das schwarz-schalten der Reihe vor dem einlesen des neuen Bitmusters in die Spalte. Ansonsten bekommt man Geisterbilder.
Auch kann die letzte/erste Zeile unterschiedlich hell sein, wenn der µC nach jedem Volldurchgang noch was anderes macht...