На крайний случай можно обойтись и без осцила: сварганить фильтр на RC цепочке с частотой среза в единицы герц (сотню кОм на пару мкФ) и измерить вольтметром эффективное (среднее) напряжение - его отношение к Vcc будет равно коэффициенту заполнения. Но довольно грубо, процентов 15 (ёмкость обычно известна плохо, тем более если её нечем измерить).
Хуже всего, что на 8 МГц похоже он вообще не сможет их никак обработать
400кГц аппаратных это хорошо, значит пока байтики ползут можно делать что-то другое (добавлять их к буферу).
Что можно сделать.
Уменьшить усреднение до 256 - деление на 256 можно сделать просто выборкой со сдвигом на байт (снова хитрый union). Плюс 4 раза в секунду сделать преобразование чисел в строку (пусть даже понадобится 7 делений) это слёзы, доли мс из 250мс.
Перенести все локальные переменные в прерываниях внутрь прерываний и объявить их register - есть надежда что работа с ними ускорится (хотя компилятор и так мог это сделать для всех кроме volatile).
Сделать пересылку по i2c тоже по прерываниям. Всю. И выдачу, и приём. Сложно, да. (Я бы сделал как автомат состояний, причём ради скорости даже не на куче if или switch, а векторным goto на метки.) Зато будет тратиться лишь столько времени сколько реально надо чтобы считать байт и записать его в буфер это порядка мкс (ну плюс накладные расхода на прерывание, но они порядка пары мкс, зато не ждать впустую 20мкс байта). И сразу добавлять их к буферу (это по идее быстро, мкс).
Честно говоря я не сталкивался чтобы вот так прям не хватало скорости, подумаешь 19 Кбайт/с по i2c принять, на 8МГц это по 400 тактов на байт, времени завались, реально должно хватать тактов по 30-50 на байт, т.е. затраты на приём данных (и сложение в буфере) должны быть порядка 10%. А уж вывод 4 раза в секунду вообще единицы процента, если не доли. Так что по моему запас огромный, и куда он весь деётся неплохо бы разобраться. Ну то есть понятно что 22.5*19=430мкс сейчас может уходить на приём по i2c (80% из которых тупое ожидание пересылки байта), но даже это ведь меньше половины доступного времени.
Кардинальное решение - переписать прерывания (и uart и i2c) на асме, это позволит не сохранять регистры и уложить по максимуму всё в регистры (не верю что компилятор с этим хорошо справляется). Правда не знаю можно ли компилятору указать что некие регистры заняты прерыванием и не использовать их. Да и асм дело такое, не самое лёгкое.