Ничего "магического" в программировании не бывает:
В данном случае, вы столкнулись с работой оптимизатора. Оптимизатор, видя что в переменной now особого смысла нет, не стал ее создавать, а банально передал в sprintf то, что получил от процедуры RX (а RX наверняка выдает int).
Если же вы раскомментируете TX, оптимизатор не сможет выкинуть переменную, выполнит преобразование в тип char и вы получите верный результат.
Решение: sprintf для перевода байта в шестнадцатиричную строку - выстрел из пушки по воробью:
unsigned char toAlf(unsigned char c)
{
if(c<10)
{
return(c+'0');
}
return(c-10+'A');
}
...
char[0]=toAlf(now>>4);
char[1]=toAlf(now&0x0F);