У меня работа с раскрошенной шиной данных LCD реализована так:
(d & 0x01)? Port_LCD_D0_1 : Port_LCD_D0_0;
(d & 0x02)? Port_LCD_D1_1 : Port_LCD_D1_0;
(d & 0x04)? Port_LCD_D2_1 : Port_LCD_D2_0;
(d & 0x08)? Port_LCD_D3_1 : Port_LCD_D3_0;
(d & 0x10)? Port_LCD_D4_1 : Port_LCD_D4_0;
(d & 0x20)? Port_LCD_D5_1 : Port_LCD_D5_0;
(d & 0x40)? Port_LCD_D6_1 : Port_LCD_D6_0;
(d & 0x80)? Port_LCD_D7_1 : Port_LCD_D7_0;
Этот фрагмент занимает 80 байт. И сколько Вы мне предлагаете сэкономить? Это же смешно. Ну пусть Вы сэкономите 50 байт, это, на мой взгляд, недостаточная плата за весь тот хлам, который придется тащить в проект. А по времени выполнения это тоже ничто по сравнению с Delay_us(50), которая стоит сразу после вывода.
Макросы объявлены в заголовочном файле, где распределяются все порты для проекта:
#define LCD_D0 (1 << PB2)
#define Port_LCD_D0_0 (PORTB &= ~LCD_D0)
#define Port_LCD_D0_1 (PORTB |= LCD_D0)