Поиск

«A /= 2» или же «A >>=1»?


Я всегда думал, что это одно и то же, однако, оказалось, что совсем не так! Обратил внимание, что код из предыдущей записи как-то неоптимально компилируется: в ассемблерном листинге в операции деления на 2 вместо сдвига было реальное деление. «Что за нафиг?» — подумал я, и заменил деление на сдвиг. Благо, коммит не делал — решил сначала проверить. И вот, вместо ожидаемого периода в 10мс (6000 об/мин) получаю какую-то чертовщину! Меняю обратно на деление: вуаля!

Что за … ?

Вот так — работает:

uint16_t current_RPM = 0;
/** * Calculate motor speed in RPM * RPM = 1/tim2_arr / 40 * 60 */
void get_RPM(){ uint32_t R = 3000000 / (uint32_t)TIM2_ARR; current_RPM = R/2;
} // calculate TIM2_ARR by RPM
uint16_t get_ARR(uint32_t RPM){ uint32_t R = 3000000 / RPM; R /= 2; return (uint16_t)R;
}


А вот так — не работает!

uint16_t current_RPM = 0;
/** * Calculate motor speed in RPM * RPM = 1/tim2_arr / 40 * 60 */
void get_RPM(){ uint32_t R = 3000000 / (uint32_t)TIM2_ARR; current_RPM = R; current_RPM >>= 1;
} // calculate TIM2_ARR by RPM
uint16_t get_ARR(uint32_t RPM){ uint32_t R = 3000000 / RPM; R >>= 1; return (uint16_t)R;
}


Значения current_RPM — от 180 до 6000, т.е. в uint16_t влезают с хорошим запасом! Что за фокусы gcc выдает? eddy_em.livejournal.com

Добавить комментарий