Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы
Непрочитано 30.01.2006, 10:20  
KiberBOSS
Гость
 
Сообщений: n/a
По умолчанию Проблема деления целых чисел с заданной точностью на AVR

Ребята, если не сложно помогите мне, пожалуйста,реализовать деление 16 битных целых безнаковых чисел до сотой доли (только на ASM для AVR Studio). Весьма срочно, горит проект.

Скомпилировал пример (деление 8 битных безнаковых целых чисел) имеющий в на CD и пришел к выводу, что его использовать и брать за основу нельзя.
Почему ???
Начнем с простого:
A = 56 (десят.)
B = 42 (десят.)
A/B =1.33 (десят.)
------------------------------
Моя реализованная программа:
(Код деления беззнаковых целых чисел взят из другого источника)

.NOLIST
.INCLUDE "m8def.inc"
.DEVICE ATmega8
.LIST

.def drem8u=r15 ;остаток
.def dres8u =r16 ;результат
.def dd8u =r16 ;делимое
.def dv8u =r17 ;делитель
.def dcnt8u =r18 ;счетчик цикла
//----------------------------------------------------
.DSEG
.ORG 0x60

//----------------------------------------------------
.ESEG
.ORG 0x00

//----------------------------------------------------
.CSEG
.ORG 0x00
//----------------------------------------------------
rjmp RESET ;0
rjmp 0 ;1
rjmp 0 ;2
rjmp 0 ;3
rjmp 0 ;4
rjmp 0 ;5
rjmp 0 ;6
rjmp 0 ;7
rjmp 0 ;8
rjmp 0 ;9
rjmp 0 ;10
rjmp 0 ;11
rjmp 0 ;12
rjmp 0 ;13
rjmp 0 ;14
rjmp 0 ;15
rjmp 0 ;16
rjmp 0 ;17
rjmp 0 ;18
//----------------------------------------------------
RESET: //--------------------------
// Setup STACK
ldi R16,high(RAMEND)
out SPH,R16
ldi R16,low(RAMEND)
out SPL,R16
//--------------------------
ldi dd8u,$38 ; 56 (десят.)
ldi dv8u,$2A ; 42 (десят.)
rcall div8u_c
nop
nop
nop
EndPrg: rjmp EndPrg
//----------------------------------------------------

;*****
div8u_c: sub drem8u,drem8u ;очистить остаток и перенос
ldi dcnt8u,9 ;инит.счетчик цикла
d8u_1: rol dd8u ;делимое/делитель сдвинуть влево
dec dcnt8u ;уменьш.счетчик на 1
brne d8u_2 ;переход если не ноль
ret
d8u_2: rol drem8u ;остаток сдвинуть влево
sub drem8u,dv8u ;остаток= остаток - делитель
brcc d8u_3 ;если рез-т ‹ 0
add drem8u,dv8u ;восст.остаток
clc ; сброс переноса для форм.рез-та
rjmp d8u_1 ;иначе
d8u_3: sec ;уст.перенос для форм.рез-та
rjmp d8u_1 ;вернуться назад
//----------------------------------------------------
И что же я получил ???
В регистре R16 = 1 (целое) - верно.
В регистре R15 = 0xE (вещественное) - НЕВЕРНО (!!!!?!?!?)
Попытался считать условно как десятичное, то в этом случае получается 14 (десят), что тоже НЕВЕРНО.

Попытался прикинуть что первый разряд двоичный после запятой - это двойка в минус первой степени, второй разряд двоичный после запятой - двойка в минус второй степени и т.д.

Ниже приведена конвертилка для ПК числе в вещественый формат:

#include‹stdio.h›
#include‹conio.h›
#include‹math.h›
//---------------------------------------------------
double ConvertByteToFloat(unsigned char A);
//---------------------------------------------------
void main(void)
{ clrscr();
int A=0xE; // Input hex number for convert to float number
printf("(hex)-› 0x%X , (dec)-› %d , %f",A,A,ConvertByteToFloat(A));
getch();
}
//---------------------------------------------------
double ConvertByteToFloat(unsigned char A)
{ double X=0;
if((A&0x1)==0x1) X=X+pow(2,-1);
if((A&0x2)==0x2) X=X+pow(2,-2);
if((A&0x4)==0x4) X=X+pow(2,-3);
if((A&0x==0x X=X+pow(2,-4);
if((A&0x10)==0x10) X=X+pow(2,-5);
if((A&0x20)==0x20) X=X+pow(2,-6);
if((A&0x40)==0x40) X=X+pow(2,-7);
if((A&0x80)==0x80) X=X+pow(2,-;
return(X);
}
//---------------------------------------------------

Пробовал изменить порядок преобразования - все никак.
Заранее благодарю.

Мой e-mail: DarkAngelDeath19@mail.ru
Реклама:
 
Непрочитано 30.01.2006, 14:12  
Паханчик
Гость
 
Сообщений: n/a
По умолчанию Проблема деления целых чисел с заданной точностью на AVR

››Начнем с простого:
››A = 56 (десят.)
››B = 42 (десят.)
››A/B =1.33 (десят.)
››......
››И что же я получил ???
››В регистре R16 = 1 (целое) - верно.
››В регистре R15 = 0xE (вещественное) - НЕВЕРНО!!!!?!?!?)
››Попытался считать условно как десятичное, то в этом ››случае получается 14 (десят), что тоже НЕВЕРНО.

Почему неверно-то? если ты делишь 56 на 42, то результат деления 1 и в остатке 14 (56-42=14), т.е. 0x0E. Т.е. - всё правильно. Что тебя смущает?
 
Непрочитано 30.01.2006, 15:24  
impuls-v
Частый гость
 
Регистрация: 18.01.2005
Сообщений: 33
Сказал спасибо: 0
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
impuls-v на пути к лучшему
По умолчанию

В журнале схемотехника в цикле статей "Микроконторллеры это просто" есть пример реализации такой и подобных вещей.
impuls-v вне форума  
Непрочитано 30.01.2006, 17:11  
KiberBOSS
Гость
 
Сообщений: n/a
По умолчанию

Может быть и совсем запутался. Меня смущает число 14 (десят.).
А как преобразовать в вещест. значение для самопроверки верности работы кода ??? Нужно получить 33 (тридцать три сотых !!!!).
 
Непрочитано 30.01.2006, 18:59  
Alex_F
Прохожий
 
Регистрация: 30.01.2006
Сообщений: 2
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Alex_F на пути к лучшему
По умолчанию

Сообщение от KiberBOSS
Может быть и совсем запутался. Меня смущает число 14 (десят.).
А как преобразовать в вещест. значение для самопроверки верности работы кода ??? Нужно получить 33 (тридцать три сотых !!!!).
Меня совершенно не смущает. Чтобы получить остаток в формате плавающей запятой, нужно сделать следующее:

Взять ваш остаток (14).
Умножить его на 100 (если вам нужно две цифры после запятой) 14*100 = 1400.
Разделить полученное число на ваш делитель 42

1400 / 42 = 33 (и три в остатке).
Alex_F вне форума  
Непрочитано 30.01.2006, 19:07  
Alex_F
Прохожий
 
Регистрация: 30.01.2006
Сообщений: 2
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Alex_F на пути к лучшему
По умолчанию

Меня совершенно не смущает.
Вам дается остаток в масштабе вашего делителя - 42.
Чтобы перевести в десятичный вид, нужно сделать следующее.

Взять ваш остаток (14).
Умножить его на 100 (если вам нужно две цифры после запятой) 14*100 = 1400.
Разделить полученное число на ваш делитель 42

1400 / 42 = 33 (и три в остатке).
Alex_F вне форума  
Непрочитано 31.01.2006, 00:21  
nml
Супер-модератор
 
Аватар для nml
 
Регистрация: 13.03.2004
Адрес: Minsk
Сообщений: 2,378
Сказал спасибо: 1,946
Сказали Спасибо 1,327 раз(а) в 578 сообщении(ях)
nml на пути к лучшему
По умолчанию

Почему неправильно? Возьмите любой калькулятор. И посчитайте 45 div 42 и 56 mod 42
nml вне форума  
Непрочитано 31.01.2006, 19:21  
KiberBOSS
Гость
 
Сообщений: n/a
По умолчанию

Друзья, спасибо большое. Теперь все прояснилось.
Считаю тему закрытой.
Еще раз спасибо.
 
Непрочитано 16.02.2006, 16:35  
KiberBOSS
Гость
 
Сообщений: n/a
По умолчанию

Ребята снова поднимаю этот вопрос.

То что выше было сказано другими программистами - все верно. Дело в том, что снова застрял, когда обнаружилась особая ситуация,например, пусть число A=1956 (dec), C=3399 (dec). При делении С/A должно получиться 1.73 (dec), а получилось 1.08 (dec). Ошибку понял, но не знаю как исправить. Помогите доделать фрагмент кода деления 2 чисел.

Ниже прилагаю свой исходник - этот код желательно подкорректировать, чтобы правильно работал, если по каким-то соображениям слишком сложно, можно исправить и основную функцию деления :

Cals_Coeff_1:
ldi R31,$00
ldi R30,$60
;//----------------------
ldd dd16uH,Z+5 ; C_curr - high byte
ldd dd16uL,Z+4 ; C_curr - low byte
ldd dv16uH,Z+1 ; A_curr - high byte
ldd dv16uL,Z+0 ; A_curr - low byte
rcall div16u
;//----------------------
std Z+48,R16 ; Save (Coeff_1 - byte 1 - целое)
;//----------------------
mov R20,R14
ldi R21,$64 ; decimal 100
mul R21,R20
movw R20,R0
;//----------------------
mov dd16uH,R21
mov dd16uL,R20
ldd dv16uH,Z+1 ; A_curr - high byte
ldd dv16uL,Z+0 ; A_curr - low byte
rcall div16u
;//----------------------
std Z+49,R16 ; Save (Coeff_1 - byte 2-вещ.)
ret
;----------------------------------------------

Ниже прилагается основная функция деления целых беззнаковых чисел 16 бит:
;// Divide Unsigned Number (WORD - 16 bit)

.def drem16uL=R14 ;
.def drem16uH=R15
.def dres16uL=R16
.def dres16uH=R17

.def dd16uL =R16
.def dd16uH =R17
.def dv16uL =R18
.def dv16uH =R19

.def dcnt16u =R20

div16u: clr drem16uL
sub drem16uH,drem16uH
ldi dcnt16u,17
d16u_1: rol dd16uL
rol dd16uH
dec dcnt16u
brne d16u_2
ret
d16u_2: rol drem16uL
rol drem16uH
sub drem16uL,dv16uL
sbc drem16uH,dv16uH
brcc d16u_3
add drem16uL,dv16uL
adc drem16uH,dv16uH
clc
rjmp d16u_1
d16u_3: sec
rjmp d16u_1
;//----------------------------------------------------
 
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Измерение перемещения каретки с точностью 0,1 мм VadimPlotnikov Измерительное оборудование 29 14.03.2013 23:33
Подпрограммы деления (32/32) для AVR, PIC и 51 karuzus Микроконтроллеры, АЦП, память и т.д 5 21.03.2008 09:52
Поддержание заданной температуры внутри блока kHz Источники питания и свет 1 10.12.2005 15:33
Сложение целых чисел большой разрядности на PIC Алексей Микроконтроллеры, АЦП, память и т.д 1 22.09.2004 02:41


Часовой пояс GMT +4, время: 13:09.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot