"A /= 2" или же "A >>=1"?
Dec. 29th, 2016 04:04 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Я всегда думал, что это одно и то же, однако, оказалось, что совсем не так! Обратил внимание, что код из предыдущей записи как-то неоптимально компилируется: в ассемблерном листинге в операции деления на 2 вместо сдвига было реальное деление. "Что за нафиг?" — подумал я, и заменил деление на сдвиг. Благо, коммит не делал — решил сначала проверить. И вот, вместо ожидаемого периода в 10мс (6000 об/мин) получаю какую-то чертовщину! Меняю обратно на деление: вуаля!
Что за … ?
Вот так — работает:
А вот так — не работает!
Значения current_RPM — от 180 до 6000, т.е. в uint16_t влезают с хорошим запасом! Что за фокусы gcc выдает?
Что за … ?
Вот так — работает:
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 выдает?