Модераторы: PILOT, ManiaK, Mazzi
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сравнить два числа: больше/меньше, не так просто как кажется 
:(
    Опции темы
Sardar, не из дома
Дата 25.3.2004, 13:53 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Есть микроконтроллер: DS80C320 - 80C52 без внутренней флеш памяти(80C32).
Задача сравнить два числа, если одно больше другого то действие N.
Вопрос звучит по идиотски, но как сравнить, используя кривые инструкции 8051, два числа?
Инструкций сравнить на больше/меньше чип не имеет, отнять одно число от другого дает чушь:
*) 6 - 52 = -46 #11010010b - так должно быть
*) 6 - 52 = 81 #01010001b - так считает микроконтроллер
Код

    subb  а,#0F0h
    anl   a,#7Fh; достанем последний(знаковый) бит
    jnz   start; если число было меньше то назад
   ;иначе оповестить о трабле


Overflow бит в PSW устанавливается не понятно когда, по идее если от меньшего отнять большее, но в жизни похоже зависит от погоды на марсе...
Код

       clr    OV
       subb   a,#0F0h; если число менше,
       jb     OV,start; то все ОК
      ;иначе бей во все колокола  


Знаю что в аккумуляторе лежат правильные значения(вывожу также через COM порт на терминал).
Подумал что чип глючит, проверил на другом то же самое. Задачку на 5 минут решаю уже вторые сутки =(
  Вверх
shedon
Дата 25.3.2004, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1209
Регистрация: 17.1.2003
Где: Нижнiй Новгородъ

Репутация: 6
Всего: 11



Код

CLR C
subb  а, #034h
JNC start; если 34h меньше аккамулятора то переход на start



--------------------
Programming is like sex: One mistake and you have to support it your lifetime
PM MAIL WWW ICQ   Вверх
bagira
Дата 25.3.2004, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2858
Регистрация: 25.10.2003
Где: в тайге Уральских гор

Репутация: 1
Всего: 123



Когда одно число вычитается из другого, то флаг С устанавливается в том случае, когда первое число меньше второго. Т.е. применяются здесь либо JC либо JNC. А другие команды (типа JZ, JNZ, JB и т.д.) применять в этом случае - смысла нет.

Еще есть одна хитрая команда: CJNE A, число, метка, например CJNE A,#40H,L1 (или CJNE A,B,L1 и т.д.) - переход на метку, если аккумулятор не равен второму числу. Но особенность этой команды - тоже флаг С устанавливается, если первое число окажется меньше второго. И ее тоже можно применить для сравнения двух чисел.




--------------------
Сегодня ты не бродил, не искал, не любил - можно сказать - и не жил...
Ф.Х. Дагларджа (Турция)
http://zveriolginovour.ru/
https://vmeste.yandex.ru/zveriolginovour 
PM MAIL WWW ICQ   Вверх
Sardar
Дата 25.3.2004, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 2
Всего: 317



Всем огромное спасибо, все заработало. Только я не понял почему carry выставляется...

[флейм]
Не нравятся мне 8051'ые =/, в PIC'e на мой взгляд инструкции более удобные и вообще сам контроллер удобней.
[/флейм]


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
PILOT
Дата 25.3.2004, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


производство
****


Профиль
Группа: Модератор
Сообщений: 2724
Регистрация: 4.4.2002
Где: москва

Репутация: 20
Всего: 54



А не понял ты потому что нужно тебе рассказать как представляются числа в контроллере.

А их два основных варианта - положительные и отрицательные. и представления есть signed (знаковое) и unsigned (беззнаковое).
Итак сначала о простом - беззнаковом.
Информация хранится в байтах, а значит мы можем максимум что сохранить так это число от 0 до 255, т.е. от 00h до FFh.
это и понятно - это же байт = 8бит, а 2 в степени 8 = 256, т.е. 256 разничных чисел: от 0..255 как раз их 256.
Но что будет если мы начнем вычитать (например):
23-24=?
вот тут, то и происходит самое интересное.
ответ очевиден: -1
но мы то работаем с числом от 0 до 255, -1 тут и не пахнет.
что делать?
Итак попробуем найти такой ответ чтобы проверив вычисление с помощью сложения получить снова 23.
Но для начала проверим что -1+1=0.
Т.е. найдем такое число чтобы прибавив к нему единицу получить 0.
Ответ очевиден, это число - FF или 255.
Почему? потому что FFh+01h это будет 100h. Но мы не можем учитывать стуршую единицу, т.к. она вышла за пределы нашего байта. поэтому результат будет именно 00h а старшая единица уйдет куда? правильно во флаг переноса.
Теперь вспоминаем про 23-24=-1:
тут все уже совсем просто: если 255 это -1, то 255+24=FFh+18h=17h=23.
Значит при этом вычитании (23-24) мы тоже выходим за границу байта. И тоже не можем уместить получившееся число в байт а значит нам ничего не остается как представить его в виде FFh и заполнить флаг переноса (в данном случае его лучше назвать флагом заема).
Естественно люди понимали что иногда лучше работать и с отрицательными числами и придумали следуещее:
давайте, говорят люди, мы будем байт понимать не как число (положительное) от 00 до FFh а как знаковое число:
от -128 до +127.
На том и порешили.
Итак в знаковом представлении число выглядит так:
(s)xxx xxxx BIN
где S-знаковый бит, если он 1 то число отрицательное, если он 0 то положительное
где X-значащие биты.
и с учетом этого видно что от 00h до 7Fh мы находимся и растем в положительной зоне.
А с отрицательной наоборот: с 80h до FFh - возрастают отрицательные числа (осторожно! -30 меньше -2, т.е. рост от большего модуля к меньшему).
теперь видно почему возникают переносы (заемы).
Но есть еще переполнение, а вот оно возникает тогда, когда мы переходим в результатах вычислений за границы знаковых чисел, например:
-120-30=-150
такое число мы не можем представить в базисе -128...+127 поэтому результатом будут младший байт и флаг переполнения.
Нукоторым такое представление не нравится и они условились считать так:
пусть 00h это будет -128, 80h это будет 0, а FFh это будет 127. тогда выход за пределы будет эквивалентен установке флага не переполнения а переноса (заема).
Переход от одной системы в другую осуществляется инвертированием самого старшего бита. Кстати можешь проверить, для закрепления.
За сим откланиваюсь и баиньки smile.gif

СУВ.








Добавлено @ 23:53
Цитата(Sardar @ 25.3.2004, 17:54)
[флейм]
Не нравятся мне 8051'ые =/, в PIC'e на мой взгляд инструкции более удобные и вообще сам контроллер удобней.
[/флейм]

а AVR еще удобнее.
Но тут от задачи зависит многое.
Например для битовых операций, ооочень удобен 51-ый, кроме того умножение и деление.
А для работы со звуком или с быстрой (но не очень) обработкой входных массивов данных, так тут AVR как нельзя кстати.
PIC ооочень недорогой (правда 51-ый тоже).

Каждой задаче свой контроллер.
А иногда вообще лучше ПЛИС ничего нет smile.gif уж не говоря о DSP...

СУВ.


--------------------
тут могла быть Ваша реклама...
PM MAIL WWW ICQ   Вверх
PILOT
Дата 25.3.2004, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


производство
****


Профиль
Группа: Модератор
Сообщений: 2724
Регистрация: 4.4.2002
Где: москва

Репутация: 20
Всего: 54



Вот тебе пример, я его не компилировал, но должен работать. И пояснения.
Код

;----------------------- программа demo4.asm -------------------------------
;------------------------ раздел объявлений --------------------------------
ADDRH    EQU       0Fh;                   Старший байт адреса внешней памяти
ADDR1L   EQU       00h;            Младший байт адреса 1-байта 1-го операнда
ADDR2L   EQU       10h;            Младший байт адреса 1-байта 2-го операнда
ADDR3L   EQU       20h;               Младший байт адреса 1-байта результата
NCIRCLE  EQU       16        
;-------------------------- исполняемая часть ------------------------------
ORG      00H;                                Директива размещения программы
         Mov       P2,#ADDRH; Через Р2 выдается ст.байт адреса внеш. памяти                                                          
         Mov       R0,#ADDR1L;                      В R0 - адрес 1-операнда
         Mov       R1,#ADDR2L;                      В R1 - адрес 2-операнда
         Mov       08h,#ADDR3L;              В ячейку 08 - адрес результата
         Mov       R2,#NCIRCLE;            В R2 - счетчик циклов = 2*Nчисел
LP1:     JB        0D5h,LP2;      При флаге F0=1 флаг переноса не очищается
         Clr       C
LP2:     MovX      A,@R0;                           Чтение байта 1-операнда
         Mov       R3,A;                               и пересылка его в R3
         Movx      A,@R1;                           Чтение байта 2-операнда
         AddC      A,R3;            Сложение байтов с учетом флага переноса
         SetB      0D3h;                             Переключение на банк 1
         Movx      @R0,A;         Запись байта результата во внешнюю память
         Clr       0D3h;                             Переключение на банк 0
         Inc       R0;   Указатель 1-операнда переводится на следующий байт
         Inc       R1;   Указатель 2-операнда переводится на следующий байт
         Inc       08h;  Указатель результата переводится на следующий байт
         Cpl       0D5h;          Флаг F0 управляет очисткой флага переноса
         DJNZ      R2,LP1;       зацикливание, если есть еще байты операнды
         SJmp      $
         End

Эта программа читает восемь пар двухбайтных операндов из внешней памяти данных, складывает операнды побайтно с учетом флага переноса и посылает результаты также во внешнюю память. В программе, кроме уже встречавшейся нам директивы ORG, использованы директивы EQU, с помощью которых определяются имена констант, встречающихся далее в тексте. Этими константами являются значения старшего и младших байтов адреса областей внешней памяти, где хранятся операнды и результаты, количество циклов сложения. Старший байт адреса равен 0Fh и одинаков для всех областей, младший адрес области первых операндов начинается с 00h, вторых операндов - 10h, результата - 20h. Количество циклов равно 2байта*8операндов=16.
Для сокращения числа команд внутри цикла предусмотрена одинаковая обработка первых байтов операндов, которые складываются без учета переноса, и вторых байтов, складываемых с учетом значения бита С. Единый цикл использует команду ADDC, но дополнительно привлекается флаг F0 из регистра PSW, изменяющий свое значение при каждом проходе. При F0==0 (обработка первых байтов) бит переноса обнуляется. Такой алгоритм применим только для 16-разрядных операндов. Для работы программы необходим счетчик, три указателя на области внешней памяти и флаг обнуления бита переноса. В качестве счетчика циклов используется регистр R2. Его содержимое декрементируется и проверяется командой DJNZ, которая организует цикл. В качестве указателей на ячейки-источники операндов используются регистры R0 и R1 банка 0. На текущую ячейку-приемник результата указывает регистр R0 банка 1 (ячейка 08h внутреннего ОЗУ), поэтому перед записью необходимо переключить текущий банк, а перед наращиванием указателей источников сделать это вновь.


--------------------
тут могла быть Ваша реклама...
PM MAIL WWW ICQ   Вверх
Sardar
Дата 1.4.2004, 01:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 2
Всего: 317



После своего последнего поста сел за мануал по 80C51 и все уяснил. Я думал что overflow устанавливается если результат операции не верен(переполнение...,так я от препода уяснил), оказывается OV устанавливается если результат сменил знак(позитивное->негативное и наоборот).
Сложение двух чисел, знаковое/без знаковое понятно, а вот реультат вычитания(subb) еще до конца не ясен.
Цитата
а как знаковое число: от -128 до +127.

В беззнаковой нотации бинарное число переводится в десятично следующим способом: (2^n*bn) + b0 (степени двойки по позиции), где n это разрядность числа, а bn соответствующий бит двоичного числа.
В знаковой нотации последний бит равен -(2^n*bn), т.е. в 8 битном числе получаем в последнем(знаковом) бите -128. Отсюда видно что -128 = 10000000b, а -3 = 11111101(-128+64+32+16+8+4+0+1). Тогда найдем простой способ обратить позитивное число в негативное: 3 = 00000011, -3 = 11111101 => CPL(3)+1, где CPL это операция NOT(invert).
Из негативного получить позитивное можне этим же алгоритмом: -N = CPL(N)+1 => 3=CPL(11111101)+1 = 00000010 + 1

PILOTIK - не плохо бы твою статью в FAQ положить smile.gif

[offtop]
Достал меня новый алгоритм отметки сообщений bored.gif, пока сам не зашел в топик не видел новых постов.
[/offtop]


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Микроконтроллеры (MCU) и микропроцессоры (MPU)"
PILOT ManiaK
UniBomb Mazzi

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


  • Прежде чем создать тему воспользуйтесь поиском или посмотрите в faq. Возможно на форуме уже есть ответ на ваш или близкий к вашему вопрос.
  • В заголовке темы в квадратных скобках обозначьте используемое семейство микроконтроллера: [avr],[pic],[arm].
  • При создании темы с вопросом указывайте участок кода с ошибкой, версию компилятора, схемы подключения, fuse биты и прочие данные, которые помогут найти правильный ответ. Для форматирования текста программ используйте кнопку код.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Для флуда, просьб выполнить задание, поиска партнёров или исполнителей существуют свои разделы.
  • Если вы заметили несовместимое с правилами сообщение, то можете уведомить об этом модератора раздела нажав кнопку Репорт у соответствующего сообщения.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, PILOT, ManiaK, UniBomb, Mazzi.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Микроконтроллеры (MCU) и микропроцессоры (MPU) | Следующая тема »


 




[ Время генерации скрипта: 0.0576 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.