@Trans00
Java-разработчик

Поясните, что за магия происходит в этом коде?

Есть программа, которю я пишу под AT89C51. В ней есть кусок, который читает информуцию с внешнего устройства байт за байтом и выводит ее на lcd экран:
void read_mem(){
	int iter;
	char now;
	char now2;
	char char1[4];
	char char2[2];
	for (iter=0; iter<=7;iter++){
		now = RX();
		memory[iter] = now;
		now2 = now;
		//TX(now);		  // commented magic
		sprintf (char1, "%2.2X", now);
		char2[0] = char1[0];
		char2[1] = char1[1];
		lcd_display(char2);
		ms_delay(300);
	}

Char2 - это костыль, который служит для того, чтобы обрезать то, что получается в char1 (там получается FF00 вместо просто FF, если подскажете, как это исправить по-человечески - большое спасибо, но вопрос даже не в этом).
В таком виде как сейчас на экран выводится что-то вроде:"000014 81 7F" вместо "00147F".
НО! коде есть закоментированная магия в виде метода, который передает на то же самое внешнее устройство свой аргумент типа char:
void TX(unsigned char cmd){
 
	unsigned char temp = 0;
	unsigned char iter = 0;
	temp = cmd;
	for (iter=0;iter<8;iter++) {
	    	if (temp&0x01) {
	    		termopin = 0x0;     //transfer 1
	        	us_5_delay();	 	
	        	termopin = 0x1;
	        	us_70_delay();
	    	} else {                //transfer 0
	    		termopin = 0x0;
	        	us_70_delay();
	        	termopin = 0x1;
	        	us_5_delay();
	    	}
		temp >>= 1;
		}
	us_70_delay();
}


Если раскоментировать эту строку по на экране магически появляется правильный текст. Почему??
  • Вопрос задан
  • 2477 просмотров
Решения вопроса 1
gbg
@gbg
Любые ответы на любые вопросы
Ничего "магического" в программировании не бывает:
В данном случае, вы столкнулись с работой оптимизатора. Оптимизатор, видя что в переменной 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);
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Сделайте так, и всё у вас будет работать:
void read_mem(){
  int iter;
  unsigned char now;
  char char1[4];
  for (iter=0; iter<=7;iter++){
    now = RX();
    memory[iter] = now;
    sprintf (char1, "%02X", now);
    lcd_display(char1);
    ms_delay(300);
  }

А именно:
- замените char на unsigned char, чтобы избежать знакового расширения при преобразовании в int при передаче в sprintf;
- добавьте 0 в форматную строку, чтобы значения 0...9 отображались как 00 ... 09.

К тому же ваш char2 не закрыт нулём в конце, так что lcd_display вам может всякого навыводить.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы