eddy_em: (Костерок)
[personal profile] eddy_em
Я всегда думал, что это одно и то же, однако, оказалось, что совсем не так! Обратил внимание, что код из предыдущей записи как-то неоптимально компилируется: в ассемблерном листинге в операции деления на 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 выдает?

Date: 2016-12-29 01:46 pm (UTC)
From: [identity profile] balmerdx.livejournal.com
А вариант
void get_RPM(){
uint32_t R = 3000000 / (uint32_t)TIM2_ARR;
current_RPM = R >> 1;
}

пробовал? Чтобы точно быть уверенным, что нет переполнения?

Date: 2016-12-29 02:59 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
Сейчас деление реализуется через сдвиг и считается все правильно.

Date: 2016-12-29 02:15 pm (UTC)
From: [identity profile] mbr.livejournal.com
current_RPM тип uint16_t

Не дочитал.

Давай ассемблерный листинг.
Edited Date: 2016-12-29 02:16 pm (UTC)

Date: 2016-12-29 02:58 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
Вот блин! Зря я не сохранил старые листинги. Сейчас пробую и -Os, и -O2, и -O3 — все равно одинаково получается: что деление, что сдвиг в ассемблере абсолютно одинаковы, т.е. gcc все правильно делает.

Чертовщина какая-то!
Похоже, что-то у меня там было int, а не uint. Зря я коммита с багом не сделал — теперь и не поймешь, что же там у меня было.

Бывает иногда у меня такая фигня: вроде бы ничего не сделал, код после кучи манипуляций как будто бы вернулся к предыдущему виду, а проблема исчезла.

Date: 2016-12-29 03:01 pm (UTC)
From: [identity profile] mbr.livejournal.com
Это скорее дело в билде. Прежде чем ругать gcc, надо clean делать :)

Date: 2016-12-29 03:03 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
И правда, я когда фигню неведомую заметил, clean не сделал.

October 2025

S M T W T F S
   1234
567 89 1011
121314 15161718
19202122232425
2627 28293031 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 25th, 2026 02:36 pm
Powered by Dreamwidth Studios