Что делает код

Vactorman
Vactorman аватар
Offline
Зарегистрирован: 30.05.2013

Здравствуйте!

Возникла необходимость передать данные по интерфейсу UART на контроллер ATMega 328p. Контроллер прошит и работает правильно. Есть кусок кода от другого контроллера на базе Arduino, он собирает буфер значений и передает их. Проблема в том, что сейчас есть необходимость сделать то же самое на другом устройстве и на языке C++. Камнем преткновения стало обилие специфических для Arduino функций, которые сильно затрудняют понимание кода. 

Собственно код:

 

#define RC_CHANS 8 
static int16_t rcData[RC_CHANS]; // interval [1000;2000] 
uint8_t i,ind,check;
uint8_t rcBuf[6+2*RC_CHANS]; 

rcBuf[0] = '$';
rcBuf[1] = 'M';
rcBuf[2] = '<';
rcBuf[3] = 2*RC_CHANS; 
check  = rcBuf[3];
rcBuf[4] = 200; //MSP_SET_RAW_RC
check ^= rcBuf[4];
ind=5;
for(i=0;i<RC_CHANS;i++) {
	rcBuf[ind] =  rcData[i]     & 0xFF;  // вопрос первый: 0xFF - что-то вроде символа-терминатора, означающего конец строки?
	check ^= rcBuf[ind++]; // вопрос второй: что делает оператор ^=
	rcBuf[ind] = (rcData[i]>>8) & 0xFF; 
	check ^= rcBuf[ind++];     
}
rcBuf[ind] = check; 

 

Результатом работы всего этого безобразия является заполненный массив rcBuf. Зачем нужны биты 0xFF и зачем данные из массива rcData переписываются дважды (да еще и с операцией rcData[i]>>8 ).

Прошу прощения за глупые вопросы, но с подобным кодом сталкиваюсь впервые. Прошу знающих людей потратить 10 минут на объяснения. :)

leshak
Offline
Зарегистрирован: 29.09.2011

Вообщем-то, в этом коде ВООБЩЕ нет ничего ардуино-специфического. Это же голый C, так что на вашем "другом устройстве" все это должно скомпилироватся вообще без измнений.

Поэтому для понимая, вам нужно почитать про битовые операции в любом учебнике C/C++

Ну или в справочнике по ардуине Arduino - BitwiseAnd  Arduino - Bitshift

 

rcBuf[ind] =  rcData[i]     & 0xFF; 

Берем младший байт rcData[i] и сохраняем его в rcBuf[] . Теоретически из-за того что rcBuf это байтовый массив, то "&  0xFF" можно было и не делать, он бы потерялся "сам по себе", без дополнительных усилий. Но видимо автор, для читабельности, решил что-бы явно было видно "старший байт" - мы выкидываем

check ^= rcBuf[ind++];

Это сокращенный синтаксис для

check = check ^ rcBuf[ind++];

Ну, а что делает ^  (он же XOR) - думаю уже знаете, если читали первую ссылку.

rcBuf[ind] = (rcData[i]>>8) & 0xFF;

А тут мы сохраняетм в rcBuf - старший байт . А младший выкидываем. И опять, таки, на мой взгляд & 0xFF - излишне (но и не мешает), так как сдвиговая операцию уже заполнила старший байт нуляем.

В итоге: тут, похоже, происходит копирование данных из массива int-тов (то есть каждый элемент двух-байтовый), в одно-байтовый массив. Плюс, в этот же масив запихивается контрольная сумма, которую расчитывали для старшего и младшего байта.

Vactorman
Vactorman аватар
Offline
Зарегистрирован: 30.05.2013

Спасибо большое!!! :)