Спасибо.
О логике работы я судил по этой картинке:
Спойлер

Когда выводы порта B объявлены как входы, в PORTB можно записать 1, что включит подтягивающие резисторы. Если к выводам ничего не подцеплено, на PINB должны появиться 1. Если записать при этом в PORTB 0, то выводы будут висеть в воздухе и непонятно, что будет в PINB. Если к порту В подцепить катоды светодиодов, подав на аноды питание, то в первом случае светодиоды гореть не будут. И во втором тоже, т.к. тока нет.
Когда выводы порта В объявлены как выходы, в PORTВ можно записать 1, и в PINB появится 1. Если записать 0, то и в PINB появится 0. Если к порту В подцепить катоды светодиодов, подав на аноды питание, то в первом случае светодиоды гореть не будут. А во втором должны загореться, т.к. будут посажены на землю.
По моему так должно работать.
А тут же получается что-то другое. При обявленнии выводов входами всегда в PINB висят нули, и при записи в PORTB нулей загораются светодиоды. Я не пойму, почему так.
Делается это чтобы манипуляции не влияли на выход, за то время как программа будет решать 1 или 0 должен быть на выходе ШИМа в данном такте на выводе контроллера будет удерживаться уровень по инерции. Хотя, по хорошему эту операцию достаточно буферизировать - менять внутреннюю переменную, а потом её за один раз выводить в порт. И не нужны будут всякие подобные шаманства.
Это фраза объясняет структуру программы в виде: объявили порт выходом, записали нужное значение, объявили входом, чтоб чего лишнего не записалось. Я правильно понял? Нет, не правильно

Объявляем выводы входами, записываем в PORTB сначала какие-то промежуточные значения, потом то, что должно быть выведено на него. Объявляем выводы выходами и на них тут же появляется уже находящиеся в PORTB значения. Между двумя объявлениями фактические значения на выводах не меняются, потому и PINB не меняется. Вроде дошло. Еще раз спасибо.