AndryG 0 26 февраля, 2015 Опубликовано 26 февраля, 2015 · Жалоба #define F_CPU 8000000u #define MB_BAUD_RATE 38400 #define MB_TIMER_PRESCALER 64 #if MB_BAUD_RATE > 19200 // не растет кокос :( #define MB_OCR_T25 (F_CPU / MB_TIMER_PRESCALER * (11 / MB_BAUD_RATE + 0.00075)) #define MB_OCR_T45 (F_CPU / MB_TIMER_PRESCALER * (11 / MB_BAUD_RATE + 0.00175)) #else // тут я вроде как разобрался как на форуме советовали: сперва умножать побольше и потом делить поменьше #define MB_OCR_T25 (F_CPU / MB_TIMER_PRESCALER * 11 * 25 /10 / MB_BAUD_RATE) #define MB_OCR_T45 (F_CPU / MB_TIMER_PRESCALER * 11 * 45 /10 / MB_BAUD_RATE) #endif Компилятор считает не то, что хочется. Результат выходит буд-то "11 / MB_BAUD_RATE" вообще нет код volatile uint8_t ocr25 = (uint8_t)MB_OCR_T25; листинг после препроцессора volatile uint8_t ocr25 = (uint8_t)(8000000u / 64 * (11 / 38400 + 0.00075)); и асм // 48 volatile uint8_t ocr25 = (uint8_t)MB_OCR_T25; LDI R16, 93 !!! а должно быть 129 ST Y, R16 Ещё препроцессору не нравится вот это: #if mb_ocr_test < MB_OCR_T25 || mb_ocr_test < MB_OCR_T45 #Error[Pe031]: expression must have integral type Во втором варианте расчета было "* 2.5". После замены на " * 25 / 10" ругаться перестал. На сим сделал вывод, что препроцессор знает только целочисленную математику. Компилятор ещё намекает, что не всё в порядке с вычислением: uint8_t ocr25 = MB_OCR_T25; #Warning[Pa092]: implicit conversion to integer does not preserve the value OCR0A = TCNT0 + MB_OCR_T45; #Warning[Pa093]: implicit conversion from floating point to integer Здесь, я так понял, надо приведение типа, ибо компилятор все же считает не целочисленно. Но проблему с ошибкой вычисления это не решает :( OCR0A = TCNT0 + (uint8_t)MB_OCR_T45; // ругаться перестал Подскажите, пжлст, где про это почитать подробней (сколько листал - не нахожу по теме)? Может встречал кто утилиты/онлайн сервисы для просмотра "и что нам насчитают"? Довольно неудобно лазить по листингам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 36 26 февраля, 2015 Опубликовано 26 февраля, 2015 · Жалоба #define MB_TIMER_PRESCALER 64 ... // не растет кокос :( #define MB_OCR_T25 (F_CPU / MB_TIMER_PRESCALER * (11 / MB_BAUD_RATE + 0.00075)) ... Компилятор считает не то, что хочется. Результат выходит буд-то "11 / MB_BAUD_RATE" вообще нет. Компилятор поступает совершенно правильно, полагая, что выражения "11 / MB_BAUD_RATE" вообще нет, поскольку в целых числах 11 / 64 = 0 А если хотите, чтобы результат получился дробным, то пишите так: 11.0 / MB_BAUD_RATE Но с дробью F_CPU / MB_TIMER_PRESCALER у вас та же история - дробную часть вы теряете. // тут я вроде как разобрался как на форуме советовали: сперва умножать побольше и потом делить поменьше #define MB_OCR_T25 (F_CPU / MB_TIMER_PRESCALER * 11 * 25 /10 / MB_BAUD_RATE) Ну, так и делайте, как вам советовали на форуме, а то, что вы написали, этому совету противоречит, т.к там уже вторая операция - деление. Но если последовать тому совету буквально, то у вас возникнет переполнение произведения в разрядной сетке целого. Поэтому было бы лучше определить F_CPU как long, чтобы произведение не было урезанным. Тогда оно будет выглядеть так: #define F_CPU 8000000L #define MB_OCR_T25 (F_CPU * 11 * 25 / 10 / MB_BAUD_RATE / MB_TIMER_PRESCALER) Или еще (uint8_t) туда добавить, чтобы компилятор warning не выдавал: #define MB_OCR_T25 ((uint8_t)(F_CPU * 11 * 25 / 10 / MB_BAUD_RATE / MB_TIMER_PRESCALER)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndryG 0 26 февраля, 2015 Опубликовано 26 февраля, 2015 · Жалоба 11.0 / MB_BAUD_RATE Вот это я поймался! Спасибо. Но с дробью F_CPU / MB_TIMER_PRESCALER у вас та же история - дробную часть вы теряете. Именно из-за переполнения я это деление и вынес наверх. Плюс поймался на частный случай 8000000 / 64 = 125000 "тю! Так тут целое и получается" :) Заработали оба варианта расчета с разными вариациями параметров. С excel совпадает. #if MB_BAUD_RATE > 19200 #define MB_OCR_T25 (F_CPU * (11.0 / MB_BAUD_RATE + 0.00075) / MB_TIMER_PRESCALER) #define MB_OCR_T45 (F_CPU * (11.0 / MB_BAUD_RATE + 0.00175) / MB_TIMER_PRESCALER) #else #define MB_OCR_T25 (F_CPU * 11 * 2.5 / MB_BAUD_RATE / MB_TIMER_PRESCALER) #define MB_OCR_T45 (F_CPU * 11 * 4.5 / MB_BAUD_RATE / MB_TIMER_PRESCALER) #endif volatile uint8_t ocr25 = (uint8_t)MB_OCR_T25; volatile uint8_t ocr45 = (uint8_t)MB_OCR_T45; А вариант проверки допустимых диапазонов препроцессором не прокатит? Препроцессору дробные числа никак не скормить? #define mb_ocr_test 255 #ifdef mb_ocr_test #if mb_ocr_test < MB_OCR_T25 || mb_ocr_test < MB_OCR_T45 #warning [MB_OCR_T25] è/èëè [MB_OCR_T45] âûõîäÿò çà ðàçðÿäíîñòü OCR-ðåãèñòðà. Ïðîâåðüòå íàñòðîéêè òàéìåðà. #endif #endif Error[Pe031]: expression must have integral type Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 27 февраля, 2015 Опубликовано 27 февраля, 2015 · Жалоба Препроцессору дробные числа никак не скормить? Никак. А вариант проверки допустимых диапазонов препроцессором не прокатит? Зачем именно препроцессором? Для этих дел существует assert_static(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 27 февраля, 2015 Опубликовано 27 февраля, 2015 (изменено) · Жалоба Никак. обычно для простоты душевной уходят от дробных вещей путём умножения на некую удобную константу, и в дальнейшем при вычислениях - делением на неё. удобные константы = те что дробны на величину байта. Но если "по взрослому" с делением, то не принципиально по большому счёту. в препроцессоре обычно можно сделать элементарные проверки на уровне иф-дефов и выводе прям не приличных сообщений на руском в случае не правильного сочетания звёзд и кода :) Изменено 27 февраля, 2015 пользователем kolobok0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться