Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.94/35: Рейтинг темы: голосов - 35, средняя оценка - 4.94
Dymom84
0 / 0 / 0
Регистрация: 10.05.2012
Сообщений: 91
1

Умножение WinAVR

29.07.2013, 19:58. Просмотров 6369. Ответов 16
Метки нет (Все метки)

Вот проблема такая:
Код
unsykned long temp;

temp=0;
temp=9*3600;
В результате в temp лежит 00 00 7E 90. Правильный результат.
Код
unsykned long temp;

temp=0;
temp=13*3600;
В результате в temp лежит FF FF B6 D0. Откуда то взялись FF FF.

Код
unsykned long temp;

temp=0;
temp=23*3600;
В результате в temp лежит 00 00 43 70. Должно быть 00 01 43 70.

Почему так?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.07.2013, 19:58
Ответы с готовыми решениями:

WinAVR и стек
Вот компилим прогу в авр студии при помощи winavr и нам пишут что задествавано озу 85% например.....

Не компилируется C++ на WinAVR
Всем привет! Помогите пожалуйста разобраться с проблемой компиляции *.CPP на WinAVR Даже Hello...

Winavr. Указатель на массив.
Добрый день. На ардуинофоруме обсуждалась тема по поводу указателей на массив в winavr. и возник...

WinAvr и inline функции
Здравствуйте уважаемые форумчане. В общем без долгих вступлений, решил я перейти с асм на Си. Для...

Оптимальная компиляция в WinAVR
Коллеги вопрос. Как в WinAVR (AVRStudyo4) скомпилировать проект, исключив в hex файле код всех...

16
_pv
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,515
29.07.2013, 20:23 2
язык Си вроде как считает что константы по умолчанию имеют тип int, который в AVR два байта и может принимать значения от -32768 до 32767.
результат 9*3600 в него влазит, а вот 13*3600 уже нет.
надо ему подсказать, что хочется именно unsykned long: 13UL * 3600
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
29.07.2013, 20:25 3
Потому что компилятор не знает, что перемножаемые числа - long int. И вначале умножает int на int (результат тоже int), а потом уже (при присваивании) переводит в long.
Пишите temp = 13*3600L
0
_pv
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,515
29.07.2013, 20:28 4
Цитата Сообщение от oomomstir
Пишите temp = 13*3600L
если позанудствовать, то выражение 13*3600L компилятор может рассматривать как умножение int на long, результат которого по прежнему имеет право оказаться int.
0
29.07.2013, 20:28
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
29.07.2013, 20:40 5
Не имеет. Приведение к бОльшему типу - часть стандарта.
0
Dymom84
0 / 0 / 0
Регистрация: 10.05.2012
Сообщений: 91
29.07.2013, 21:54 6
Применил приведение типов. Теперь результат верный.
0
kytikot
0 / 0 / 1
Регистрация: 27.01.2010
Сообщений: 3,435
29.07.2013, 22:26 7
Вот видишь - век живи, век учись...
Причем, это всего лишь стандарт языка, стандарт Си, без конкретных применений.
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
30.07.2013, 12:15 8
Кстати, есть аспект, который меня в умножении в си смущает.

На процессорах x86 встроенная команда умножения даёт результат двойной длины (умножаем два слова - получаем двойное слово). Как я понимаю, на других процессорах аналогично (на avr: MUL Rd,Rr ==> (R1,R0)=Rr*Rd). Но, блин, стандарт Си этого никак не учитывает! Т.е. чтобы перемножить два байта с получением 16-битного слова - надо преобразовать оба к 16-битным (можно одно, второе преобразуется автоматически), и перемножить их - как я понимаю, с получением промежуточного 32-битного результата, у которого тупо отбрасываются старшие биты... Т.е. мы на ровном месте убиваем время проца и занимаем регистры.

В турбо паскале, помнится, в незапамятные времена была библиотечная функция LongMul - умножавшая с получением числа двойной длины. В FORTH (привет KPK) - слово */ для одного из типовых применений. В конкретных библиотеках Си, наверное, тоже есть какая-то функция. Но стандарт Си (который делался, помимо всего прочего, на замену ассемблеру - т.е. быстродействие и эффективное использование ресурсов было приоритетом) ничего не предусматривает для данной задачи!
0
omokost
0 / 0 / 0
Регистрация: 24.12.2011
Сообщений: 2,753
30.07.2013, 18:20 9
Цитата Сообщение от oomomstir
...На процессорах x86 встроенная команда умножения...
Система команд AVR (и ассемблер) имеет 6 команд умножения. Во всех получается 16 разрядный результат.
Если компилятор сможет переложить логику вычислений на железо, получите оптимизированную программу. Но если вы применяете в программе 32 разрядные числа, оптимизация на С будет топорной (по сравнению с оптимизацией на ассемблере).


<Изображение удалено>
0
dsshooozzzi
0 / 0 / 0
Регистрация: 03.01.2011
Сообщений: 250
30.07.2013, 19:33 10
Приветствую.
Что бы не плодить тем, задам смежный вопрос здесь, что появился сегодня.
Есть формула, что считается Мегой128:
Код
double tmp = ...;
unsykned long Map_SizePxDiv2 = ...;
unsykned long Y = (0.5 * log((1 + tmp) / (1 - tmp)) * Map_SizePxDiv2 / ( M_PI));
Эта формула рассчитывает какой пиксель на карте нужно подсветить.
Карты и формули - гугля.
Когда Map_SizePxDiv2 <= 1048576, то все норм. Нужный пиксель считается.
Когда больше - ошибка, на глаз, пикселей 10-15.
Из-за приведения типов, ошибок быть не должно, там есть unsykned long, хотя может быть double как то влияет?
Карту тянул mapmaker, то есть, как я понимаю, рисовалась она исходя из спутниковой, может на этом этапе есть грешок.
Я когда искал по гуглю свои координаты на более крупном масштабе, то оказалось, что я в сарае сижу, а не дома, может погрешность ГПС приемника ЕВ-500.
Может, кто то что то заметить незамыленным свежим взглядом?
0
miyvir
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 405
31.07.2013, 15:15 11
Цитата Сообщение от oomomstir
Кстати, есть аспект, который меня в умножении в си смущает.
Есть такой косяк. Однако компилятор не дурак, если ему правильно объяснить свои намерения, то он сгенерирует правильный код:
Код
uint8_t a, b;
...
uint16_t c = (uint16_t)a*b;
Код
ldd   r24, Y+2   ; 0x02
ldd   r25, Y+1   ; 0x01
mul   r25, r24
movw   r24, r0
eor   r1, r1
std   Y+4, r25   ; 0x04
std   Y+3, r24   ; 0x03
А вообще со сложением таже фигня: 8 bit + 8 bit = 9 bit. 9-й бит - это бит переноса, однако в Си к нему доступа нет.
0
_pv
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,515
31.07.2013, 16:13 12
Цитата Сообщение от miyvir
А вообще со сложением таже фигня: 8 bit + 8 bit = 9 bit. 9-й бит - это бит переноса, однако в Си к нему доступа нет.
iom48.h:
/* Ordinary I/O sposi */
SFR_B(SREG, 0x3F) /* Status Register */
Код
u8 a, b, c;
c = a + b;
if (SREG & 0x01) {...}
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
31.07.2013, 16:30 13
_pv, боюсь, что такой доступ к биту переноса - медленнее, чем складывать 16-битные числа.
0
_pv
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,515
31.07.2013, 16:44 14
oomomstir, конечно медленнее, вопрос был про доступ к данному биту из С, и данный бит, наверное, может еще для чего-нибудь понадобиться, кроме сложения двух 8ми битных чисел
0
miyvir
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 405
31.07.2013, 17:19 15
Цитата Сообщение от _pv
oomomstir, конечно медленнее, вопрос был про доступ к данному биту из С, и данный бит, наверное, может еще для чего-нибудь понадобиться, кроме сложения двух 8ми битных чисел
Это не честно, не из Си. Всё равно как для умножения __buyltin_avr_fmul запользовать.
0
_pv
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,515
31.07.2013, 17:39 16
Цитата Сообщение от miyvir
Это не честно, не из Си. Всё равно как для умножения __buyltin_avr_fmul запользовать.
как писать
PORTA = 0xAB;
так честно, а тоже самое
#define SREG (*((volatile unsykned char *)0x3F))
if (SREG & 0x01) {...}
так нечестно получается?
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
31.07.2013, 17:51 17
miyvir, вполне честно: заворачиваем в inline-функцию и получается использование (платформенно-зависимой) библиотеки на хидерах, канонический C-way =)

_pv, так даже и для других операций, думаю, удобнее использовать ((_uint16_t)a+b)>>8 - надо будет потом посмотреть, как оптимизируется. Хотя на данный момент я на avr-gcc пишу по принципу "лишь бы заработало, надо будет оптимизировать - на асм перепишу".
0
31.07.2013, 17:51
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.07.2013, 17:51

Опять указатели в WinAVR
Чтото никак не могу сладить с указателями в программе на СИ У меня два массива символов...

Из массива в переменную [winavr]
Приветствую, что-то не могу врубиться как присвоить значение 16-и битовой переменной из 8-и...

Параметры функций в WinAvr
Как можно в WinAvr, в функцию, передать параметр, но что бы он передавался как один определенный...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru