Jesús, tengo que discrepar.
Las direcciones de memoria apuntan a bytes, no a nibbles. Cualquier cosa que hagas con nibbles requerirá de alguna argucia para diseccionar un byte.
Fíjate cómo compila tu ejemplo esta instrucción:
.................... uByte.usByte.usNible1 = 5;
0086: MOVLW 05
0087: MOVWF 11
El valor que hubiera en el nibble alto de uByte estaría machacado.
Pues o el compilador o trata mal las estructuras o no son soportadas para nibbles, ya que los dos nibbles los ha separado como dos bytes. El caso es que no da ningún error ni advierte de nada. Bueno, esto da idea de como funciona CCS.
La prueba definitiva es:
uByte.usByte.usNible1 = A;
uByte.usByte.usNible2 = B;
printf("Valor: %X", uByte.nByte);
Deberia devolver en el LCD: "AB"
Un saludo