реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> деление на ноль
Jenya7
сообщение Feb 19 2014, 10:20
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



надоело все время высчитывать делитель для таймера - решил автоматизировать процесс:
CODE
#define F_CPU 72000000UL
#define F_CPU_MHZ 72
#define SYSTEM_TICK_NS ((1 /F_CPU_MHZ) * 1000UL)

uint32_t GetPrescaleForDelay(uint32_t delay, char * units)
{
uint32_t prescale;
uint32_t multiplyer;
uint32_t ticks;

if(strcmp(units,"ns")==0)
{ multiplyer = 1; }
else if(strcmp(units,"us")==0)
{ multiplyer = 1000; }
else if(strcmp(units,"ms")==0)
{ multiplyer = 1000000; }
//else
//{ return 0; }

//how many ticks needed for delay
// if(SYSTEM_TICK_NS > 0) //не помогает
ticks = (delay * multiplyer) / SYSTEM_TICK_NS;

prescale = F_CPU / ticks;
return prescale;
}


компайлер честно предупреждает - Warning[Pe039]: division by zero на строчке ticks = (delay * multiplyer) / SYSTEM_TICK_NS;

но это как то действует на нервы. как бороться с делением на ноль?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 19 2014, 10:35
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Jenya7 @ Feb 19 2014, 14:20) *
компайлер честно предупреждает - Warning[Pe039]: division by zero на строчке ticks = (delay * multiplyer) / SYSTEM_TICK_NS;

Попробуйте подавить выдачу предупреждения - компиляторы обычно дают такую возможность.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 19 2014, 10:43
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



У вас SYSTEM_TICK_NS будет равен нулю для любого F_CPU_MHZ больше 1.
Исправьте SYSTEM_TICK_NS на

Код
#define SYSTEM_TICK_NS (1000UL /F_CPU_MHZ)


Цитата(_Артём_ @ Feb 19 2014, 12:35) *
Попробуйте подавить выдачу предупреждения
Ой.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 19 2014, 11:23
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Сергей Борщ @ Feb 19 2014, 15:43) *
У вас SYSTEM_TICK_NS будет равен нулю для любого F_CPU_MHZ больше 1.
Исправьте SYSTEM_TICK_NS на

Код
#define SYSTEM_TICK_NS (1000UL /F_CPU_MHZ)


Ой.


ой спасибо - так не ругается.
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 19 2014, 12:47
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Jenya7 @ Feb 19 2014, 15:23) *
ой спасибо - так не ругается.

Вы бы лучше разобрались, как работает целочисленная арифметика в языке Си. Там таких граблей - море.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 19 2014, 13:06
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(scifi @ Feb 19 2014, 17:47) *
Вы бы лучше разобрались, как работает целочисленная арифметика в языке Си. Там таких граблей - море.

понял - без явного приведения типов компайлер округлит это выражение #define SYSTEM_TICK_NS ((1 /F_CPU_MHZ) * 1000UL) до нуля.
интересно а так можно?
#define SYSTEM_TICK_NS ((float) (1000UL /F_CPU_MHZ)
Go to the top of the page
 
+Quote Post
Andreas1
сообщение Feb 19 2014, 13:11
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 446
Регистрация: 12-03-06
Из: Москва
Пользователь №: 15 142



Цитата(Jenya7 @ Feb 19 2014, 17:06) *
#define SYSTEM_TICK_NS ((float) (1000UL /F_CPU_MHZ)

Сначала округлит, затем во флоат переведет.
Надо писать не 1000UL, а 1000.0 тогда все вычисления будут во флоате и только где уже нужен результат пишете (u32)....
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 19 2014, 13:21
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



или так #define SYSTEM_TICK_NS ((1.0 / F_CPU_MHZ) * 1000.0)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 19 2014, 13:43
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Я бы делал
Код
#define TIMER_TICKS(time_ms)   (((time_ms) * F_CPU + 500)/ 1000)
....
ticks = TIMER_TICKS(delay * multiplyer);


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 19 2014, 14:00
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Сергей Борщ @ Feb 19 2014, 18:43) *
Я бы делал
Код
#define TIMER_TICKS(time_ms)   (((time_ms) * F_CPU + 500)/ 1000)
....
ticks = TIMER_TICKS(delay * multiplyer);


Сергей как всегда крут. a14.gif
Go to the top of the page
 
+Quote Post
Andreas1
сообщение Feb 19 2014, 14:10
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 446
Регистрация: 12-03-06
Из: Москва
Пользователь №: 15 142



Вроде по умолчанию S16 числа? Переполнение не выходит?
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 19 2014, 14:53
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Andreas1 @ Feb 19 2014, 19:10) *
Вроде по умолчанию S16 числа? Переполнение не выходит?

это интересное замечание, надо проверить.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 03:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01948 секунд с 7
ELECTRONIX ©2004-2016