![]() |
|
Модераторы: PILOT, ManiaK, Mazzi |
![]()
|
|
| Sardar, не из дома |
|
||||
|
Unregistered |
Есть микроконтроллер: DS80C320 - 80C52 без внутренней флеш памяти(80C32).
Задача сравнить два числа, если одно больше другого то действие N. Вопрос звучит по идиотски, но как сравнить, используя кривые инструкции 8051, два числа? Инструкций сравнить на больше/меньше чип не имеет, отнять одно число от другого дает чушь: *) 6 - 52 = -46 #11010010b - так должно быть *) 6 - 52 = 81 #01010001b - так считает микроконтроллер
Overflow бит в PSW устанавливается не понятно когда, по идее если от меньшего отнять большее, но в жизни похоже зависит от погоды на марсе...
Знаю что в аккумуляторе лежат правильные значения(вывожу также через COM порт на терминал). Подумал что чип глючит, проверил на другом то же самое. Задачку на 5 минут решаю уже вторые сутки =( |
||||
|
|||||
| shedon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1209 Регистрация: 17.1.2003 Где: Нижнiй Новгородъ Репутация: 6 Всего: 11 |
-------------------- Programming is like sex: One mistake and you have to support it your lifetime |
|||
|
||||
| bagira |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 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 |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
Всем огромное спасибо, все заработало. Только я не понял почему carry выставляется...
[флейм] Не нравятся мне 8051'ые =/, в PIC'e на мой взгляд инструкции более удобные и вообще сам контроллер удобней. [/флейм] -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| PILOT |
|
|||
|
производство ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 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. тогда выход за пределы будет эквивалентен установке флага не переполнения а переноса (заема). Переход от одной системы в другую осуществляется инвертированием самого старшего бита. Кстати можешь проверить, для закрепления. За сим откланиваюсь и баиньки СУВ. Добавлено @ 23:53
а AVR еще удобнее. Но тут от задачи зависит многое. Например для битовых операций, ооочень удобен 51-ый, кроме того умножение и деление. А для работы со звуком или с быстрой (но не очень) обработкой входных массивов данных, так тут AVR как нельзя кстати. PIC ооочень недорогой (правда 51-ый тоже). Каждой задаче свой контроллер. А иногда вообще лучше ПЛИС ничего нет СУВ. -------------------- тут могла быть Ваша реклама... |
|||
|
||||
| PILOT |
|
|||
|
производство ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2724 Регистрация: 4.4.2002 Где: москва Репутация: 20 Всего: 54 |
Вот тебе пример, я его не компилировал, но должен работать. И пояснения.
Эта программа читает восемь пар двухбайтных операндов из внешней памяти данных, складывает операнды побайтно с учетом флага переноса и посылает результаты также во внешнюю память. В программе, кроме уже встречавшейся нам директивы ORG, использованы директивы EQU, с помощью которых определяются имена констант, встречающихся далее в тексте. Этими константами являются значения старшего и младших байтов адреса областей внешней памяти, где хранятся операнды и результаты, количество циклов сложения. Старший байт адреса равен 0Fh и одинаков для всех областей, младший адрес области первых операндов начинается с 00h, вторых операндов - 10h, результата - 20h. Количество циклов равно 2байта*8операндов=16. Для сокращения числа команд внутри цикла предусмотрена одинаковая обработка первых байтов операндов, которые складываются без учета переноса, и вторых байтов, складываемых с учетом значения бита С. Единый цикл использует команду ADDC, но дополнительно привлекается флаг F0 из регистра PSW, изменяющий свое значение при каждом проходе. При F0==0 (обработка первых байтов) бит переноса обнуляется. Такой алгоритм применим только для 16-разрядных операндов. Для работы программы необходим счетчик, три указателя на области внешней памяти и флаг обнуления бита переноса. В качестве счетчика циклов используется регистр R2. Его содержимое декрементируется и проверяется командой DJNZ, которая организует цикл. В качестве указателей на ячейки-источники операндов используются регистры R0 и R1 банка 0. На текущую ячейку-приемник результата указывает регистр R0 банка 1 (ячейка 08h внутреннего ОЗУ), поэтому перед записью необходимо переключить текущий банк, а перед наращиванием указателей источников сделать это вновь. -------------------- тут могла быть Ваша реклама... |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
После своего последнего поста сел за мануал по 80C51 и все уяснил. Я думал что overflow устанавливается если результат операции не верен(переполнение...,так я от препода уяснил), оказывается OV устанавливается если результат сменил знак(позитивное->негативное и наоборот).
Сложение двух чисел, знаковое/без знаковое понятно, а вот реультат вычитания(subb) еще до конца не ясен.
В беззнаковой нотации бинарное число переводится в десятично следующим способом: (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 положить [offtop] Достал меня новый алгоритм отметки сообщений [/offtop] -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
![]()
|
| Правила форума "Микроконтроллеры (MCU) и микропроцессоры (MPU)" | |
|
|
На данный раздел помимо Правил форума распространяются текже следующие правила:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, PILOT, ManiaK, UniBomb, Mazzi. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Микроконтроллеры (MCU) и микропроцессоры (MPU) | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |